Jump to content
  • Advertisement
Sign in to follow this  
ProjectinMatrix

Arbirtary axis rotation?

This topic is 2610 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 playing with some matrix math, i have a question. Does arbirtary axis rotation offer any advantage over concatenating 3 rotation matrices?

Example: Matrix result = Matrix::MakeXRotation(x) * Matrix::MakeYRotation(y) * Matrix::MakeZRotation(z);

I've checked the formula out, it seems that arbirary axis rotation is more expensive... Am i missing some key point or important concept?

Share this post


Link to post
Share on other sites
Advertisement
I'm just curious if there is a difference in the values of the resulting matrix.. I haven't implemented Arbitrari Axis Rotation yet, i'm trying to figure out if it's worth my time or now. Performance isn't an issue, i'm just researching.
Sorry for not making my first post clear.

Share this post


Link to post
Share on other sites
Rotating around an arbitrary axis is faster than multiplying 3 matrices together, although if the 3 matrices are already built and the only operation you are performing is to combine them, their speeds are fairly similar.
If you are building and then combining the 3 matrices, axis rotation is by-far more efficient.

In the case where the 3 matrices are already built, axis rotation loses time in computing a sine and cosine, but both can be computed in a single instruction on many machines, and after that the rest of the matrix is built with single multiplications, in contrast with 3-matrix concatenating which will ultimately incur quite-a-few multiplies and probably result in similar or even slower performance.

But profiling on your target hardware is of course the best way to know for sure.


L. Spiro

Share this post


Link to post
Share on other sites
Like YogurtEmperor said, in these scenarios which is fastest depends on what data you may already have precalculated for other reasons. In the end, I recommend trusting a profiling tool over the best guess of anyone here.

Share this post


Link to post
Share on other sites

I'm playing with some matrix math, i have a question. Does arbirtary axis rotation offer any advantage over concatenating 3 rotation matrices?

Example: Matrix result = Matrix::MakeXRotation(x) * Matrix::MakeYRotation(y) * Matrix::MakeZRotation(z);

I've checked the formula out, it seems that arbirary axis rotation is more expensive... Am i missing some key point or important concept?


I'd also add the point that depending on what you are doing, the concatenation version has gimbal lock issues which the normal axis+angle item does not have if you choose a decent axis for the input. An example usage where i would always use an axis+angle variation ignoring any performance items is in free camera movement calculations. A fixed camera or limited camera environment I might not bother but I usually start with axis+angle so I don't run into gimbal lock if I change my mind.

Share this post


Link to post
Share on other sites
Good points. Thanks for clearing this up for me. One more question. I've implemented arbitrary axis rotations, however the function signature is this:
Matrix Matrix::AxisAngleRotation(Vector& rotate, float degrees);
I'd like it to be something along the lines of
Matrix Matrix::AxisAngleRotation(Vector& rotate);
Where the x component specifies the angle to rotate about the x axis, the y component the angle around the y axis and the z component the angle about the z axis.
I have no clue how to do that as all the references i find lead to this formula...
My implementation


Matrix Matrix::AxisAngleRotation(Vector& rotate, float degrees) {
#define x rotate.x
#define y rotate.y
#define z rotate.z
degrees *= 0.0174532925f; // To radians!

float c, s, t;

c = cos(degrees);
s = sin(degrees);
t = 1 - c;

Matrix rotation = Matrix::identity;

rotation.mat[0] = t * x * x + c;
rotation.mat[1] = t * x * y - s * z;
rotation.mat[2] = t * x * z + s * y;

rotation.mat[4] = t * x * y + s * z;
rotation.mat[5] = t * y * y + c;
rotation.mat[6] = t * y * z - s * x;

rotation.mat[8] = t * x * z - s * y;
rotation.mat[9] = t * y * z + s * x;
rotation.mat[10] = t * z * z + c;

return rotation;
#undef x
#undef y
#undef z
}



All help is appriciated!

Share this post


Link to post
Share on other sites

