4

我有一个 JavaFX 3D 场景,在随机位置添加了一堆盒子和球体。似乎深度顺序都是错误的,我不知道为什么。我曾尝试使用 myNode.setDepthTest(DepthTest.ENABLE) 但这似乎没有帮助。我附上了一个应该证明问题的应用程序。

知道我在这里可能做错了什么吗?非常感谢任何帮助。

import javafx.application.Application;
import javafx.application.ConditionalFeature;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.DepthTest;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Shape3D;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class Array3DTest extends Application {


double mousePosX;
double mousePosY;
double mouseOldX;
double mouseOldY;
double mouseDeltaX;
double mouseDeltaY;

/**
 * This is the group which rotates 
 */
Group root3D;

/**
 * The camnera to 
 */
private Rotate rotateY;
private Rotate rotateX;
private Translate translate;

public Array3DTest( ){


}

public Group createScene(){

    // Create and position camera
    PerspectiveCamera camera = new PerspectiveCamera(true);
    camera.setFarClip(15000);
    camera.setNearClip(0.1);
    camera.setDepthTest(DepthTest.ENABLE);
    camera.getTransforms().addAll(
            rotateY=new Rotate(0, Rotate.Y_AXIS),
            rotateX=new Rotate(0, Rotate.X_AXIS),
            translate=new Translate(250, 250, -1000));

    root3D=new Group(); 
    root3D.getChildren().add(camera);
    root3D.setDepthTest(DepthTest.ENABLE);


    final PhongMaterial redMaterial = new PhongMaterial();
       redMaterial.setSpecularColor(Color.ORANGE);
       redMaterial.setDiffuseColor(Color.RED);      

    for (int i=0; i<50; i++){
         Shape3D mySphere;
        if (i%2==0)    mySphere = new Box(100,100, 100);
        else mySphere= new Sphere(30);
        mySphere.setTranslateX(Math.random()*500);
        mySphere.setTranslateY(Math.random()*500);
        mySphere.setTranslateZ(Math.random()*200);
        mySphere.setMaterial(redMaterial);
        mySphere.setDepthTest(DepthTest.ENABLE);
        root3D.getChildren().add(mySphere);
    }

    // Use a SubScene to mix 3D and 3D stuff.        
    SubScene subScene = new SubScene(root3D, 500,500);        
    subScene.setFill(Color.WHITE);
    subScene.setCamera(camera);
    subScene.setDepthTest(DepthTest.ENABLE);
    Group group = new Group();
    group.getChildren().add(subScene);

    handleMouse(subScene); 

    return group;

}

 private void handleMouse(SubScene scene) {

        scene.setOnMousePressed(new EventHandler<MouseEvent>() {

            @Override public void handle(MouseEvent me) {
                mousePosX = me.getSceneX();
                mousePosY = me.getSceneY();
                mouseOldX = me.getSceneX();
                mouseOldY = me.getSceneY();
            }
        });

        scene.setOnScroll(new EventHandler<ScrollEvent>() {
            @Override public void handle(ScrollEvent event) {
                System.out.println("Scroll Event: "+event.getDeltaX() + " "+event.getDeltaY()); 
                translate.setZ(translate.getZ()+  event.getDeltaY() *0.001*translate.getZ());   // + 


            }
        });


        scene.setOnMouseDragged(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent me) {
                mouseOldX = mousePosX;
                mouseOldY = mousePosY;
                mousePosX = me.getSceneX();
                mousePosY = me.getSceneY();
                mouseDeltaX = (mousePosX - mouseOldX);
                mouseDeltaY = (mousePosY - mouseOldY);

                double modifier = 1.0;
                double modifierFactor = 0.1;

                if (me.isControlDown()) {
                    modifier = 0.1;
                }
                if (me.isShiftDown()) {
                    modifier = 10.0;
                }
                if (me.isPrimaryButtonDown()) {
                    rotateY.setAngle(rotateY.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0);  // +
                    rotateX.setAngle(rotateX.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0);  // -
                }
                if (me.isSecondaryButtonDown()) {
                    translate.setX(translate.getX() -mouseDeltaX * modifierFactor * modifier * 5);
                    translate.setY(translate.getY() - mouseDeltaY * modifierFactor * modifier * 5);   // +
                }


            }
        });
    }

@Override
public void start(Stage primaryStage) throws Exception {
    System.out.println(
            "3D supported? " + 
                    Platform.isSupported(ConditionalFeature.SCENE3D)
            );  
    Group group=createScene();
    primaryStage.setResizable(false);
    Scene scene = new Scene(group, 500,500, true);
    primaryStage.setScene(scene);
    primaryStage.show();
}



public static void main(String[] args) {
    launch(args);
}

}
4

1 回答 1

6

由于您使用的是SubScene对象,因此您可以方便地启用深度缓冲区,就像您已经为Scene. 此外,启用抗锯齿也会有所帮助。

根据JavaDoc:

depthBuffer 和 antiAliasing 标志是条件特性。使用各自的默认值:false 和 SceneAntialiasing.DISABLED。

所以只需使用其他构造函数SubScene

SubScene subScene = new SubScene(root3D, 500, 500, true, SceneAntialiasing.BALANCED);  

你会注意到不同之处。

于 2015-02-17T17:40:40.133 回答