Overlaping Shapes - 错误的重叠形状行为 [英] Overlaping Shapes - wrong overlapping shapes behaviour

查看:103
本文介绍了Overlaping Shapes - 错误的重叠形状行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之 - 我有2个旋转矩形。在旋转时(通过Y轴)它们应该相互重叠 - 不幸的是,尽管旋转180度,但是其中一个ractangles总是在前面。如何解决这种行为?它似乎与whitch矩形被添加到组中的顺序相关。最后添加的那个总是在前面。

In short - I have 2 rotating rectangles. While rotating (by Y axis) they should overlap one over another - unfortunetlny one of ractangles is "always in front" despite of 180 degree turn. How to fix that behaviour? It looks like it is relevant to order in whitch rectangles hass been added to group. The one that was added as last is always in front.

场景:

    package drawing.scene;

import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import drawing.objects.Clock;
import drawing.objects.Cube;

public class MyScene extends Application {

    private int sceneEdgeSize = 800;
    private int clolcSize = 400;

    @Override
    public void start(Stage primaryStage) throws Exception {
        Group g = new Group();
        g.setTranslateX((sceneEdgeSize - clolcSize) / 2f);
        g.setTranslateY((sceneEdgeSize - clolcSize) / 2f);

        final Cube c = new Cube(clolcSize);
        g.getChildren().add(c);
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                Rotate r = rotate(0, Rotate.Y_AXIS);
                c.getTransforms().add(r);
                double angle = 0.0;
                while (true) {

                    r.setAngle(angle += 2);
                    try {
                        Thread.sleep(25);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        });
        t.setDaemon(true);
        primaryStage.setScene(new Scene(g, sceneEdgeSize, sceneEdgeSize));
        PerspectiveCamera camera = new PerspectiveCamera();
        primaryStage.getScene().setCamera(camera);
        primaryStage.show();
        t.start();

    }

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

    public Rotate rotate(double angle, Point3D axis) {
        return new Rotate(angle, clolcSize / 2f, clolcSize / 2f, 0, axis);
    }

}

立方体类:

package drawing.objects;

import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.scene.transform.Rotate;

public class Cube extends Group {

    private double edgeLength = 0;

    public Cube(double edgeLength) {
        super();
        this.edgeLength = edgeLength;
        create();
    }

    private void create() {
        final Rotate rx = new Rotate(0, Rotate.X_AXIS);
        final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
        final Rotate rz = new Rotate(0, Rotate.Z_AXIS);

        this.getTransforms().addAll(rx, ry, rz);

        ObservableList<Node> children = this.getChildren();
        //@formatter:off

        Rectangle rect;

        rect = RectangleBuilder // face
                .create()
                .width(edgeLength-20)
                .height(edgeLength-20)
                .translateZ(edgeLength * 0.5)
//                  .translateY(edgeLength * 0.5)
                //  .translateX(-edgeLength * 0.5)
                .fill(Color.LIGHTGREEN)
                .build()
                ;
        children.add(rect);
        rect = RectangleBuilder // face
                .create()
                .width(edgeLength-20)
                .height(edgeLength-20)
                .translateZ(-edgeLength * 0.5)
//              .translateY(-edgeLength * 0.5)
            //  .translateX(-edgeLength * 0.5)
                .fill(Color.DARKGREEN)
                .build()
                ;
        children.add(rect);


        //@formatter:on
    }
}


推荐答案

你应该在场景中切换深度缓冲

此问题中的代码基本上已过时,部分内容也不正确:

The code in this question is largely obsolete and is also incorrect in parts:


  1. 对于 JavaFX 3D工作,建议使用 Java 8

  2. 要构建多维数据集,请使用 Box 形状。

  3. 对于其他几何类型,请使用 Sphere Cylinder MeshView

  4. 使用 Ambient 指示灯点亮您的场景。

  5. 材料应用于您的3D遮挡它们的对象。

  6. 使用模型导入器导入复杂的网格模型。

  7. 构建器

  8. 为了处理动画,不建议生成另一个线程,而是使用 JavaFX动画包

  9. 对于特定的a在您的问题中, RotateTransition 是适当的动画。

  10. 您的解决方案不是线程安全的。您不应该修改活动场景图中的节点属性(例如显示节点的转换属性),而不应该修改应用程序线程(使用 Platform.runLater 而不是)。

  11. 你没有创建一个场景与深度缓冲设置为true。深度缓冲标志告诉JavaFX它应该对3D对象应用深度排序和剔除。

  1. For JavaFX 3D work, it is recommended to use Java 8.
  2. For building a cube, use a Box shape.
  3. For other geometry types, use a Sphere, Cylinder or MeshView.
  4. Use Point and Ambient lights to illuminate your Scene.
  5. Apply Materials to your 3D objects to shade them.
  6. Use Model importers to import complex mesh models.
  7. Builders are deprecated.
  8. For handling animation it is not recommended to spawn another thread, but to use the JavaFX animation package.
  9. For the particular animation in your question, a RotateTransition is the appropriate animation.
  10. Your solution is not threadsafe. You should not modify properties of nodes in the active scene graph (e.g. the transform properties of a displayed node) off of the application thread (use Platform.runLater instead).
  11. You are not creating a scene with depth buffering set to true. The depth buffering flag tells JavaFX that it should apply depth sorting and culling to 3D objects.

同时检查您的系统是否支持JavaFX 3D:

Also check that your system supports JavaFX 3D:

