0

我正在尝试在 javaFX 中创建一个魔方,我正在努力解决面部的旋转问题。到目前为止,我只是将一张脸中的 9 个立方体添加到一个组中并旋转 90 度以使整个脸以正确的方式旋转,但是这种方法似乎不适用于多次旋转。

相反,我想围绕每个面中心的枢轴点旋转每个立方体。为此,我尝试使用内置在 pivot 参数中的 Rotate 类,但它似乎对旋转没有影响。这是我用来旋转正面的函数的简化版本,其中二维数组 frontFace 包含正面从左上角到右下角的所有立方体:

public void rotate() {
    Rotate r = new Rotate(45, 0, 0, -100, Rotate.Z_AXIS);
    for (int x = 0; x < 3; x++) {
        for (int y = 0; y < 3; y++) {
            frontFace[x][y].getCube().getTransforms().add(r);
        }
    }
}   

这会产生以下结果(我已将其旋转 45 度,以便更容易看到):

当前轮换

而我希望它像这样旋转:

理想旋转

这是我第一个使用 javaFX 的项目,任何帮助将不胜感激!到目前为止的完整项目可以在这里找到:

https://gofile.io/d/KidwKh

编辑:我被要求包含一个最小的、可重现的示例,所以我试图将问题浓缩到一个希望不会混淆的类中,这里是代码:

import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.AmbientLight;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

public class Example extends Application {


    public static final float X_RED     = 0.5f / 7f;
    public static final float X_GREEN   = 1.5f / 7f;
    public static final float X_BLUE    = 2.5f / 7f;
    public static final float X_YELLOW  = 3.5f / 7f;
    public static final float X_ORANGE  = 4.5f / 7f;
    public static final float X_WHITE   = 5.5f / 7f;
    public static final float X_GRAY    = 6.5f / 7f;


    public static int red = 0;
    public static int green = 1;
    public static int blue = 2;
    public static int yellow = 3;
    public static int orange = 4;
    public static int white = 5;
    public static int grey = 6;



    public static int WIDTH = 1400;
    public static int HEIGHT = 800;



    private static final SmartGroup MainCubeGroup = new SmartGroup();
    private static PhongMaterial mat = new PhongMaterial();


    MeshView[][] frontFace = new MeshView[3][3];

    @Override
    public void start(Stage primaryStage) {
        ViewCamera camera = new ViewCamera(MainCubeGroup);
        mat.setDiffuseMap(new Image(getClass().getResourceAsStream("pallete.png")));
        MainCubeGroup.getChildren().addAll(new AmbientLight(Color.WHITE));
        Scene scene = new Scene(MainCubeGroup, WIDTH, HEIGHT, true);

        //creates just frontFace of cube
        frontFace[0][0] = createCube(new Point3D(-100, -100, -100), new int[]{blue, grey, white, grey, red, grey});
        frontFace[0][1] = createCube(new Point3D(0, -100, -100),  new int[]{blue, grey, white, grey, grey, grey});
        frontFace[0][2] = createCube(new Point3D(100, -100, -100), new int[] {blue, green, white, grey, grey, grey});
        frontFace[1][0] = createCube(new Point3D(-100, 0, -100), new int[]{blue, grey, grey, grey, red, grey});
        frontFace[1][1] = createCube(new Point3D(0, 0, -100), new int[]{blue, grey, grey, grey, grey, grey});
        frontFace[1][2] = createCube(new Point3D(100, 0, -100),  new int[]{blue, green, grey, grey, grey, grey});
        frontFace[2][0] = createCube(new Point3D(-100, 100, -100), new int[]{blue, grey, grey, grey, red, yellow});
        frontFace[2][1] = createCube(new Point3D(0, 100, -100), new int[]{blue, grey, grey, grey, grey, yellow});
        frontFace[2][2] = createCube(new Point3D(100, 100, -100),  new int[]{blue, green, grey, grey, grey, yellow});


        rotate(45);


        scene.setFill(Color.BLANCHEDALMOND);
        scene.setCamera(camera);
        primaryStage.setTitle("DDD");
        primaryStage.setScene(scene);
        MainCubeGroup.translateXProperty().set(WIDTH / 2);
        MainCubeGroup.translateYProperty().set(HEIGHT / 2);
        primaryStage.show();
        camera.initMouseControl(scene, primaryStage);
    }


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


