【问题标题】:JavaFX 8 Z-buffer issueJavaFX 8 Z 缓冲区问题
【发布时间】:2016-02-06 10:01:07
【问题描述】:

我的问题是 JavaFX 3D 中的 Z-Buffer,它在我的机器上似乎没有按预期工作。

我知道以下问题: Overlapping shapes...Z Order...

但是我确实启用了 Z-Buffer,并且节点仍然按照它们添加到场景图中的顺序进行渲染。

也许我缺少一些依赖项或其他什么?

我正在发布代码,希望有人可以帮助我。我正在创建一个在椭圆路径上围绕另一个节点移动节点的过渡。

提前谢谢你!

public class OrbitExp extends Application {
Group root = new Group();
Scene scene = new Scene(root, 800, 600, true, SceneAntialiasing.BALANCED);
PerspectiveCamera camera = new PerspectiveCamera();
@Override
public void start(Stage primaryStage) {
    root.setDepthTest(DepthTest.ENABLE); 
//Tried to set Depthtest explicitly. Assumed maybe it did not inherit:S
    System.out.println(
        "3D supported? " +
        Platform.isSupported(ConditionalFeature.SCENE3D)
    );    // returns true

    System.out.println("root z-buffer: " + root.getDepthTest());
    initCamera();
    Box 
            box1 = new Box(50,50,50),
            box2 = new Box(10,10,10);
    root.setTranslateX(scene.getWidth()/2);
    root.setTranslateY(scene.getHeight()/2);
    PhongMaterial 
            pmat = new PhongMaterial(Color.BLUE),
            pmat2 = new PhongMaterial(Color.RED);
    box1.setMaterial(pmat);
    box2.setMaterial(pmat2);
    scene.setFill(Color.LIGHTGREEN);
    root.getChildren().addAll(box1,box2);
    SequentialTransition sqt = orbit(box1, box2, 40, 40, Duration.seconds(3), 360);
    sqt.play();
    scene.setOnMouseClicked(click->{
        Node node = (Node)(click.getPickResult().getIntersectedNode());
        System.out.println("Tx: "+node.getTranslateX());
        System.out.println("Ty: "+node.getTranslateY());
        System.out.println("Tz: "+node.getTranslateZ());
    }); 
// just for debugging, but coords does seem to be alright
    primaryStage.setScene(scene);
    primaryStage.show();
}
public static void main(String[] args) {
    launch(args);
}
private void initCamera() {
    camera.setTranslateZ(-50);
    camera.setTranslateY(20);
    camera.setFarClip(5000);
    camera.setNearClip(0);
    scene.setCamera(camera);
}
SequentialTransition orbit(Node node1, Node node2,double a, double b, Duration totalDuration, int N) {
    SequentialTransition sqt = new SequentialTransition();
    Duration dur = new Duration(totalDuration.toMillis()*(1.0d/N));
    node2.setTranslateX(a+node1.getTranslateX());
    node2.setTranslateZ(node1.getTranslateZ());
    for (int i = 1; i < N; i++) {
        TranslateTransition tt = new TranslateTransition(dur, node2);
        double 
                angle = i*(360.0d/N),
                toX = (Math.cos(Math.toRadians(angle))*a)+node1.getTranslateX(),
                toZ = (Math.sin(Math.toRadians(angle))*b)+node1.getTranslateZ();
        tt.setToX(toX);
        tt.setToZ(toZ);
        tt.setInterpolator(Interpolator.LINEAR);
        sqt.getChildren().add(tt);
        System.out.println("angle = " + angle + "\nangle in rads: " + Math.toRadians(angle) + "\ntoX = " + toX + "\ntoZ = " + toZ);
    }
    sqt.setCycleCount(Timeline.INDEFINITE);
    return sqt;
}

}

这是我的第一篇文章:)

