Matrix 3f rotation ?

I use odejava together with AgentFX for some simulations. Every (Ode)Body has a getRotation() which returns a matrix3f that I’d like to use with my A9Nodes.
However, A9nodes uses vector3f to set rotations.
How do I convert matrix3f to vector 3f that I can use in A9node.setRotation() ?

I assume the Vector3f represents the euler (yaw/pitch/roll) angles.

Use the getQuaternion of Body to get a rotation quaternion. From there, you need to convert the quaternion to the euler vector.

I have used this code before: http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
(note, you need to fix some compile problems with that code, hopefully you can work out where ;))

Cheers,

Will.

[quote]I assume the Vector3f represents the euler (yaw/pitch/roll) angles.

Use the getQuaternion of Body to get a rotation quaternion. From there, you need to convert the quaternion to the euler vector.

I have used this code before: http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
(note, you need to fix some compile problems with that code, hopefully you can work out where ;))

Cheers,

Will.
[/quote]
Thank you very much Will.
I don’t have the time for it now, but I guess I would be asking less questions if I took the time out to learn linear algebra…

I’m happy to propose you two ready-to-use functions I wrote for Gamma ( see http://gamma.dev.java.net ) :

Matrix3f to Vector3f :

public static final Vector3f rmToEa(Matrix3f m) {
        
        float angle_x, angle_y, angle_z, A, B, C, D, tr_x, tr_y;
        float[] mat = new float[16];
        mat[0] = m.m00;
        mat[1] = m.m10;
        mat[2] = m.m20;
        mat[4] = m.m01;
        mat[5] = m.m11;
        mat[6] = m.m21;
        mat[8] = m.m02;
        mat[9] = m.m12;
        mat[10] = m.m22;
        
        angle_y = D = (float) Math.asin(mat[2]); /* Calculate Y-axis angle */
        C = (float) Math.cos(angle_y);
        angle_y = (float) Math.toDegrees(angle_y);
        if ((float) Math.abs(C) > 0.005) /* Gimball lock? */
        {
            tr_x = mat[10] / C; /* No, so get X-axis angle */
            tr_y = -mat[6] / C;
            angle_x = (float) Math.toDegrees(Math.atan2(tr_y, tr_x));
            tr_x = mat[0] / C; /* Get Z-axis angle */
            tr_y = -mat[1] / C;
            angle_z = (float) Math.toDegrees(Math.atan2(tr_y, tr_x));
        } else /* Gimball lock has occurred */
        {
            angle_x = 0; /* Set X-axis angle to zero */
            tr_x = mat[5]; /* And calculate Z-axis angle */
            tr_y = mat[4];
            angle_z = (float) (float) Math.toDegrees(Math.atan2(tr_y, tr_x));
        }
        
        /* return only positive angles in [0,360] */
        if (angle_x < 0)
            angle_x += 360;
        if (angle_y < 0)
            angle_y += 360;
        if (angle_z < 0)
            angle_z += 360;
        
        return new Vector3f(angle_x, angle_y, angle_z);
        
    }

Vector3f to Matrix3f :


    public static Matrix3f eaToRm(Vector3f v) {
        
        float angle_x = (float) Math.toRadians(v.x);
        float angle_y = (float) Math.toRadians(v.y);
        float angle_z = (float) Math.toRadians(v.z);
        
        float A = (float) Math.cos(angle_x);
        float B = (float) Math.sin(angle_x);
        float C = (float) Math.cos(angle_y);
        float D = (float) Math.sin(angle_y);
        float E = (float) Math.cos(angle_z);
        float F = (float) Math.sin(angle_z);
        float AD = A * D;
        float BD = B * D;
        float[] mat = new float[16];
        mat[0] = C * E;
        mat[1] = -C * F;
        mat[2] = D;
        mat[4] = BD * E + A * F;
        mat[5] = -BD * F + A * E;
        mat[6] = -B * C;
        mat[8] = -AD * E + B * F;
        mat[9] = AD * F + B * E;
        mat[10] = A * C;
        mat[3] = mat[7] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
        mat[15] = 1;
        
        Matrix3f m = new Matrix3f();
        m.m00 = mat[0];
        m.m10 = mat[1];
        m.m20 = mat[2];
        m.m01 = mat[4];
        m.m11 = mat[5];
        m.m21 = mat[6];
        m.m02 = mat[8];
        m.m12 = mat[9];
        m.m22 = mat[10];
        
        return m;
        
    }

MagicSpark,

They look like handy methods.

A few comments: These methods will most likely be executed several times per frame, for example when synching the display objects. With that in mind do you really need to declare a float array in rmToEa? Also, a good trick with these performance critical methods is to pass in the object that the values will be written to (this allows for object reuse). E.g. rmToEa(Matrix3f m, Vertex3f v); Odejava uses this idea extensivly. We also have methods which don’t need to pass in the returned object, and these just create a new object (in your case, rmToEa(m, new Vector3f()) ).

Finally, is there any reason why you are returning the values in Degrees not Radians? My observation is that most display and physics libraries work in radians, and that fighting the trend is a loosing battle, and only ends up in double conversions.

Will.

I’m using degrees for my game, so I return degrees…
But I can return radians if you want ;D.
I’ll change the way the arguments are passed.