transforming vector by matrix

Started by
5 comments, last by Zakwayda 17 years, 10 months ago
I'm attempting to transform a vector by a matrix. My matrix is held in a one dimensional array and has column vectors. I previously thought I had this code right, but then again, I've never actually used it in anything that has worked (not necessarily due to this code). So, is this right? Will this properly transform a vector by a matrix? Or must the top line elements be 0,1,2 as I vaguely suspect in my sleepy state?

util::CVector3d CMatrix::operator*(const util::CVector3d& v)
{
	CVector3d res;

	res.x = (m_mat[0]*v.x) + (m_mat[4]*v.y)  + (m_mat[8]*v.z) + m_mat[12];
	res.y = (m_mat[1]*v.x) + (m_mat[5]*v.y)  + (m_mat[9]*v.z) + m_mat[13];
	res.z = (m_mat[2]*v.x) + (m_mat[6]*v.y)  + (m_mat[10]*v.z) + m_mat[14];

	return res;
}

Also, if someone could help me by explaining "homogeneous coordinates", that would be enlightening. Although I probably understand what it is, just not with all the big words (happens to me a lot). As far as I can see, if we're attempting to do calculations in 3 dimensions, we use 4 so we can do calculations in projective space. And projective space is when the coords are being projected to the screen. Am I in the ballpark?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Advertisement
Your function looks correct, assuming column vectors and column-major matrix layout. If it's intended to be an OpenGL-style matrix, those are the correct conventions. For that matter though, I think the same code would work for row vectors and row-major layout (except for the order of the function arguments).

Also, for various reasons it's a little suspect to define operator*() for a 4x4 matrix and a 3x1 or 1x3 vector ('point' in your case, actually), but that's another topic...
Your code is right if (1) you're using column vectors _and_ (2) column major order (or else row vectors _and_ row major order), and (3) the order of components is [x,y,z,w] where w denotes the homogneous co-ordinate.

(1) means that a matrix vector product is
matrix * column_vector
or else the alternative
row_vector * matrix

The (2) term defines how the 2 dimensional matrix is arranged in the linear memory. E.g. for column-major order the indices would be
 0  4  8 12 1  5  9 13 2  6 10 14 3  7 11 15

while for row-majow order they would be
 0  1  2  3 4  5  6  7 8  9 10 1112 13 14 15


Several explanations for homogeneous co-ordinates exists. E.g. they could be understood as a numerical extension to distinct location vectors and direction vectors. In a vector algebra you could say that some rules exist like
point + direction = point
direction + direction = direction
but there is no way to express these by using affine vectors only (where
vector + vector = vector
is the one and only addition rule).
For this to understand you must know that location vectors are to be transformed in another way than direction vectors are: Location vectors have an origin and hence are sensitive to translation, while direction vectors have no origin and are hence not sensitive to translation.

So you could understand homogeneous vectors with w==0 as direction vectors, and with w==1 as location vectors (and with other w as unnormalized location vectors that could be normalized to w==1 by division). Setting such vectors into above rules you can see that the w component is behaved well w.r.t. the algebra.

Moreover, performing a (transformation) matrix by vector product, you can see that the 2 affine rules
new_position := transformation * position + translation
new_direction := transformation * direction
can be expressed simply by
new_homogeneous := transformation * homogeneous
making the things easier.

And at last, projections like the perspective projection could be expressed in homogeneous co-ordinates by matrix vector products, too.


EDIT: One time more lost against jyk's speed.
Quote:Original post by haegarr
The (2) term defines how the 2 dimensional matrix is arranged in the linear memory. E.g. for column-major order the indices would be
 0  4  8 12 1  5  9 13 2  6 10 14 3  7 11 15

while for row-majow order they would be
 0  1  2  3 4  5  6  7 8  9 10 1112 13 14 15



Hmmm, so, for column major order, which means that I'll have column vectors, the indices will be set out in memory like so: [x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, w1, w2, w3, w4]

And for row major order, which means that the matrix will contains row vectors, the indices will be set out in memory like so: [x1, y1, z1, w1, x2, y2, z2, w2, x3, y3, z3, w3, x4, y4, z4, w4]

Is this correct?

In any case, more questions are bound to follow tomorrow when I wake up again. But, for the moment, thanks guys.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Quote:Original post by Endar
...
Hmmm, so, for column major order, which means that I'll have column vectors,
...
And for row major order, which means that the matrix will contains row vectors,...

Column-major doesn't require column vectors and row-major doesn't require row vectors. It's just done that way in most API's for convenience.

Also, the order of the matrix elements in memory when using column-major/column vectors is the same as when using row-major/row vectors. You can mix OpenGL and D3DX matrices. The primary difference is the notation (and the order of operands).
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Quote:Original post by JohnBolton
Quote:Original post by Endar
...
Hmmm, so, for column major order, which means that I'll have column vectors,
...
And for row major order, which means that the matrix will contains row vectors,...

Column-major doesn't require column vectors and row-major doesn't require row vectors. It's just done that way in most API's for convenience.

Also, the order of the matrix elements in memory when using column-major/column vectors is the same as when using row-major/row vectors. You can mix OpenGL and D3DX matrices. The primary difference is the notation (and the order of operands).


So, internally, there's no difference in the matrix functions or the memory.

But, if we had matrices A and B, to get matrix C, for one of the notations (row or column) we'd have to do A*B , and for the other notatation, to get matrix C, we'd have to do B*A.

Is this right?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Quote:Original post by Endar
So, internally, there's no difference in the matrix functions or the memory.

But, if we had matrices A and B, to get matrix C, for one of the notations (row or column) we'd have to do A*B , and for the other notatation, to get matrix C, we'd have to do B*A.

Is this right?
Pretty close. With column/column vs. row/row, the layout in memory is indeed the same. As for the various matrix funtions, some examples (such as yours) can be coded the same for each convention, while others (such as matrix-matrix multiplication) will be different.

As for the second question, again that's close, but it's not so much 'get matrix C' as 'get a particular transform C'. If you want to apply two transforms A and B to a column vector, you write:
v' = B*A*v
To a row vector:
v' = v*A*B
This is what motivates the different multiplication orders.

This topic is closed to new replies.

Advertisement