System.out.println(
  "3D supported? " + 
  Platform.isSupported(ConditionalFeature.SCENE3D)
);

Java 8旋转立方体的3D示例代码

这是一个用Java 8编码的旋转立方体。

Here is a rotating cube coded in Java 8.

import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;

public class RotatingCube extends Application {

    private static final double SCENE_SIZE = 300;
    private static final double BOX_EDGE_LENGTH = SCENE_SIZE / 2d;

    private static final Color BOX_COLOR     = Color.DARKGREEN;
    private static final Color AMBIENT_COLOR = Color.rgb(30, 30, 30);
    private static final Color LIGHT_COLOR   = Color.WHITE;

    private static final Duration ROTATION_DURATION = Duration.seconds(4.5);

    @Override
    public void start(Stage stage) throws Exception {
        Scene scene = new Scene(
                new Group(
                        new AmbientLight(AMBIENT_COLOR),
                        createPointLight(),
                        createRotatingBox()
                ),
                SCENE_SIZE, SCENE_SIZE,
                true,
                SceneAntialiasing.BALANCED
        );
        scene.setFill(Color.MIDNIGHTBLUE.darker().darker().darker());
        scene.setCamera(new PerspectiveCamera());

        stage.setScene(scene);
        stage.show();
    }

    private PointLight createPointLight() {
        PointLight light = new PointLight(LIGHT_COLOR);
        light.setTranslateX( SCENE_SIZE / 2d);
        light.setTranslateY( SCENE_SIZE / 2d);
        light.setTranslateZ(-SCENE_SIZE);

        return light;
    }

    private Box createRotatingBox() {
        final Box box = new Box(BOX_EDGE_LENGTH, BOX_EDGE_LENGTH, BOX_EDGE_LENGTH);
        box.setTranslateX(SCENE_SIZE / 2d);
        box.setTranslateY(SCENE_SIZE / 2d);
        box.setTranslateZ(BOX_EDGE_LENGTH / 2d);
        box.setMaterial(new PhongMaterial(BOX_COLOR));

        rotateAroundYAxis(box);

        return box;
    }

    private void rotateAroundYAxis(Box box) {
        RotateTransition rotate = new RotateTransition(ROTATION_DURATION, box);
        rotate.setFromAngle(0);
        rotate.setToAngle(360);
        rotate.setAxis(Rotate.Y_AXIS);
        rotate.setCycleCount(RotateTransition.INDEFINITE);
        rotate.setInterpolator(Interpolator.LINEAR);
        rotate.play();
    }

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

}

Java 8 3D示例两个旋转矩形的代码

import javafx.animation.*;
import javafx.application.*;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;

public class RotatingRectangles extends Application {

    private static final double SCENE_SIZE = 300;
    private static final double EDGE_LENGTH = SCENE_SIZE / 2d;

    private static final Duration ROTATION_DURATION = Duration.seconds(4.5);

    @Override
    public void start(Stage stage) throws Exception {
        System.out.println(
            "3D supported? " +
            Platform.isSupported(ConditionalFeature.SCENE3D)
        );

        Scene scene = new Scene(
                createRotatingShapes(),
                SCENE_SIZE, SCENE_SIZE,
                true,
                SceneAntialiasing.BALANCED
        );
        scene.setFill(Color.MIDNIGHTBLUE.darker().darker().darker());
        scene.setCamera(new PerspectiveCamera());

        stage.setScene(scene);
        stage.show();
    }

    private Group createRotatingShapes() {
        final Rectangle rect1 = new Rectangle(
            EDGE_LENGTH, EDGE_LENGTH,
            Color.LIGHTGREEN
        );
        rect1.setTranslateX(-EDGE_LENGTH / 2d);
        rect1.setTranslateY(-EDGE_LENGTH / 2d);
        rect1.setTranslateZ( EDGE_LENGTH / 2d);

        final Rectangle rect2 = new Rectangle(
            EDGE_LENGTH, EDGE_LENGTH,
            Color.DARKGREEN
        );
        rect2.setTranslateX(-EDGE_LENGTH / 2d);
        rect2.setTranslateY(-EDGE_LENGTH / 2d);
        rect2.setTranslateZ(-EDGE_LENGTH / 2d);

        final Group shapes = new Group(
            rect1, rect2
        );

        shapes.setTranslateX(SCENE_SIZE / 2d);
        shapes.setTranslateY(SCENE_SIZE / 2d);
        shapes.setTranslateZ(EDGE_LENGTH / 2d);

        rotateAroundYAxis(shapes);

        return shapes;
    }

    private void rotateAroundYAxis(Node node) {
        RotateTransition rotate = new RotateTransition(ROTATION_DURATION, node);
        rotate.setFromAngle(0);
        rotate.setToAngle(360);
        rotate.setAxis(Rotate.Y_AXIS);
        rotate.setCycleCount(RotateTransition.INDEFINITE);
        rotate.setInterpolator(Interpolator.LINEAR);
        rotate.play();
    }

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

}

在第一张图片中,黑色矩形已经在浅色矩形的前面旋转。

In the first picture the dark rectangle has been rotated in front of the light rectangle.

在第一张图片中,浅色矩形已经在黑色矩形的前面旋转。

In the first picture the light rectangle has been rotated in front of the dark rectangle.

因此,您可以看到JavaFX系统正确显示场景中的深度排序形状。

So you can see that the JavaFX system is correctly displaying the depth sorted shapes in the scene.


这篇关于Overlaping Shapes - 错误的重叠形状行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