Rotating a rotated node weird axis result...

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Rotating a rotated node weird axis result...

Post by robmar »

If a node is rotated -90 degrees on its z-axis, its x-axis then points up-down, so to spin it around on the "floor", I rotate the x-axis.

That works fine.

If a node is rotated -90 degress on the x-axis, its z-axis then points up-down, so to spin it, you would think that rotating the z-axis would work.

But it doesn´t work like that for some reason! The y-axis still controls the floor-spin, but y is now pointing along the z-direction!

Any ideas why this happens, and how I can apply rotations to already rotated objects?
Last edited by robmar on Thu May 24, 2012 6:19 pm, edited 3 times in total.
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Rotating a rotated node weird axis result...

Post by smso »

My solution is to parent the node to an empty scene node.
To spin the node around on the "floor", I only have to rotate the empty node about the y-axis.

Regards,
smso
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

The problem is I have 700 nodes, so I really don´t want to double that number. Why doesn´t the behaviour do what seems logical,... or did I miss something?
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

My nodes are created randomly, in any of a number of configurations and rotations, then at some point if I want to copy them to a new rotation and space, I need to be able to rotate each node individually, which should be quite simple. I calculate a rotation vector for the current object rotation, and then rotate the to-be-applied rotation by that, and apply it. However, there is a weird thing going on with the rotation on the x-axis, where the z-axis doesn´t seem to become the "y", and the "y", although rotated to the "z", still does its "y" thing! :S

I must have missed something really stupid... ???
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Rotating a rotated node weird axis result...

Post by smso »

Assume the node aligns in the z-direction initially. Then it is rotated in some unknown way. Finally, it needs to orientate in a new direction, say, dir.

Do this:

Code: Select all

core::matrix4 matrix = node->getAbsoluteTransformation();
core::vector3df heading(0.0f, 0.0f, 1.0f);
matrix.rotateVect(heading);
 
matrix.buildRotateFromTo(heading, dir);
node->setRotation(matrix.getRotationDegrees());
 
Regards,
smso
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

Thanks for the code snippet, unfortunately, I´m pasting nodes from an object-list which stores the current rotation of the object, but the object itself is not yet created, so I can´t call those functions.

What I have is the current rotation in degrees on all 3 axis of the node, and the rotation to be applied.

So, for example, if the node where a mesh cube, with the 6 sides painted in different colors, and the yellow side facing forward to the camera, the user wants to rotate it 90 degrees on the up-axis, which could be any axis of the node as it may have a previous rotation, the XYZ value of which we have of course.

So my code calculates the real up vector of the object based on its rotation, say 1,0,0, because it was rotated 90 degrees previously on the z-axis.

I use this to rotate the rotation to be applied to the axis of the node as they have been rotated, and then the object should rotate correctly.

// If new node rotation set, the node must be rotated, however, this needs to take into account the object´s existing rotation
// 1. get up-vector of current node rotation
// 2. multiply each axis of it by requried rot in degrees

core::vector3df up(0.f,1.f,0.f);
up.rotateYZBy( pListObjects->rot3D.X );
up.rotateXZBy( pListObjects->rot3D.Y );
up.rotateXYBy( pListObjects->rot3D.Z );
// We now have the object´s actual up vector based on its rotation

// "Y" rotation only of node, regardless of any current rotation of node:-
// By multiplying by the required node rotation (Y) input by the user (to be applied onto current rotation), by the object´s up vector, we move the required rotation to the correct (rotated) axis
if ( !up.Z ) // If not rotated on x-axis (i.e. Z-up), so Y or X are vertical rotation axis
{
if ( up.X )
_3dfPasteObjectRotationAdj.X = m_3dfPasteObjectRotation.Y;
else
_3dfPasteObjectRotationAdj.Y = m_3dfPasteObjectRotation.Y;
}
else // If rotated on x-axis, rotation stays on Y! No idea why yet!! ///todo3d????
{
_3dfPasteObjectRotationAdj.Z = m_3dfPasteObjectRotation.Y;
}
// The "3dfPasteObjectRotationAdj" rotation should now be ready to add to the nodes current rotation

