Yes, but then if you´ve got mixed models, some rotated, some not, and general code to control the orientation (rotation of models), then you have to add the required rotation to the object, taking into account its existing orientation.
With rotation of a node´s Z-axis this works (consider that the node´s Y-axis is rotated to the world X-axis, and the X-axis becomes vertical, which must be then adjusted to sping the node around over the floor) but with rotation of the X-axis, which puts the Z-axis vertical, it doesn´t work, and the node´s Y-axis, still rotates the model around the floor!
This problem seems to relate to the way the xyz rotation angles are processed by Irrlicht, causing what is called gimble lock to occur.
To solve this problem ... anyone got a tidy solution to this????
In this code below, which doesn´t yet solve this problem (help!) we include the facility to rotate the rotated node around a centre point in space.
This code below is a first rought attempt to provide a solution to object rotation under these circumstances:-
Code: Select all
// 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); Set to standard up-vector
up.rotateYZBy( pListObjects->rot3D.X ); // Rotate all axis to requried direction in degrees
up.rotateXZBy( pListObjects->rot3D.Y );
up.rotateXYBy( pListObjects->rot3D.Z );
// We now have the object´s actual up vector based on its rotation
// We will consider only the "Y" rotation only of node (spin over floor), regardless of any current rotation of node:-
// By multiplying the object´s up vector by the required node rotation (Y) input by the user (to be applied onto current rotation), we move the required rotation to be applied, to the correct (rotated) axis of the node.
// Note: The below tests (!up.Z) work even with very small values near to zero, but its probably not the best way to do it!
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; Set spin rotation to node´s Y-axis, which is its X-axis
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
// ???? Do we need to process rotation directions here or above?
// Test code to rotate a new 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 );