    public void rotate(int angle) {
        Rotate r = new Rotate(angle, 0, 0, -100, Rotate.Z_AXIS);
        for (int x = 0; x < 3; x++) {
            for (int y = 0; y < 3; y++) {
                frontFace[x][y].getTransforms().add(r);
            }
        }
    }


    public static MeshView createCube(Point3D position, int[] face){
        int sideLength = 90;
        TriangleMesh meshCube = new TriangleMesh();
        meshCube.getTexCoords().addAll(
                X_RED, 0.5f,
                X_GREEN, 0.5f,
                X_BLUE, 0.5f,
                X_YELLOW, 0.5f,
                X_ORANGE, 0.5f,
                X_WHITE, 0.5f,
                X_GRAY, 0.5f
        );

        meshCube.getPoints().addAll(
                sideLength/2,  sideLength/2,  sideLength/2,  //point0
                sideLength/2, -sideLength/2,  sideLength/2,  //point1
                sideLength/2,  sideLength/2, -sideLength/2,  //point2
                sideLength/2, -sideLength/2, -sideLength/2,  //point3
                -sideLength/2,  sideLength/2,  sideLength/2, //point4
                -sideLength/2, -sideLength/2,  sideLength/2, //point5
                -sideLength/2,  sideLength/2, -sideLength/2, //point6
                -sideLength/2, -sideLength/2, -sideLength/2  //point7
        );
        //textures
        meshCube.getFaces().addAll(

                2,face[0],3,face[0],6,face[0],      // F
                3,face[0],7,face[0],6,face[0],

                0,face[1],1,face[1],2,face[1],      // R
                2,face[1],1,face[1],3,face[1],

                1,face[2],5,face[2],3,face[2],      // U
                5,face[2],7,face[2],3,face[2],

                0,face[3],4,face[3],1,face[3],      // B
                4,face[3],5,face[3],1,face[3],

                4,face[4],6,face[4],5,face[4],      // L
                6,face[4],7,face[4],5,face[4],

                0,face[5],2,face[5],4,face[5],      // D
                2,face[5],6,face[5],4,face[5]

        );
        MeshView cube = new MeshView(meshCube);
        cube.setDrawMode(DrawMode.FILL);
        cube.setMaterial(mat);
        cube.setTranslateX(position.getX());
        cube.setTranslateY(position.getY());
        cube.setTranslateZ(position.getZ());
        MainCubeGroup.getChildren().add(cube);
        return cube;
    }
}

这是图像pallete.png,如果您想要颜色,则在代码中使用它,尽管我认为它与问题无关: pallete.png

谢谢。

4

1 回答 1

0

当您将 Rotate 对象附加r到 frontFace 节点时,每个此类节点都会解释 Rotate 对象在该节点自己的坐标系中的坐标。每个立方体都在自己的坐标系中将其中心定义为 (0, 0, -100),因此围绕该枢轴点旋转会使立方体围绕自己的中心旋转。

您想要的是将所有 frontFace 节点围绕同一坐标系(它们的父组的坐标系)中的单个枢轴点旋转。

然后,您可以使用parentToLocal方法将该枢轴点重复转换为每个 frontFace 的坐标系,并基于该“本地”枢轴点应用一个新的 Rotate 实例。

public void rotate(int angle) {
    // These coordinates are in the parent Group's coordinate system.
    Point3D pivot = new Point3D(0, 0, -100);

    for (int x = 0; x < 3; x++) {
        for (int y = 0; y < 3; y++) {
            Node cube = frontFace[x][y];

            Point3D localPivot = cube.parentToLocal(pivot);

            Rotate r = new Rotate(angle,
                localPivot.getX(), localPivot.getY(), localPivot.getZ(),
                Rotate.Z_AXIS);
            cube.getTransforms().add(r);
        }
    }
}
于 2020-08-08T20:09:30.037 回答