// Now rotate original rotation to match new object rotation
//_3dfRotV = pListObjects->rot3D;
//fLenRotV =_3dfRotV.getLength();
//_3dfRotV.normalize();
//adjObjRot = (_3dfPasteObjectRotationAdj.rotationToDirection( _3dfRotV )).normalize() * fLenRotV;

// pListObjects->rot3D = adjObjRot + _3dfPasteObjectRotationAdj; // Add rotation to object
pListObjects->rot3D += _3dfPasteObjectRotationAdj; // Add actual "Y" rotation to object
pListObjects->rot3D.X = fmod( pListObjects->rot3D.X, 360.0f ); // Keep to bounds
pListObjects->rot3D.Y = fmod( pListObjects->rot3D.Y, 360.0f );
pListObjects->rot3D.Z = fmod( pListObjects->rot3D.Z, 360.0f );

// Rotate animation-rotation to match new object rotation
_3dfRotV = pListObjects->m_a3dfRotVector;
fLenRotV =_3dfRotV.getLength();
_3dfRotV.normalize();
pListObjects->m_a3dfRotVector = (_3dfPasteObjectRotationAdj.rotationToDirection( _3dfRotV )).normalize() * fLenRotV;
// Check if object to be rotated around centre point
if ( m_3dfPasteSpaceRotation.Y != 0.0f ) // Then rotate the coordinates in 3D space
rotateAroundCentre( pListObjects->m_3dfObjCentre, m_3dfRotCentre, m_3dfPasteSpaceRotation );
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Rotating a rotated node weird axis result...

Post by smso »

Because of finite numerical precision/tolerance, the following might not give you expected results:

Code: Select all

if ( !up.Z ) // If not rotated on x-axis (i.e. Z-up), so Y or X are vertical rotation axis
...
if ( up.X )
...
if ( m_3dfPasteSpaceRotation.Y != 0.0f ) // Then rotate the coordinates in 3D space
e.g. what if up.Z equals 0.0000000001f?

Regards,
smso
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

I thought the same and tested that, and very small floating values where processed as "false", which was handy.

Any idea why the rotation of the x-axis results in the object´s Y-axis still acting as if it was in the same position? Is this a bug in Irrlicht?
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Rotating a rotated node weird axis result...

Post by mongoose7 »

