Does anyone know of a fast way to tell if a matrix has non-uniform scaling?

Started by Jan 12 2013 09:45 AM

,
7 replies to this topic

Posted 12 January 2013 - 09:45 AM

Does anyone know of a fast way to tell if a matrix has non-uniform scaling?

Posted 12 January 2013 - 11:46 AM

You can probably get the length of the basis vectors of the matrix (for example the length of the first, second and third row). This gives you the x, y and z scale. If they are not equal to each other there is non-uniform scaling.

Not sure if this is the best/safest or fastest method though, but it is definitely faster than doing full polar/spectral decomposition.

**Edited by Buckshag, 12 January 2013 - 11:48 AM.**

Posted 12 January 2013 - 01:20 PM

If a matrix is the composition of a rotation and a uniform scaling, its three columns should be orthogonal to each other and have the same length.

Posted 13 January 2013 - 04:30 AM

Thanks for the answer. This is the formula I came up with finally:

// note: this is opengl type matrix bool Matrix::IsUnformScaling() const { const float THRESHOLD = 0.01f; float xLen = m[0]*m[0] + m[1]*m[1] + m[2]*m[2]; float yLen = m[4]*m[4] + m[5]*m[5] + m[6]*m[6]; float zLen = m[8]*m[8] + m[9]*m[9] + m[10]*m[10]; return fabsf(xLen - yLen) < xLen*THRESHOLD && fabsf(xLen - zLen) < xLen*THRESHOLD; }

I tested it and it seems to work ;)

Posted 13 January 2013 - 01:01 PM

I can construct a matrix that has non-uniform scaling in it and passes your test, though...

EDIT: More explicitly,

EDIT: More explicitly,

m[0] = 0.8; m[1] = 0.6; m[2] = 0.0; m[4] = 0.6; m[5] = 0.8; m[6] = 0.0; m[8] = 0.0; m[9] = 0.0; m[10] = 1.0;

**Edited by Álvaro, 13 January 2013 - 01:07 PM.**

Posted 13 January 2013 - 02:24 PM

I can construct a matrix that has non-uniform scaling in it and passes your test, though...

EDIT: More explicitly,m[0] = 0.8; m[1] = 0.6; m[2] = 0.0; m[4] = 0.6; m[5] = 0.8; m[6] = 0.0; m[8] = 0.0; m[9] = 0.0; m[10] = 1.0;

Ok, my bad.

do you have a solution perchance?

Posted 13 January 2013 - 07:57 PM

I posted that already, although perhaps my description was too succinct. You also need to verify that those three vectors are orthogonal to each other (check all three pairs).

EDIT: To be complete, you should also verify that the transformation preserves orientation (its determinant is positive).

bool are_orthogonal(Vector3 v, Vector3 w) { static float const tolerance = 1e-6; float dp = dot_product(v,w); return dp * dp < dot_product(v,v) * dot_product(w,w) * tolerance; }

EDIT: To be complete, you should also verify that the transformation preserves orientation (its determinant is positive).

**Edited by Álvaro, 13 January 2013 - 07:58 PM.**

Posted 14 January 2013 - 12:37 PM

Ok. I tried that out and it seems to work well.

Thanks for your help Alvaro ;)