簡體   English   中英

如何向AnchorPane添加3D表面

[英]How can I add 3D surface to the AnchorPane

如何將3D曲面添加到view.fxml ,Scene Builder面板上沒有“曲面”之類的“東西”。 我的場景構建器層次結構如下所示:

等級制度

和ss應用-就像我們可以看到在左上角有東西一樣,表面應該在中間。 在此處輸入圖片說明

我想先添加一些3D表面樣本:我的控制器代碼:

    package sample.packet3D;

import org.fxyz.cameras.CameraTransformer;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.fxml.FXML;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.layout.AnchorPane;


public class Window3DController {

    @FXML
    private AnchorPane anchorPane;
    @FXML
    private Group group;

    private Window3DBuilder window3dBuilder;
    private PerspectiveCamera perspectiveCamera;



    @FXML
    public void initialize() {
        perspectiveCamera = new PerspectiveCamera(true);

        window3dBuilder = new Window3DBuilder( group, perspectiveCamera );
        window3dBuilder.createScene();



        group.sceneProperty().addListener(new InvalidationListener() {

            @Override
            public void invalidated(Observable observable) {
                group.getScene().setCamera(perspectiveCamera);
                group.sceneProperty().removeListener(this);
            }
        });
    }
}

邏輯類:

   package sample.packet3D;


import org.fxyz.cameras.CameraTransformer;
import org.fxyz.shapes.primitives.SurfacePlotMesh;

import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Rotate;

public class Window3DBuilder {

    private Group group;
    private SurfacePlotMesh surface;
    private PerspectiveCamera perspectiveCamera;
    private CameraTransformer cameraTransformer;
    private PointLight light;

    public Window3DBuilder( Group group, PerspectiveCamera perspectiveCamera ) {
        this.group = group;
        this.perspectiveCamera = perspectiveCamera;
        cameraTransformer = new CameraTransformer();
    }

    public void createScene() {

        createSurface();
        createLight(); 
        group.getChildren().addAll(surface);

        cameraTransformer.setTranslate(0, 0, 0);
        cameraTransformer.getChildren().addAll(perspectiveCamera);

        perspectiveCamera.setNearClip(0.1);
        perspectiveCamera.setFarClip(100000.0);
        perspectiveCamera.setTranslateX((group.getBoundsInLocal().getMaxX() + group.getBoundsInLocal().getMinX()) / 2d);
        perspectiveCamera.setTranslateY((group.getBoundsInLocal().getMaxY() + group.getBoundsInLocal().getMinY()) / 2d);
        double max = Math.max(group.getBoundsInLocal().getWidth(), group.getBoundsInLocal().getHeight());
        perspectiveCamera.setTranslateZ(-2 * max);

    }

    public void createLight() {
        light = new PointLight(Color.WHITE);
        cameraTransformer.getChildren().add(light);
        light.setTranslateX(perspectiveCamera.getTranslateX());
        light.setTranslateY(perspectiveCamera.getTranslateY());
        light.setTranslateZ(perspectiveCamera.getTranslateZ());
    }

    private void createSurface() {
        surface = new SurfacePlotMesh(
                p-> Math.sin(p.magnitude() + 1e-10) / (p.magnitude() + 1e-10),
                20, 20, 100, 100, 4);
        surface.setCullFace(CullFace.NONE);
        surface.setTextureModeVertices3D(1530, p -> p.magnitude());
        surface.getTransforms().addAll(new Rotate(200, Rotate.X_AXIS), new Rotate(-20, Rotate.Y_AXIS));
    }



}

並查看:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.effect.*?>
<?import javafx.scene.canvas.*?>
<?import javafx.scene.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.packet3D.Window3DController">
   <children>
      <Group fx:id="group">
         <effect>
            <Lighting>
               <bumpInput>
                  <Shadow />
               </bumpInput>
               <light>
                  <Light.Distant />
               </light>
            </Lighting>
         </effect>
      </Group>
      <PerspectiveCamera fx:id="perspectiveCamera" visible="false" />
   </children>
</AnchorPane>

我究竟做錯了什么 ? 有人可以幫我嗎? 這也是我按下按鈕進入的窗口之一。

@FXML
    public void moveTo3DScene(ActionEvent event) throws IOException {
        Stage stage3D = (Stage) ((Node) event.getSource()).getScene().getWindow();
        Parent parent3D = FXMLLoader.load(getClass().getResource("packet3D/Window3DSceneView.fxml"));
        stage3D.setTitle("Animation 3D");
        stage3D.setScene(new Scene(parent3D, 1200, 800));
        stage3D.show();

    }

在此處輸入圖片說明

您對PerspectiveCamera有問題。 它具有一個名為fixedEyeAtCameraZero的布爾參數,默認情況下為false,並且在場景的左上角顯示了一個很小的曲面。

我們需要將其設置為true,因此:

如果fixedEyeAtCameraZero為true,則眼睛位置在相機的本地坐標中固定為(0,0,0)

但是很遺憾,您無法設置參數,沒有setFixedEyeAtCameraZero()方法。 更改它的唯一方法是使用相機構造函數。

這意味着您必須從FXML文件中刪除PerspectiveCamera ,並通過控制器上的代碼將其添加

public class Window3DController {

    @FXML
    private AnchorPane anchorPane;
    @FXML
    private Group group;

