9

因此,到目前为止,我在 JavaFX 中用于旋转对象的方法是将其分层为 3 组,每组都附加一个 Rotate 并锁定到单个轴,如下所示:

    Rotate heading, roll, pitch;
    Group normalrotate, rollrotate, verticalrotate;

    heading.setAxis(new Point3D(0,1,0));
    normalrotate.getTransforms().add(heading);

    roll.setAxis(new Point3D(0,0,1));
    rollrotate.getTransforms().add(roll);

    pitch.setAxis(new Point3D(1,0,0));
    verticalrotate.getTransforms().add(pitch);

每次我需要旋转对象时都做了一个 setAngle() 。这仅适用于航向和滚动,直到我决定我也需要俯仰。现在很多 OpenGL 等教程都说旋转矩阵或四元数最适合这些类型的旋转,但是 javadoc 缺乏任何有用的数据。

示例:当我在 y 轴上将对象旋转 180 度时会发生什么(以及在透明蓝色中实际应该发生的情况) 在此处输入图像描述 我错过了什么吗?所有帮助将不胜感激。

4

2 回答 2

13

所有这些教程都指向旋转矩阵是有原因的:在 3D 中,您不能一个一个地同时执行旋转,您需要一次执行它们。由于 JavaFX 只使用一个角度和一个轴,因此您必须提供一种方法,将三个轴上的三个旋转转换为一个角度和一个轴。

不久前,我在我的博客文章中讨论了这些操作背后的所有数学知识,关于使用 Leap Motion 获得手的三个旋转(俯仰、偏航、滚动)来旋转 3D 模型。

所以基本上,从三个旋转:俯仰(围绕它的 X 轴)、偏航(围绕它的 Y 轴)和滚动(围绕它的 Z 轴),你有这些矩阵:

矩阵

如果你把它们结合起来,你就有一个单一的矩阵:

矩阵

无需进一步解释,角度和旋转单位轴分量可以通过以下公式计算:

特征值

可以写成:

private void matrixRotateNode(Node n, double alf, double bet, double gam){
    double A11=Math.cos(alf)*Math.cos(gam);
    double A12=Math.cos(bet)*Math.sin(alf)+Math.cos(alf)*Math.sin(bet)*Math.sin(gam);
    double A13=Math.sin(alf)*Math.sin(bet)-Math.cos(alf)*Math.cos(bet)*Math.sin(gam);
    double A21=-Math.cos(gam)*Math.sin(alf);
    double A22=Math.cos(alf)*Math.cos(bet)-Math.sin(alf)*Math.sin(bet)*Math.sin(gam);
    double A23=Math.cos(alf)*Math.sin(bet)+Math.cos(bet)*Math.sin(alf)*Math.sin(gam);
    double A31=Math.sin(gam);
    double A32=-Math.cos(gam)*Math.sin(bet);
    double A33=Math.cos(bet)*Math.cos(gam);

    double d = Math.acos((A11+A22+A33-1d)/2d);
    if(d!=0d){
        double den=2d*Math.sin(d);
        Point3D p= new Point3D((A32-A23)/den,(A13-A31)/den,(A21-A12)/den);
        n.setRotationAxis(p);
        n.setRotate(Math.toDegrees(d));                    
    }
}

哪里alf是滚动,bet是俯仰,gam是偏航。

你可以在这里找到完整的项目。

于 2015-05-10T00:34:07.810 回答
1

我可以提供一个解决方案。但这有点不文明,可能是一种不鼓励的做法。

Node[] my3dModel = get3DModel();//the method creates a mesh (I suppose that you used Interactive mesh, but it's not important here)
Pane paneForMyModel = new Pane();
paneForMyModel.getChildren.addAll(my3dModel);//you add your model to this pane
//and now
paneForMyModel.getTransforms().add(new Rotate(angle, axis));
于 2019-05-29T16:47:48.140 回答