Code: Select all
// Input: Direction of travel vector, and an up vector that does not need to allow for elevation in travel direction, result is the node´s required rotation in degrees
vector3df createRotations(vector3df const &fromDirection, vector3df const &fromUp, ISceneNode *testNode)
{
vector3df masterDirection(fromDirection);
masterDirection.normalize();
vector3df masterUp(fromUp);
masterUp.normalize();
// *** First calculate the true up vector in relation to the direction vector, which may be elevated:-
// Get a vector perpendicular to the two angles input. The two angles form an L of a plane, the result is an up vector from this plane
// Project the up vector onto a vector that's orthogonal (perpendicual/at 90 degrees) to the direction
vector3df realUp = masterDirection.crossProduct(masterUp).normalize(); // Result is vector pointing right to the directon vector and at 90 deg to the up
// Now realUp is actually the real Left!
realUp = realUp.crossProduct(masterDirection); // Now produce the real (corrected) upvector in relation to the direction of travel (which may be elevated for example)
// *** Set the quaternion´s rotation to that of the direction vector:-
quaternion quatDirection; // Set the quaternion´s rotation to that of the master direction vector
quatDirection.rotationFromTo(vector3df(0, 0, 1), masterDirection); // Calc the rotation required from the standard forward direction to the master direction
// *** Calculate true upvector related to direction of travel:-
vector3df worldUp(0, 1, 0); // Apply that rotation to the world up vector
matrix4 mat;
mat = quatDirection.getMatrix();
mat.rotateVect(worldUp); // Rotate worldUp vector by up vector of direction vector (which could be an elevated direction of travel for example
// Now we have an upvector related correctly to the direction of travel
quaternion quatUp; // Get the quaternion to rotate to the required up
quatUp.rotationFromTo(worldUp, realUp); // Set quat´s rotation equal to that needed to go from world up (010) to required (real)up
quaternion quat = quatDirection * quatUp; // Concatenate them to get a total rotation for the node so that it face in the direction set, and is also elevated correctly
// Convert to euler rotations
vector3df eulers;
quat.toEuler(eulers); //... in radians
eulers *= RADTODEG; //... and now in degrees
// This is the euler rotations required.
if ( testNode )
{
// Now let's test them.
testNode->setRotation(eulers);
testNode->updateAbsolutePosition();
mat = testNode->getAbsoluteTransformation();
vector3df slaveDirection(0, 0, 1);
mat.rotateVect(slaveDirection); // Rotate a standard forward direction to the same as the node
vector3df slaveUp(0, 1, 0);
mat.rotateVect(slaveUp); // Rotate a standard world up direction to that of the node
(void)printf("\nEulers %.2f %.2f %.2f\n",
eulers.X, eulers.Y, eulers.Z);
(void)printf("From dir %.2f %.2f %.2f, up %.2f %.2f %.2f\n",
masterDirection.X, masterDirection.Y, masterDirection.Z,
realUp.X, realUp.Y, realUp.Z);
(void)printf(" to dir %.2f %.2f %.2f, up %.2f %.2f %.2f\n",
slaveDirection.X, slaveDirection.Y, slaveDirection.Z,
slaveUp.X, slaveUp.Y, slaveUp.Z);
(void)printf(" %s %s\n",
masterDirection == slaveDirection ? "PASS" : "FAIL",
realUp == slaveUp ? "PASS" : "FAIL");
}
return eulers;
}