Jump to content
  • Advertisement
Sign in to follow this  
Endar

transforming vector by matrix

This topic is 4438 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

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?

Share this post


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

Share this post


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

Share this post


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

Share this post


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

Share this post


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

Share this post


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

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!