У меня есть программа, которая составляет класс Cube, который выходит из класса Group, в этом кубе я создаю Polygon, который служит одним изграни этого куба, если смотреть на него, он становится нормальным, но когда перспектива камеры поворачивается назад на многоугольник. После создания странной белой линии над передней я заметил, что это происходит из-за порядка, в котором элементы создаются и добавляются вконтейнер через 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;
}
}
Класс main.java
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();
}
}