• Advertisement
Sign in to follow this  

Detect non-uniform scaling in matrix

This topic is 1829 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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;

Edited by Álvaro

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites
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).
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement