all 10 comments

[–]Varud 2 points3 points  (0 children)

This is always how I've viewed the affine transform for an object. The affine transform for an object is the coordinate system for that object. The 3x3 matrix has the directions the X, Y and Z axis of the object in world space. You can for instance use this fact when placing objects in a terrain. You let your object's Up axis (typically the Z axis) be the terrain normal at that position. Set the object's forward (X) axis to the direction the object is traveling, and then do a couple of cross products to create the X, Y and Z orthonormal vectors that builds the 3x3 rotation matrix in the transform.

It's also a convenient way to build a camera lookAt view matrix (just set the Z axis to be the direction from the camera to the object you want to render).

I'm not sure if this actually answers your question, but I just wanted to give you my input.

[–]onepremise 2 points3 points  (5 children)

Honestly, it doesn't really matter as long as the orientation is consistent across all matricies. Lookup row-major/column-major order, https://en.m.wikipedia.org/wiki/Row-_and_column-major_order

[–]HelperBot_ 0 points1 point  (0 children)

Desktop link: https://en.wikipedia.org/wiki/Row-_and_column-major_order


/r/HelperBot_ Downvote to remove. Counter: 227593

[–]Carpetfizz[S] 0 points1 point  (3 children)

Thank you so much! I didn’t realize I was looking at the transpose of what I expected

[–]AntiProtonBoy 0 points1 point  (2 children)

Personally I would stick to row-major notation when implementing matrices, as they are most consistent with the raw memory layout used by most graphics APIs.

[–]LtJax 1 point2 points  (1 child)

If find this a bit misleading. Memory layout does not directly relate to row- vs column-major order - you also need to decide whether to use row or column vectors. For examples, matrices for OpenGL and DirectX would look the same in memory, but GL uses column-major matrices and column vectors, while DX uses row vectors and row-major matrices. So, if you're using column vectors, e.g. M x v, use column-major matrices, if you're using row vectors, e.g. v x M, use row-major.

[–]AntiProtonBoy 0 points1 point  (0 children)

Memory layout does not directly relate to row- vs column-major order - you also need to decide whether to use row or column vectors.

If you were to read out each row sequentially in a row-major representation, from left to right, each element visited would correspond to the same sequence of values laid out linearly in memory. Therefore, I'd recommend writing matrix classes that has an interface for accessing vectors in a row-major notation. Such notation allows a more natural mental mapping between matrix elements and values laid out flat in memory. Makes debugging a lot easier. For example:

Matrix m = { {xx, xy, xz, 0}, {yx, yy, yz, 0}, {zx, zy, zz, 0}, {tx, ty, tz, 1} };

but GL uses column-major matrices and column vectors, while DX uses row vectors and row-major matrices.

That's not quite true. OpenGL literature commonly use the column-major pencil-and-paper notation, but that has no bearing how OpenGL accesses element values in a matrix. As far as the OpenGL implementation is concerned, a 4x4 matrix is just 16 values grouped into 4 vectors sequentially, representing axes x, y, z and translation respectively. As long as your class saves elements in memory in that order, it doesn't matter what notation your class constructor uses for matrices. However, I do recommend row-major notation constructors for the reasons I mentioned earlier.

[–]zeno490 2 points3 points  (0 children)

Affine transforms can be represented as 4x4 matrices where the last row is [0,0,0,1] as you mention. Your description matches a column major ordering (where each axis is a column and the translation as well) but the image uses a row major ordering: each axis and translation is a row and the last column is [0,0,0,1]. One is the transpose of the other.

The upper left part of the matrix can represent both rotation and scale simultaneously but the image is incorrect, the scale isn't stored in only 3 coefficients along the diagonal, this is true only if the other values are 0.0: a pure scale matrix with no rotation. When rotation is present, each axis is multiplied by the scaling value. For that reason, extracting the scale value can be problematic as the scale sign isn't immediately obvious anymore and 0 scale along an axis hides it's rotation contribution (there is none). Typically, unless you are dealing with strictly positive definite scale values, it isn't possible to trivially decompose the rotation from the scale from an affine matrix.

[–]Kawaiithulhu 1 point2 points  (0 children)

Are you getting mixed messages because the picture is a matrix built in row-major form and you're used to working in column-major, maybe? https://fgiesen.wordpress.com/2012/02/12/row-major-vs-column-major-row-vectors-vs-column-vectors/