... I've implemented arbitrary axis rotations, however the function signature is this:
Matrix Matrix::AxisAngleRotation(Vector& rotate, float degrees);

Just for notice: The vector should be const.


I'd like it to be something along the lines of
Matrix Matrix::AxisAngleRotation(Vector& rotate);
Where the x component specifies the angle to rotate about the x axis, the y component the angle around the y axis and the z component the angle about the z axis.
...

Axis/angle rotation representation and the interpretation of vector components as you describe are different things! You should not do an Euler rotation and name it AxisAngleRotation. And even if you write another function like EulerRotation(...) you should IMHO not use a Vector to specify the angles because it dismisses the clear definition of what purpose a Vector instance is for. E.g. what means Matrix::Rotation(...) * vector if vector is a vector of angles? Please don't do that.

Share this post


Link to post
Share on other sites

Good points. Thanks for clearing this up for me. One more question. I've implemented arbitrary axis rotations, however the function signature is this:
Matrix Matrix::AxisAngleRotation(Vector& rotate, float degrees);
I'd like it to be something along the lines of
Matrix Matrix::AxisAngleRotation(Vector& rotate);
Where the x component specifies the angle to rotate about the x axis, the y component the angle around the y axis and the z component the angle about the z axis.
I have no clue how to do that as all the references i find lead to this formula...
...snip...

All help is appriciated!



First off, I'm going to bring up a possible source of contention but it is a relevant item: don't use degree's. Degree's are not a real mathematical concept in terms of most of the functions you need to use as they will want radian's as inputs. Yeah, 3.14 is less obvious than 180, but once you get used to it, it doesn't actually slow you down since it is a linear conversion. I.e. memorize the radians for 45, 90, etc and it really isn't much different or difficult to see/find bugs in angle calculations. But having to use conversions between radian's and degree's all the time is not only a performance issue but it's a damn pain in the ass since "many" things will by nature require radian's and degree's will have to be converted which "mostly" leads to more bugs when you forget which version of "angle" you are in at a given time.

Second, as haegarr said, your function has no valid reason to be called AxisAngle if you don't actually implement what the name suggests. What you describe is "XYZConcatenation", it has nothing to do with axis+angle.

Share this post


Link to post
Share on other sites
Try this.



/**
* Create a matrix that rotates around an arbitrary axis.
*
* \param _fX The X component of the arbitrary axis.
* \param _fY The Y component of the arbitrary axis.
* \param _fZ The Z component of the arbitrary axis.
* \param _fAngle Angle of rotation in radians.
* \return Returns this object.
*/
CMatrix4x4 & __fastcall CMatrix4x4::MatrixRotationAxis( float _fX, float _fY, float _fZ, float _fAngle ) {
float fS;
float fC;
CMathLib::SinCos( _fAngle, fS, fC );

float fT = 1.0f - fC;
register float fTX = fT * _fX;
register float fTY = fT * _fY;
register float fTZ = fT * _fZ;
float fSX = fS * _fX;
float fSY = fS * _fY;
float fSZ = fS * _fZ;

_11 = fTX * _fX + fC;
_12 = fTX * _fY + fSZ;
_13 = fTX * _fZ - fSY;
_14 = 0.0f;

_21 = fTY * _fX - fSZ;
_22 = fTY * _fY + fC;
_23 = fTY * _fZ + fSX;
_24 = 0.0f;

_31 = fTZ * _fX + fSY;
_32 = fTZ * _fY - fSX;
_33 = fTZ * _fZ + fC;
_34 = 0.0f;

_41 = 0.0f;
_42 = 0.0f;
_43 = 0.0f;
_44 = 1.0f;

return (*this);
}


And remember to get the sine and cosine together instead of separately.

__inline void __fastcall CMathLib::SinCos( float _fA, float &_fSine, float &_fCosine ) {
__asm {
fld _fA
fsincos
mov ecx, _fCosine
mov edx, _fSine
fstp dword ptr [ecx]
fstp dword ptr [edx]
}
}



L. Spiro

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!