W3C home > Mailing lists > Public > www-style@w3.org > September 2010

Re: [css3-3d-transforms] matrix3d() uses column-major order, but CSSMatric properties row-major ?

From: Chris Marrin <cmarrin@apple.com>
Date: Wed, 08 Sep 2010 17:52:09 -0700
Cc: "www-style@w3.org list" <www-style@w3.org>
Message-id: <C1D2DFC4-70AE-47C3-AA65-2FDE37B44893@apple.com>
To: Sylvain Galineau <sylvaing@microsoft.com>

On Sep 8, 2010, at 4:07 PM, Sylvain Galineau wrote:

> The matrix3d() transform uses column-major order [1]:
> 
> # matrix3d(...)
> # specifies a 3D transformation as a 4x4 homogeneous matrix of 16 values in column-major order.
> 
> The CSSMatrix interface, however, describes its property names in row-major order:
> 
> # m11-m44 
> # of type float Each of these attributes represents one of the values in the 4x4 matrix. For instance 
> # m12 represents the value in the 2nd column of the first row.
> 
> Is that intentional ?

Ok, first of all let me apologize in advance if I get this explanation muddled. Matrix order gives me a huge headache and I'd really like to say, "look it just works so don't worry about it" :-)

But knowing that such an attitude, in addition to being rude, goes against the nature of spec writing. So here goes. I also want to apologize for being pedantic. I do it because it's the only way I can keep it straight.

A 4x4 column major matrix is one where the sequential numbers of the matrix proceed down and then across. That is (starting at 1):

	1	5	9	13
	2	6	10	14
	3	7	11	15
	4	8	12	16

It helps me to look at a matrix like this as 4 vectors, each with 4 components (so called homogeneous vectors), (x, y, z, w). For our purposes we will ignore the w term. If you think of the matrix as a camera, then the first column is called the 'right' vector, the 2nd column is the 'up' vector and the third column is 'forward'. The 4th column is not a vector, but a position; the position of the camera. I say all this because in my mind that makes it easier to visualize what each column is used for. Let's look at that matrix:

	rightX		upX			forwardX	positionX
	rightY		upY			forwardY	positionY
	rightZ		upZ			forwardZ	positionZ
	0			0			0			1

If you have a camera in its "identity" orientation (sitting right side up, at home position, looking at the page) you get these vectors

	right: (1, 0, 0)		up:(0, 1, 0)		forward:(0, 0, 1)		position:(0, 0, 0)

Plug those into the matrix and you get

	1		0		0		0
	0		1		0		0
	0		0		1		0
	0		0		0		1

The identity matrix! If you rotate about the X axis, you would leave the right vector alone and rotate the up and forward vectors so they remain perpendicular to each other. For scale you make the vectors longer or shorter. For skew you change one of the vectors so it's no longer perpendicular to the others. You can visualize a box being spun, stretched or warped by the motion of these vectors. 

Anyway, I just wanted to say all that to give you a clear picture of what the matrix "looks like".  Sorry if that's too much detail, but it really does help me keep all this straight. 

The spec has attributes that represent each matrix entry. For instance, m23 represents column 2, row 3. There was some confusion about this because it seems like the numbers should be row, column. But since these are column major matrices, it was agreed that having the column number first made more sense. It really doesn't make much difference as long as the numbering is consistent. 

So the matrix looks like this:

	m11	m21	m31	m41
	m12	m22	m32	m42
	m13	m23	m33	m43
	m14	m24	m34m	m44

and values are passed to matrix3d() like this:

	matrix3d(m11, m12, m13, m24, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44)

Passing them in that order keeps the elements of the 4 "vectors" together. 

So the line in the spec you show is wrong. It should say, "m12 represents the value in the 2nd row of the first column". We should also make the order of parameters passed to matrix3d() clear. I don't think it is clear currently.

Does that make things more clear? Or have I just confused the issue more?

-----
~Chris
cmarrin@apple.com
Received on Thursday, 9 September 2010 00:52:42 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 17:20:31 GMT