【问题讨论】:

    标签: java javafx javafx-8 javafx-3d


    【解决方案1】:

    如果您使用矩形检查您提供的link 上的代码,深度缓冲区工作正常。

    将矩形更改为使用 3D 框也可以。

    问题是你如何定义一个与另一个相关的盒子的旋转,所以我没有像你一样使用RotateTransitionSequentialTransitionTranslateTransition,而是应用了Rotate转换为红色框,在蓝色框的中心设置一个枢轴,并使用AnimationTimer 修改该旋转的角度以创建“轨道”效果。

    您甚至可以在大盒子上使用透明度(从 8u60 开始)来查看它下面的小盒子。

    private final Group shapes = new Group();
    private long lastTimerCall;
    private AnimationTimer timeline;
    
    @Override
    public void start(Stage stage) throws Exception {
        Scene scene = new Scene(createRotatingShapes(), 400, 300,
                true, SceneAntialiasing.BALANCED);
        scene.setFill(Color.LIGHTGREEN);
        final PerspectiveCamera camera = new PerspectiveCamera();
        camera.setRotationAxis(Rotate.X_AXIS);
        camera.setRotate(10);
        camera.setTranslateZ(200);
        scene.setCamera(camera);
    
        stage.setScene(scene);
        stage.show();
    }
    
    private Group createRotatingShapes() {
        final Box box1 = new Box(50, 50, 50);
        // Transparency in box1: last node of the group
        box1.setMaterial(new PhongMaterial(Color.web("#0000FF80")));
    
        box1.setTranslateZ(50);
    
        final Box box2 = new Box(10, 10, 10);
        box2.setMaterial(new PhongMaterial(Color.RED));
    
        box2.setTranslateZ(-50);
    
        shapes.getChildren().addAll(box2, box1);
    
        shapes.setTranslateX(200);
        shapes.setTranslateY(150);
    
        rotateAroundYAxis(box2);
    
        return shapes;
    }
    
    private int count = 0;
    private void rotateAroundYAxis(Node node) {
        Rotate r = new Rotate(0, 0, 0, 100, Rotate.Y_AXIS);
        node.getTransforms().add(r);
        lastTimerCall = System.nanoTime();
        timeline = new AnimationTimer() {
            @Override public void handle(long now) {
                if (now > lastTimerCall + 100_000_000l) {
                    r.setAngle((count++)%360);
                }
            }
        };
        timeline.start();
    }
    
    
    @Override
    public void stop() {
        timeline.stop();
    }
    

    在盒子前面:

    在蓝色框后面:

    编辑

    如果您查看 nearClip 的 Camera JavaDoc:

    指定到近剪裁平面眼睛的距离 这个相机在眼睛坐标空间中。 不绘制比 nearClip 更靠近眼睛的对象。 nearClip 被指定为 大于 的值,而不是零。少一个值 大于或等于零被视为非常小的正数。

    (粗体是我的)。

    所以你的代码的问题是这一行:

    camera.setNearClip(0);
    

    只需将其更改为:

    camera.setNearClip(0.01);
    

    它会按您的预期工作。

    【讨论】:

    • 感谢您的快速回答,我确实看到您的解决方案运行良好,我很乐意接受它作为答案。但是,我确实看不到为什么在我的程序中,cube1 在 cube2 之后仍然在 cube2 之前渲染,请您澄清一下“如何定义与另一个相关的盒子之一的旋转”。非常感谢!
    • Rotate r使用pivotZ = 100,两个框之间的距离,所以只需要旋转红色框即可。使用深度缓冲区,组中框的顺序无关紧要,除了将透明度设置为蓝色。如果您切换顺序,它会起作用,但蓝色框不会是透明的。
    • 检查您的相机设置并进行更改:camera.setNearClip(0.01);。您的代码现在可以工作了。我已经用这个编辑了我的答案。
    • 错误的剪辑设置很微妙。我也在another answer 中偶然发现了这一点,在那里我调试了一段时间并提出了一个解决方案,但最后注意到提问者只是设置了错误的剪切平面。 (在未来关于“JavaFX 中的奇怪渲染问题”的问题中,我将首先检查剪切平面......)。顺便说一下 +1
    • 谢谢,现在一切都好。一切都按原样呈现。我不知道将 camera nearClip 设置为 0 会导致问题。文档说:“小于或等于零的值被视为非常小的正数。”,所以我认为它是安全的:S
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    • 2011-05-28
    相关资源
    最近更新 更多