0

Given a 4x4 3d transformation matrix, what's the best way to compute whether it does more than scaling and translation? Specifically I would like to know if it rotates or skews the image.

I am using Cocoa so libraries like CoreGraphics and CoreAnimation are available.

ide
  • 19,942
  • 5
  • 64
  • 106

2 Answers2

2

Looking at a matrix with elements numbered like this:

[ a00 a01 a02 a03 ]
[ a10 a11 a12 a13 ]
[ a20 a21 a22 a23 ]
[ a30 a31 a32 a33 ]
  • A scaling transform has values other than 1.0 in elements a00, a11 and/or a22.
  • A translation matrix has values other than 0.0 in elements a03, a13 and/or a23.

If those are the only types of transformations you expect, all other values must match the identity matrix.

It's relatively rare to have non-identity values in the last row, unless you're dealing for example with projection matrices. If the matrix in question could potentially be of that form, you'll have to test for:

a30 == 0.0
a31 == 0.0
a32 == 0.0
a33 == 1.0

Other than that, you'll just have to test the non-diagonal elements of the upper-left 3x3 matrix to be zero:

a01 == 0.0
a02 == 0.0
a10 == 0.0
a12 == 0.0
a20 == 0.0
a21 == 0.0

Any of these values being non-zero would introduce some form of rotation/skew.

As always, be careful about comparing floating point values for equality. The values above will be exactly 0.0 if they were never set to anything else. But if the matrix is the result of some form of computation, you may have to test for the values being smaller than a small constant, instead of for exactly 0.0.

When testing the matrix values, be mindful about your matrix being stored in row- or column-major order. For example, if you matrix elements are stored in an array, element a03 will be at index 3 in row-major order, and at index 12 in column-major order.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
1

See Understanding 4x4 homogenous transform matrices if you lack the knowledge

Now if your transform is just:

  1. rotation

    then the axises stay perpendicular to each other and their size stays the same (usually unit vectors) but they get rotated.

  2. scaling

    changes only the size of the axis direction vectors so the axises must stay perpendicular to each other and does not change direction.

  3. translation

    this just moves the origin vector all the rest stays as was

  4. skew

    this breaks the orthogonality so axises will not be perpendicular to each other

If you put this together

scaling and translation should left axises parallel to global axises so:

  1. extract axis vectors X,Y,Z
  2. make them unit vectors
  3. compare them with global axises
  4. the projection part of matrix should be P=(0,0,0,1) ... bottom row

something like:

X/=|X|;
Y/=|Y|;
Z/=|Z|;

if ( fabs(fabs(dot(X,(1,0,0)))-1.0)
    +fabs(fabs(dot(Y,(0,1,0)))-1.0)
    +fabs(fabs(dot(Z,(0,0,1)))-1.0)
    +fabs(P.x-0.0)
    +fabs(P.y-0.0)
    +fabs(P.z-0.0)
    +fabs(P.w-1.0) > 1e-6) return "not just scaling&translation";

where:

|X|=sqrt(X.x*X.x+X.y*X.y+X.z*X.z);
dot(X,Y)=(X.x*Y.x)+(X.y*Y.y)+(X.z*Y.z);

[notes]

beware your matrix form I use OpenGL style matrices (column wise) if you have row wise matrices then you need to transpose ...

Community
  • 1
  • 1
Spektre
  • 49,595
  • 11
  • 110
  • 380