Java 改变相机角度后,形状中会出现奇怪的线条

Java 改变相机角度后,形状中会出现奇怪的线条,java,javafx,Java,Javafx,我有一个程序,它构成了一个从Group类扩展而来的立方体类,在这个立方体中,我创建了一个多边形,作为立方体的一个面,当面对它时,它会呈现法线,但是当相机透视在前面一个面上创建了一条奇怪的白线后,它会向后旋转多边形,我注意到这是由于通过getChildren()创建和添加到容器中的项目的顺序造成的。add(),该行不能独立于创建立方体和面并将其添加到容器的顺序进行渲染 类cube.java import java.util.ArrayList; import javafx.event.Event

我有一个程序,它构成了一个从Group类扩展而来的立方体类,在这个立方体中,我创建了一个多边形,作为立方体的一个面,当面对它时,它会呈现法线,但是当相机透视在前面一个面上创建了一条奇怪的白线后,它会向后旋转多边形,我注意到这是由于通过getChildren()创建和添加到容器中的项目的顺序造成的。add(),该行不能独立于创建立方体和面并将其添加到容器的顺序进行渲染

类cube.java

import java.util.ArrayList;

import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Point3D;
import javafx.geometry.Pos;
import javafx.scene.CacheHint;
import javafx.scene.DepthTest;
import javafx.scene.Group;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;

public class Cube extends Group{

    public final Rotate rx = new Rotate(0, Rotate.X_AXIS);
    public final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
    public final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
    public final Translate translate;
    public final double x;
    public final double y;
    public final double z;
    public final Group group;
    public static final ArrayList<Cube> instances = new ArrayList<Cube>();

    public static final int A_LEFT = 0;
    public static final int A_RIGHT = 1;
    public static final int A_TOP = 2;
    public static final int A_BOTTOM = 3;
    public static final int A_FRONT = 4;
    public static final int A_BACK = 5;

    public Cube(double tam, double x, double y, double z, Color cor, Group grupo) {
        this.group = grupo;
        setDepthTest(DepthTest.ENABLE);
        setCacheHint(CacheHint.SCALE_AND_ROTATE);
        setCache(true);
        Cube.instances.add(this);
        //System.out.print(Cube.instances.size());
        grupo.getChildren().add(this);
        this.x = x; 
        this.y = y;
        this.z = z;

        translate = new Translate(x,y,z);

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

        Button b = new Button("Test Button");
        b.setOnMouseClicked(new EventHandler<Event>() {

            @Override
            public void handle(Event event) {
                System.out.println("Test click");
            }

        });

        HBox frontFace = this.createFace(tam, tam, tam*-0.5, tam*-0.5, tam*-0.5, Rotate.X_AXIS, 0, cor.deriveColor(0.0, 1.0, (1 - 0.5 * 1), 1.0));
        HBox backFace = this.createFace(tam, tam, tam*-0.5, tam*-0.5, tam*0.5, Rotate.Y_AXIS, 180d, cor.deriveColor(0.0, 1.0, (1 - 0.4 * 1), 1.0));
        HBox leftFace = this.createFace(tam, tam, tam*-1, tam*-0.5, 0, Rotate.Y_AXIS, 90d, cor.deriveColor(0.0, 1.0, (1 - 0.3 * 1), 1.0));
        HBox rightFace = this.createFace(tam, tam, 0, tam*-0.5, 0, Rotate.Y_AXIS, -90d, cor.deriveColor(0.0, 1.0, (1 - 0.2 * 1), 1.0));
        HBox bottomFace = this.createFace(tam, tam, tam*-0.5, 0, 0, Rotate.X_AXIS, 90d, cor.deriveColor(0.0, 1.0, (1 - 0.1 * 1), 1.0));
        HBox topFace = this.createFace(tam, tam, tam*-0.5, tam*-1, 0, Rotate.X_AXIS, -90d, cor.deriveColor(0.0, 1.0, (1 - 0.6 * 1), 1.0));

        Polygon polygon = new Polygon();
        polygon.getPoints().addAll(new Double[]{
            55.0, 0.0,
            110.0, 110.0,
            0.0, 110.0
            });

        polygon.setStroke(Color.BROWN);
        polygon.setStrokeWidth(0);
        polygon.setSmooth(false);
        polygon.setCacheHint(CacheHint.SCALE_AND_ROTATE);

        backFace.getChildren().add(polygon);
        backFace.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)));
        polygon.setFill(Color.BLACK);
        polygon.setStroke(null);

      //  leftFace.getChildren().add(polygon2);

        ImageView anImage = new ImageView(new Image("android.png",110,110,false,true));

        anImage.setFitWidth(100);
        anImage.setPreserveRatio(true);
        anImage.setCacheHint(CacheHint.SCALE_AND_ROTATE);
        anImage.setSmooth(true);
        anImage.setCache(true); 

       // backFace.getChildren().add(anImage);

        /*BackgroundImage myBI= new BackgroundImage(new Image("android.png",110,110,false,true),
                BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT,
                  BackgroundSize.DEFAULT);*/

        //frontFace.setBackground(new Background(myBI));

        frontFace.setStyle("-fx-background-color:rgba(0,0,0,0)");

        rightFace.setOnMouseClicked(e -> this.createNextCube(e, Cube.A_RIGHT));
        leftFace.setOnMouseClicked(e -> this.createNextCube(e, Cube.A_LEFT));
        topFace.setOnMouseClicked(e -> this.createNextCube(e, Cube.A_TOP));
        bottomFace.setOnMouseClicked(e -> this.createNextCube(e, Cube.A_BOTTOM));
        frontFace.setOnMouseClicked(e -> this.createNextCube(e, Cube.A_FRONT));
        backFace.setOnMouseClicked(e -> this.createNextCube(e, Cube.A_BACK));

        //frontFace.getChildren().addAll(b);

        getChildren().addAll(
            frontFace,
            leftFace,
            rightFace,
            topFace,
            bottomFace,
            backFace
        );
    }

    public HBox createFace(double w, double h, double x, double y, double z, Point3D axis, double rotation, Color cor) {
        HBox g = new HBox();
        g.setPrefSize(w, h);
        g.setTranslateX(x);
        g.setTranslateY(y);
        g.setTranslateZ(z);

        g.setAlignment(Pos.CENTER);

        g.setRotationAxis(axis);
        g.setRotate(rotation);
        g.setBackground(new Background(new BackgroundFill(cor, CornerRadii.EMPTY, Insets.EMPTY)));

        return g;
    }

    public Cube createNextCube(MouseEvent e, int side) {
        if(e.getButton() == MouseButton.PRIMARY) {
            double px = this.x;
            double py = this.y;
            double pz = this.z;

            switch(side) {
            case Cube.A_RIGHT:
                px += 110;
            break;
            case Cube.A_LEFT:
                px -= 110;
            break;
            case Cube.A_TOP:
                py -= 110;
            break;
            case Cube.A_BOTTOM:
                py += 110;
            break;
            case Cube.A_FRONT:
                pz -= 110;
            break;
            case Cube.A_BACK:
                pz += 110;
            break;
            }

            return new Cube(110, px, py, pz, Color.ALICEBLUE, this.group);
        }

        return null;
    }
}
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.CacheHint;
import javafx.scene.DepthTest;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application{

    private PerspectiveCamera camera;
    private Rotate cameraRotateX, cameraRotateY, cameraRotateZ;
    private double antX;
    private double antY;


    public void init(Stage primaryStage) {
            camera = new PerspectiveCamera();
            cameraRotateX = new Rotate(0, Rotate.X_AXIS);
            cameraRotateY = new Rotate(0, Rotate.Y_AXIS);
            cameraRotateZ = new Rotate(0, Rotate.Z_AXIS);

            Translate cameraTranslate = new Translate(-700 / 2, -300 / 2, 0);
            camera.getTransforms().addAll(
                    cameraRotateX,
                    cameraRotateY,
                    cameraRotateZ,
                    cameraTranslate);
            Group root = new Group();
            root.setDepthTest(DepthTest.ENABLE);
            primaryStage.setResizable(true);
            primaryStage.setScene(new Scene(root, 700, 300, true, SceneAntialiasing.BALANCED));
            primaryStage.getScene().setCamera(camera);
           // root.getTransforms().addAll(
                    //new Translate(700 / 2, 300 / 2),
                    //new Rotate(180, Rotate.X_AXIS)
           // );

            //Group gp = new Group();
           // gp.setDepthTest(DepthTest.);
            //gp.setCache(true);
            camera.setNearClip(0.01);

            Cube cubo = new Cube(110, 0,0,0, Color.RED, root);

            Timeline animation = new Timeline();
            animation.getKeyFrames().addAll(
                    new KeyFrame(Duration.ZERO,
                            new KeyValue(cubo.ry.angleProperty(), 0d),
                            new KeyValue(cubo.rx.angleProperty(), 0d)
                    ),
                    new KeyFrame(Duration.seconds(30),
                            new KeyValue(cubo.ry.angleProperty(), 360d),
                            new KeyValue(cubo.rx.angleProperty(), 360d)
                    )
            );

            animation.setCycleCount(Animation.INDEFINITE);

            //root.getChildren().add(gp);

            root.setCache(true);
           // root.setCacheHint(CacheHint.SCALE_AND_ROTATE);

            //animation.play();

            primaryStage.getScene().setOnMousePressed(e -> pressed(e));
            primaryStage.getScene().setOnMouseDragged(e -> moved(e));
            primaryStage.getScene().setOnScroll(e -> cameraTranslate.setZ(cameraTranslate.getZ()+e.getDeltaY()));
            primaryStage.getScene().heightProperty().addListener(h -> cameraTranslate.setY(-1*(primaryStage.getScene().getHeight())/2));
            primaryStage.getScene().widthProperty().addListener(w -> cameraTranslate.setX(-1*(primaryStage.getScene().getWidth())/2));
    }

    public void pressed(MouseEvent ev) {
        antX = ev.getSceneX();
        antY = ev.getSceneY();
    }

    public void moved(MouseEvent ev) {

        double movX = ev.getSceneX() - antX;
        double movY = ev.getSceneY() - antY;

        cameraRotateX.setAngle(cameraRotateX.getAngle() + movY);
        cameraRotateY.setAngle(cameraRotateY.getAngle() + movX);

        antX = ev.getSceneX();
        antY = ev.getSceneY();
    }

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

    @Override
    public void start(Stage palco) throws Exception {
        init(palco);
        palco.show();
    }

}