If you're going to rotate objects through 90 deg, you can't use Tait-Bryan angles. For example (90, 30, 30) - this "rolls" 30 deg, then pitches 90 deg, but now the orginal z-axis is aligned with the y-axis, so the y rotation of 30 deg either doubles or cancels (I can't be bothered to work it out) the original roll.

Why don't you use the rotation axis and the angle? This is effectively a quaternion. You can combine rotations using quaternion arithmetic.
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Rotating a rotated node weird axis result...

Post by smso »

To rotate a node about its local y-axis by, say, 15deg. I do this:

Code: Select all

core::matrix4 matrix = node->getAbsoluteTransformation();
core::vector3df yaxis(0.0f, 1.0f, 0.0f); // yaxis in world space
matrix.rotateVect(yaxis); // yaxis in local space
yaxis.normalize();
 
core::quaternion q;
q.fromAngleAxis(15.0f*core::DEGTORAD, yaxis);
 
core::vector3df rot = q.getMatrix().getRotationDegrees();
node->setRotation(rot);
My last advice is to stop thinking about "rotation of node" but treat it as "orientation of node"; otherwise, welcome to the brain busting hell of rotations!!

Regards,
smso
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

Thanks so very much for the feedbacks, Í thought it was just me having problems with visualizing rotations!

My problem is that I have some nice models that have an orientation (good word that!) that point up, so I rotate them by x = -90 to make them face forward to camera.

Then I´d like to be able to copy and paste them into a new location, which can also be rotated around the floor at any angle, but then I started getting these hair-pulling problems as I´d never heard of gimbal lock.

So in my paste code, I create an object that holds all the settings for the new node, but as that node isn´t yet in existence, I can´t call getBasoluteTRansformation, etc., so I just wanted to work out the maths for the new placement of the object and then apply the forward tilt.

It started to get so complicated, with all world-space quadrants having different signs +/- on the rotations of the different axis, and then the x-axis moves with each rotation to a different quadrant... I guess I just haven´t got the math clear in my head.

If I set a parent to the forward-tilted node, internally Irrlicht works all the maths out and I can spin the node around to my hearts content, but how to do that without parenting and taking both the over-floor rotation and any x, y or z axis orientation-tilt into account?
blAaarg
Posts: 94
Joined: Tue Mar 02, 2010 9:11 pm
Location: SoCal

Re: Rotating a rotated node weird axis result...

Post by blAaarg »

If you can't rotate the meshes in the mesh editing software, you could try getting a mesh manipulator from the scene manager and using its transform() method to permanently have the meshes rotated -90 degrees around the X-axis before you even start. That way, when you go to store their rotations around the y-axis and/or turn the object on the floor, you'll only have the one rotation to worry about. It'll be less brain bashing and quicker at run time, for some cost of set-up of the meshes at load time.
"Computers don't make mistakes! What they do they do on purpose!!"

-Dale Gribble
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

Yes, but with 700 meshes, many of which may need manipulation, the software will grind to a halt!

The efficient way to do this is to adjust the orientation thro rotation, and then just simply add the required rotation.

How difficult can that be! The rotation software in Irrlicht causes gimbal lock, as do many other 3D systems, which mathematically could be, and should be, solved.

Lets make Irrlicht better than the rest, and show how this can be solved properly.

I mean Irrlicht handles the parent rotations of any object, with any type of orientation, so clearly its just a matter of knowing the internals of Irrlicht and handling the math correctly.

Someone must know exactly how do achieve this without bodges!
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Rotating a rotated node weird axis result...

Post by smso »

I'm using 2 methods to correct for the orientation of the input mesh. One is by parenting to an empty node. The other is by using mesh manipulator as suggested by blAaarg. However, the latter method does not work with animated mesh.

IMO you should actually try out these methods and see the actual fps first.

If the fps is too low, you may consider using LOD algorithms. If you want to study the internal working of the irrlicht engine, just look at the source codes.

Regards,
smso
blAaarg
Posts: 94
Joined: Tue Mar 02, 2010 9:11 pm
Location: SoCal

Re: Rotating a rotated node weird axis result...

Post by blAaarg »

using mesh manipulator does not work with animated mesh
I did not know that :shock: Hmmm :?
The efficient way to do this is to adjust the orientation thro rotation, and then just simply add the required rotation.
Unfortunately, "adding" or accumulating rotations is not just a simple matter of using addition but of multiplying matrices (as smso showed you), having Irrlicht do it for you (as he suggested) or using quaternions as mongoose7 said. All of those involve much more math than simply adding degrees! Sometimes you can get away with just adding to the x and y rotations as long as x stays away from +/-90 degrees. If you are simply trying to turn a bunch of meshes that have been modeled so that they are oriented up (0,1,0) when they are loaded, and you want them to start off the program facing forward (0,0,-1), it's much more efficient to do that manipulation once (at the beginning of your program, before the loop) rather than redoing it every single frame! Better still, re-orient them in the modeling software/exporter so they show up with the correct orientation. Then, just worry about the one rotation.

Also, you at first said you had 700 nodes but now you're saying you have 700 meshes? There's an important difference. Do you have 700 actually different models (a mesh is not a node) or just several? When you say you're copying the nodes, presumably they'll be using the same model in the mesh cache and so the copied nodes will not duplicate the mesh but merely redraw it with a different world transformation. In other words, 700 (or so) nodes could use one mesh (or a few different ones, if their geometry is actually different).
"Computers don't make mistakes! What they do they do on purpose!!"

-Dale Gribble
Post Reply