Hey eveyone,

I think I came accross problems with scale and rotation in the Matrix4f class.

I found this while working on the blender importer when sometimes I had problems with nodes transformations

Consider this piece of code:

[java]

public class Transformations extends SimpleApplication {

```
@Override
public void simpleInitApp() {
Geometry geometry = new Geometry("box", new Box(0.5f, 1f , 0.5f));
Material defaultMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
defaultMaterial.setColor("Color", ColorRGBA.DarkGray);
geometry.setMaterial(defaultMaterial);
Matrix4f m = new Matrix4f();
//FIRST LINE TO UNCOMMENT
//m.setRotationQuaternion(new Quaternion(new float[] {FastMath.HALF_PI, 0, 0}));
//SECOND LINE TO UNCOMMENT
//m.setScale(1, 0.5f, 1);
System.out.println(m);
Transform t = new Transform();
t.setRotation(m.toRotationQuat());
t.setTranslation(m.toTranslationVector());
t.setScale(m.toScaleVector());
geometry.setLocalTransform(t);
rootNode.attachChild(geometry);
}
public static void main(String[] args){
new Transformations().start();
}
```

}

[/java]

In a result you will see a box that has the height of 2. Quite simple

Its transformation matrix is:

Matrix4f

[

1.0 0.0 0.0 0.0

0.0 1.0 0.0 0.0

0.0 0.0 1.0 0.0

0.0 0.0 0.0 1.0

]

Now uncomment the first line I pointed out. The result should be a ‘lying’ box.

Its transformation matrix:

Matrix4f

[

1.0 0.0 0.0 0.0

0.0 0.0 -1.0 0.0

0.0 1.0 0.0 0.0

0.0 0.0 0.0 1.0

]

And now uncomment the second line. I would expect that the box will shrink to the size of 1x1x1.

But instead, its size did not change. The transformation matrix is still:

Matrix4f

[

1.0 0.0 0.0 0.0

0.0 0.0 -1.0 0.0

0.0 1.0 0.0 0.0

0.0 0.0 0.0 1.0

]

even though we set the scale to [1, 0.5, 1].

The problem here is with this method in Matrix4f:

[java]

public void setScale(float x, float y, float z) {

m00 *= x;

m11 *= y;

m22 *= z;

}

[/java]

It works only when there is no rotation. The scale should affect the whole forward (**F**), up (**U**) and side (**S**) vectors of the matrix.

Which are the first, second and third columns of the matrix).

My suggestion is to fix it with these methods:

[java]

public void setScale(float x, float y, float z) {

Vector3f v = new Vector3f(m00, m10, m20);

v.normalizeLocal().multLocal(x);

m00 = v.x;

m10 = v.y;

m20 = v.z;

```
v.set(m01, m11, m21);
v.normalizeLocal().multLocal(y);
m01 = v.x;
m11 = v.y;
m21 = v.z;
v.set(m02, m12, m22);
v.normalizeLocal().multLocal(z);
m02 = v.x;
m12 = v.y;
m22 = v.z;
}
public void setScale(Vector3f scale) {
this.setScale(scale.x, scale.y, scale.z);
}
```

[/java]

When you do that and run the program you will notice that the box had indeed shrinked but it is not properly rotated.

Even though its transformation matrix is now fine:

Matrix4f

[

1.0 0.0 0.0 0.0

0.0 0.0 -1.0 0.0

0.0 0.5 0.0 0.0

0.0 0.0 0.0 1.0

]

The problem is with extracting the rotation quaternion from the matrix.

The **F**, **U** and **S** vectors should first be normalized so that the quaternion is extracted without ‘scale noise’.

The patch for that is simple. In the Quaternion class, at the begining of the method:

[java]

public Quaternion fromRotationMatrix(float m00, float m01, float m02,

float m10, float m11, float m12,

float m20, float m21, float m22);

[/java]

add the following lines:

[java]

float lengthSquared = m00 * m00 + m10 * m10 + m20 * m20;

if (lengthSquared != 1f && lengthSquared != 0f){

lengthSquared = 1.0f / FastMath.sqrt(lengthSquared);

m00 *= lengthSquared;

m10 *= lengthSquared;

m20 *= lengthSquared;

}

lengthSquared = m01 * m01 + m11 * m11 + m21 * m21;

if (lengthSquared != 1f && lengthSquared != 0f){

lengthSquared = 1.0f / FastMath.sqrt(lengthSquared);

m01 *= lengthSquared;

m11 *= lengthSquared;

m21 *= lengthSquared;

}

lengthSquared = m02 * m02 + m12 * m12 + m22 * m22;

if (lengthSquared != 1f && lengthSquared != 0f){

lengthSquared = 1.0f / FastMath.sqrt(lengthSquared);

m02 *= lengthSquared;

m12 *= lengthSquared;

m22 *= lengthSquared;

}

[/java]

The code is identical to Vector3f.normalize() method. But I used the code to avoid instantiating additional vectors since this method might be called quite often.

If you run the code now, you will notice that the box is shrinked and properly rotated.

Let me know what do you think about those changes. I will do more testing with transformations but maybe someone will notice errors here

Cheers