Rotate a 3D object on 3 axis in JavaFX properly
Asked Answered
B

2

9

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:

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

and did a setAngle() for each time I needed to rotate the object. This worked very well for only heading and roll until i decided that I need pitch too. Now a lot of tutorials for OpenGL and alike say that rotational matixes or quaternions are best for these type of rotations, but the javadoc lacks any usefull data regaring this.

Example: What happens when I rotate an object by 180 degrees on the y axis (and what should actually have happened in transparent blue) enter image description here Am I missing something? All help would be appreciated.

Barabarabarabas answered 9/5, 2015 at 21:54 Comment(0)
S
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.

Skippie answered 10/5, 2015 at 0:34 Comment(7)
Another awesome answer! Thank you for this, I really hit a roadblock on this issue.Barabarabarabas
I am unfortunately still having problems with determening the added up final yaw, roll and pitch angles relative to the scene #30817623Barabarabarabas
I saw your new question, I'll try to have a look at itPolyhydroxy
thank you so much for your very clear answer! it really helps me out.Glyphography
Why are your matrices different from the matrices here? en.wikipedia.org/wiki/Rotation_matrix#Basic_rotationsDelgado
@kuhaku Good point. I think they might have edited it? I checked this a few years ago, and the sign was the opposite. Anyway it is easy to verify and adjust based on your input for yaw, pitch and roll angles.Polyhydroxy
It may help to point out that rotations (and matrix multiplication) don't commute. That is to say the order of consecutive rotations matter. Any two or more rotations about different axes is equivalent to a single rotation about a composite axis. However, the composite answer is different if you change the order of rotations. Jose's calculation is for a specific product of three matrices, that is rotations in a specific order. I believe it is A=AzAyAx which would be rotate about x axis first, y second and z thirdNegotiant
I
1

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));
Instrument answered 29/5, 2019 at 16:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.