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?
Arbirtary axis rotation?
Have you profiled to see if it's actually an issue, or are you just pre-maturely optimizing?
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.
Sorry for not making my first post clear.
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
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
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.
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.
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
All help is appriciated!
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!
... 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.
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.
Try this.
And remember to get the sine and cosine together instead of separately.
L. Spiro
/**
* 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
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement