Rotate a 3D object on 3 axis in JavaFX properly

后端 未结 2 526
面向向阳花
面向向阳花 2020-12-09 13:52

So the method that I\'ve used so far to rotate objects in JavaFX was that I layered it in 3 groups, each of them with a Rotate attached and locked to a single axis like so:<

相关标签:
2条回答
  • 2020-12-09 14:15

    There's a reason why all those tutorials point to rotational matrices: in 3D you can't perform simultaneous rotations one by one, you need to perform them at once. Since JavaFX only uses one angle and one axis, you have to provide the way to convert three rotations over three axes in just one angle and one axis.

    A while ago I went to all the math behind these operations in my blog post about using Leap Motion to get the three rotations of your hand (pitch, yaw, roll) to rotate a 3D model.

    So basically, from three rotations: pitch (around its X axis), yaw (around its Y axis) and roll (around its Z axis), you have these matrices:

    Matrices

    and if you combine them you have one single matrix:

    Matrix

    Without further explanations, the angle and the rotation unitary axis components can be computed from:

    eigenvalues

    Which can be written as:

    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));                    
        }
    }
    

    where alf is roll, bet is pitch and gam is yaw.

    You can find the full project here.

    0 讨论(0)
  • 2020-12-09 14:28

    I can offer a solution. But it is a bit uncivilized and might be a discouraged practice.

    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));
    
    0 讨论(0)
提交回复
热议问题