    private Window3DBuilder window3dBuilder;
    private PerspectiveCamera perspectiveCamera;

    @FXML
    public void initialize() {
        perspectiveCamera = new PerspectiveCamera(true);

        window3dBuilder = new Window3DBuilder(group, perspectiveCamera);
        window3dBuilder.createScene();

        group.sceneProperty().addListener(new InvalidationListener() {
            @Override
            public void invalidated(Observable observable) {
                group.getScene().setCamera(perspectiveCamera);
                group.sceneProperty().removeListener(this);
            }
        });
    } 

}

最后一步:您需要為相機設置一些參數,基本上是基於網格大小的z坐標:

public void createScene() {
    createSurface();
    group.getChildren().addAll(surface);

    perspectiveCamera.setNearClip(0.1);
    perspectiveCamera.setFarClip(100000.0);
    perspectiveCamera.setTranslateX((group.getBoundsInLocal().getMaxX() + group.getBoundsInLocal().getMinX()) / 2d);
    perspectiveCamera.setTranslateY((group.getBoundsInLocal().getMaxY() + group.getBoundsInLocal().getMinY()) / 2d);
    double max = Math.max(group.getBoundsInLocal().getWidth(), group.getBoundsInLocal().getHeight());
    perspectiveCamera.setTranslateZ(-2 * max);
}

這將顯示您的表面,但不像您期望的那樣:您正在應用的效果適用於2D:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.Group?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Window3DController">
   <children>
      <Group fx:id="group" />
   </children>
</AnchorPane>

刪除這些效果,並使用PointLight通過代碼添加它們:

public class Window3DBuilder {

    private final Group group;
    private SurfacePlotMesh surface;
    private final CameraTransformer cameraTransformer;
    private final PerspectiveCamera perspectiveCamera;
    private PointLight light;

    public Window3DBuilder( Group group, PerspectiveCamera perspectiveCamera ) {
        this.group = group;
        this.perspectiveCamera = perspectiveCamera;
        cameraTransformer = new CameraTransformer();
    }

    public void createScene() {
        createSurface();
        group.getChildren().addAll(surface, cameraTransformer);

        cameraTransformer.setTranslate(0, 0, 0);
        cameraTransformer.getChildren().addAll(perspectiveCamera);

        perspectiveCamera.setNearClip(0.1);
        perspectiveCamera.setFarClip(100000.0);
        perspectiveCamera.setTranslateX((group.getBoundsInLocal().getMaxX() + group.getBoundsInLocal().getMinX()) / 2d);
        perspectiveCamera.setTranslateY((group.getBoundsInLocal().getMaxY() + group.getBoundsInLocal().getMinY()) / 2d);
        double max = Math.max(group.getBoundsInLocal().getWidth(), group.getBoundsInLocal().getHeight());
        perspectiveCamera.setTranslateZ(-2 * max);
        createLight();
    }

    public void createLight() {
        light = new PointLight(Color.WHITE);
        cameraTransformer.getChildren().add(light);
        light.setTranslateX(perspectiveCamera.getTranslateX());
        light.setTranslateY(perspectiveCamera.getTranslateY());
        light.setTranslateZ(perspectiveCamera.getTranslateZ() / 10);
    }

    private void createSurface() {
        surface = new SurfacePlotMesh(
                p-> Math.sin(p.magnitude() + 1e-10) / (p.magnitude() + 1e-10),
                20, 20, 100, 100, 4);
        surface.setCullFace(CullFace.NONE);
        surface.setTextureModeVertices3D(1530, p -> p.magnitude());
        surface.getTransforms().addAll(new Rotate(200, Rotate.X_AXIS), new Rotate(-20, Rotate.Y_AXIS));
    }

}

表面

我想將相機保存在.fxml文件中。 我基於PerspectiveCamera創建了一個自定義控件。

從一個非常簡單的課程開始...

import javafx.scene.PerspectiveCamera;


public class PerspectiveCamera3D extends PerspectiveCamera {

// force 3D
public PerspectiveCamera3D() {
    super(true);
}

// toss the parameter, force 3D
public PerspectiveCamera3D(final boolean fixedEyeAtCameraZero) {
    this();
}
}

導出到.jar文件。 啟動Scene Builder並打開.fxml文件,將其放置在相機要放置的位置。

打開“庫”標題上的“齒輪”菜單。 然后導入FXML / Jar。 導入新創建的.jar文件。 將彈出一個對話框,列出您的控件。 確認后,控件將出現在自定義菜單中。 就像其他任何控件一樣,您的控件現在可以使用了。

“ Fixed Eye ...”復選框將仍然是只讀的,但被選中。 可以根據需要設置所有其他屬性。 要設置fx:id,只需將以下內容添加到您的控制器代碼中...

@FXML
public PerspectiveCamera3D cambot;

這是一個示例的更詳細信息... https://rterp.wordpress.com/2014/07/28/adding-custom-javafx-component-to-scene-builder-2-0-part-2/

我這樣做的唯一問題是,通過在Eclipse中單擊.fxml文件來啟動Scene Builder時,會導致異常(我認為這是我計算機上的本地問題,因為我的啟動方式和他們的工作目錄)。 如果我打開Scene Builder,然后從Scene Builder的“文件”菜單中打開.fxml文件,它會很好地工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM