libgdx / libgdx

Desktop/Android/HTML5/iOS Java game development framework
http://www.libgdx.com/
Apache License 2.0
23.42k stars 6.44k forks source link

Matrix4#getRotation() is calculating incorrect rotation for one particular matrix #3250

Closed vinaysshenoy closed 9 years ago

vinaysshenoy commented 9 years ago

We use a custom model format(extracted from a collada version of the asset) where the node transforms (translation, rotation and scale) are saved as a single 4x4 matrix in row major order(similar to collada). We have written a custom model loader that parses this out into models.

We use a Matrix4 to extract the individual components out and set it to the model, like so.

            Matrix4 nodeMatrixCache = new Matrix4();

            //Convert to column order. node.matrix.matrix is a float array of size 16
            nodeMatrixCache.set(node.matrix.matrix).tra();

            final Vector3 translation = new Vector3();
            final Vector3 scale = new Vector3();
            final Quaternion rotation = new Quaternion();

            nodeMatrixCache.getRotation(rotation, true);
            nodeMatrixCache.getTranslation(translation);
            nodeMatrixCache.getScale(scale);

            modelNode.rotation = rotation;
            modelNode.scale = scale;
            modelNode.translation = translation;

We are using the exact same code for multiple assets, and all are loading perfectly fine, except for one. The matrix is [-0.003857 -2.209997 0.000000 0.000000 
0.000000 0.000000 2.210000 0.012000 
-2.209997 0.003858 0.000000 0.000000 
0.000000 0.000000 0.000000 1.000000] (in row-major order).

This one particular asset gives a rotation of [-0.49956352 0.22691926 0.5004361 0.49956352] when we extract the rotation.

However, if we convert the collada to G3DJ, the rotation that we see in the node is [-0.499563 0.500436 0.500436 0.499563]. Index 1 of the rotation matrix has a drastically different value, and it's screwing up the model's rotation when it appears.

Any idea what the problem could be?

P.S: The reason we are not using G3DB is because we need to stream the assets from the network, so we have a custom format that is much smaller than G3DB.

xoppa commented 9 years ago

Please provide an sscce showing the issue you're reporting.

Btw, you really should reconsider your approach, extracting values from a matrix like that is going to cause issues.

vinaysshenoy commented 9 years ago

I'm pretty new to this, and I don't know what an sscce is. Would you please enlighten me?

Yes, this is a temporary stop gap measure. I'm planning to set up a pipeline in the near future which will use fbx-conv to convert to g3dj and then we will convert g3dj to a new format, which will enable us to move away from this approach.

But for the present, we need to get some of the basic stuff working before we can go ahead with that. On Jul 1, 2015 11:02 PM, "Xoppa" notifications@github.com wrote:

Please provide an sscce showing the issue you're reporting.

Btw, you really should reconsider your approach, extracting values from a matrix like that is going to cause issues.

— Reply to this email directly or view it on GitHub https://github.com/libgdx/libgdx/issues/3250#issuecomment-117759006.

vinaysshenoy commented 9 years ago

Never mind, I got what an sscce is. I'll add one right now.

vinaysshenoy commented 9 years ago

Here's an example -

public class DesktopLauncher {

    public static void main(String[] arg) {

        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();

        final Game game = new Game();
        new LwjglApplication(doowupScene, config);

        Matrix4 matrix4 = new Matrix4();

        //Column order matrix
        matrix4.set(new float[]{
                -0.003857f, 0.0f, -2.209997f, 0.0f,
                -2.209997f, 0.0f, 0.003858f, 0.0f,
                0.0f, 2.21f, 0.0f, 0.0f,
                0.0f, 0.012f, 0.0f, 1.0f
        });

        final Vector3 translation = new Vector3();
        final Vector3 scale = new Vector3();
        final Quaternion rotation = new Quaternion();

        matrix4.getRotation(rotation, true);
        matrix4.getTranslation(translation);
        matrix4.getScale(scale);

        //Expected output: [-0.499563,  0.500436,  0.500436,  0.499563]
        Gdx.app.log("Test", "Rotation: " + rotation.toString());

        //Expected output: [ 2.210000,  2.210000,  2.210000]
        Gdx.app.log("Test", "Scale: " + scale.toString());

        //Expected output: [ 0.000000,  0.012000,  0.000000]
        Gdx.app.log("Test", "Translation: " + translation.toString());
    }
}
xoppa commented 9 years ago

Thanks, should be fixed now

vinaysshenoy commented 9 years ago

OK, that was quick! Thanks! On Jul 2, 2015 1:42 PM, "Xoppa" notifications@github.com wrote:

Thanks, should be fixed now

— Reply to this email directly or view it on GitHub https://github.com/libgdx/libgdx/issues/3250#issuecomment-117952924.