Euler rotations from direction and up vectors

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Euler rotations from direction and up vectors

Post by rogerborg »

Say you want to scene node to achieve a target direction vector and a target up vector, i.e. the vectors that its +Z (forwards) and +Y (up) axes need to be aligned to. How do you calculate the Euler rotations necessary to achieve those vectors, i.e. the setRotation() that you'd apply to a scene node?

This code isn't pretty, but it works for my test cases. Improvements are welcome.

Code: Select all

#include <irrlicht.h>
#include <assert.h>

#pragma comment(lib, "Irrlicht.lib")

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;


void createRotations(vector3df const & fromDirection,
                vector3df const & fromUp,
                ISceneNode * testNode)
{
   vector3df masterDirection(fromDirection);
   masterDirection.normalize();

   vector3df masterUp(fromUp);
   masterUp.normalize();

   // project the up vector onto a vector that's orthogonal to the direction
   vector3df realUp = masterDirection.crossProduct(masterUp).normalize();
   realUp = realUp.crossProduct(masterDirection);

   // Get the quaternion to rotate to the required direction
   quaternion quatDirection;
   quatDirection.rotationFromTo(vector3df(0, 0, 1), masterDirection);

   // Apply that rotation to the world up vector
   vector3df worldUp(0, 1, 0);
   matrix4 mat;
   quatDirection.getMatrix(mat);
   mat.rotateVect(worldUp);

   // Get the quaternion to rotate to the required up
   quaternion quatUp;
   quatUp.rotationFromTo(worldUp, realUp);

   // Concatenate them to get a total rotation
   quaternion quat = quatDirection * quatUp;

   // Convert to euler rotations
   vector3df eulers;
   quat.toEuler(eulers); //... in radians
   eulers *= RADTODEG;   //... and now in degrees
   // This is the euler rotations required. 
   
   // Now let's test them.   
   testNode->setRotation(eulers);
   testNode->updateAbsolutePosition();
   mat = testNode->getAbsoluteTransformation();

   vector3df slaveDirection(0, 0, 1);
   mat.rotateVect(slaveDirection);

   vector3df slaveUp(0, 1, 0);
   mat.rotateVect(slaveUp);

   (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");
}

int main()
{
   IrrlichtDevice* device = createDevice(EDT_NULL);
   ISceneManager* smgr = device->getSceneManager();
   ISceneNode * node = smgr->addEmptySceneNode();

   createRotations(vector3df(0, 0, 1), vector3df(0, 1, 1), node);
   createRotations(vector3df(1, 0, 0), vector3df(0, 1, 0), node);
   createRotations(vector3df(1, 0, 1), vector3df(0, 1, 1), node);
   createRotations(vector3df(1, 0, 1), vector3df(1, 0, -1), node);
   createRotations(vector3df(-1, 0, -1), vector3df(-1, -2, -3), node);
   createRotations(vector3df(0, 1, 1), vector3df(1, 0, 0), node);
   createRotations(vector3df(0, 1, 1), vector3df(0, 1, 0), node);
   createRotations(vector3df(1, 1, 1), vector3df(-1, 1, -1), node);
   createRotations(vector3df(3, 4, 5), vector3df(-2, 4, -6), node);

   device->drop();
    return 0;
}
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
init512
Posts: 18
Joined: Mon Mar 26, 2007 6:08 pm
Contact:

Thank You!

Post by init512 »

rogerborg, this is *exactly* what I have been looking for. Thank you very much!
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

You are very welcome, I'm glad this was useful.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
MisterRose
Posts: 18
Joined: Thu Jun 16, 2011 2:46 pm

Post by MisterRose »

I had to change the following line from

quatDirection.getMatrix(mat);

to

mat = quatDirection.getMatrix();

I guess someone changed that function to make it more consistent with the other classes.
You are unique - just like everyone else.
Post Reply