Matrix operator...

Started by
6 comments, last by back2music 14 years ago
Hi I seemed to have an error in and old code i digged up. The error was related to the matrix class operator* and some confusion in which order the operators argument comes into the function. Soo please validate what is the correct order of arguments to a operator when doing matrix multiplication. for example consider a*b; Is "this" the left-side (a), and m the right-side (b) according to the function? In my previous code I had to reverse the order in MatrixMultiply, that is exchange arguments this.ref() and m.ref(). So either I didn't understand which arguments was left-/right-side in the operator or the multiply function was wrong. If this function below is correct, then the multiply was originally wrong. Matrix Matrix::operator*(Matrix &m) { Matrix tmp; MatrixMultiply(tmp.ref(), this->ref(), m.ref()); return tmp; }
Advertisement
Row-major matrices used by DirectX produces results equal to the left operand followed by the right operand.

Column-major matrices used by OpenGL produce results equal to the right operand followed by the left operand.

There is no right or wrong answer. You have mixed up the major-ness of your matrices. Pick one and stick with it.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

The result of a matrix multiplication A * B is mathematically defined in explicit terms. You should ever implement the operator w.r.t. that definition, or else confusion will emerge! You should further implement it as non-member function.

Because matrix multiplication isn't commutative, you'll probably come to cases where you don't want to distinct "on the left" or "on the right" (what would simply be possible with operator*) but "on the local side" or "on the global side". Now, here comes the problem of column vs. row vectors into play EDIT, as already mentioned by YogurtEmperor/EDIT. To avoid any confusion, it would IMHO be best to implement 2 non-member functions that explicitely express their behaviour in their names, e.g.
inline Matrix mulWithLocal( Matrix const& matrix, Matrix const& local );
inline Matrix mulWithGlobal( Matrix const& matrix, Matrix const& global );
(Made them inlined to avoid performance penalties.) Then implement the both helper routines w.r.t. the vector convention of your choice utilizing the operator*.

The only issue with the solution above is IMHO that it needs more typing than a simple *.


Just my 2 €-Cent.

[Edited by - haegarr on April 24, 2010 10:43:24 AM]
Quote:Original post by haegarr
Now, here comes the problem of column vs. row vectors into play, as already mentioned by YogurtEmperor.
YogurtEmperor was actually referring to matrix majorness (a different issue).
Quote:Original post by YogurtEmperor
Row-major matrices used by DirectX produces results equal to the left operand followed by the right operand.

Column-major matrices used by OpenGL produce results equal to the right operand followed by the left operand.
It sounds like you might be confusing matrix 'majorness' with vector notation convention. When you say (e.g.) 'equal to the left operand followed by the right operand', I assume you mean that the resulting transform is equal to the transform represented by the matrix on the left, followed by the transform represented by the matrix on the right (as would be the case in DirectX). However, this doesn't have anything to do with matrix majorness; rather, it has to do with whether row vectors or column vectors are being used.

In any case, this shouldn't have any impact on how the '*' operator is implemented for matrices; matrix multiplication is defined the same way (and should be implemented the same way) regardless of what vector notation convention is being used.
Quote:Original post by jyk
Quote:Original post by haegarr
Now, here comes the problem of column vs. row vectors into play, as already mentioned by YogurtEmperor.
YogurtEmperor was actually referring to matrix majorness (a different issue).
Uhh, I've read it in a hurry. You're right, of course. However,
Quote:Original post by jyk
In any case, this shouldn't have any impact on how the '*' operator is implemented for matrices; matrix multiplication is defined the same way (and should be implemented the same way) regardless of what vector notation convention is being used.
is nevertheless exactly what I meant :)
A good way to keep track of this is to wrap your multiplication routine in another named member function, such as Concatenate. Let this function take care of the funny business of matrix multiplication order. This way client code need only worry about which transform should be concatenated, and not the (somewhat arbitrary) way in which this is accomplished.
Quote:for example consider a*b;

Is "this" the left-side (a), and m the right-side (b)
according to the function?


Yes for all operators. a * b is the equivalent of a.operator*(b), so "this" is the left hand side, and the parameter is the right hand side.
Quote:Original post by taz0010
Quote:for example consider a*b;

Is "this" the left-side (a), and m the right-side (b)
according to the function?


Yes for all operators. a * b is the equivalent of a.operator*(b), so "this" is the left hand side, and the parameter is the right hand side.


As I suspected, I just forgot the logic around the operators and became unsure whatever was right soo thank you all!

It's been 10 years since I worked with software development before I completely quit coding soo these little things are easy to forget.

My old library routine for matrix multiplication was indeed in the incorrect order, it calculated B*A when it should have calculated A*B (I never tested them when I wrote them a long time ago since I used a sdk at the time).

Once again, thank you all for your help!









This topic is closed to new replies.

Advertisement