Hello,
It seems that I'm currently mathematical disabled a little bit. I have load a 3D object and can show it. Additionally I have 2 vectors (normalized) which defines the rotation of this object. The first vector is the direction of the objects X axis, the second is it's normale vector (matches the direction of the Y axis) For example: v1(-1.0,0,0) v2(0,1.0,0) which defines the objects x axis directs into the opposite to the world x axis
How can I calculate the angles for setRotation function of a scene node object from this?
calculate angle from 2 vectors for object rotation
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Re: calculate angle from 2 vectors for object rotation
It's not massively intuitive, but vector3df::getHorizontalAngle() will get you the required Y and X rotations.HydroNom wrote:It seems that I'm currently mathematical disabled a little bit. I have load a 3D object and can show it. Additionally I have 2 vectors (normalized) which defines the rotation of this object. The first vector is the direction of the objects X axis, the second is it's normale vector (matches the direction of the Y axis) For example: v1(-1.0,0,0) v2(0,1.0,0) which defines the objects x axis directs into the opposite to the world x axis
How can I calculate the angles for setRotation function of a scene node object from this?
Code: Select all
vector3df const masterVector(vector3df(-1, -2, -3).normalize());
vector3df const rotations = masterVector.getHorizontalAngle();
matrix4 mat;
mat.setRotationDegrees(rotations);
vector3df slaveVector(0, 0, 1);
mat.rotateVect(slaveVector);
assert(masterVector == slaveVector);
Irrlicht maths uses the common idiom that +Z is forwards, i.e. rotations are relative to (0, 0, 1).
The up vector (what you called the "normale") has no part in this calculation, since a direction vector can be defined by only two rotations (Y then X in this case).
Last edited by rogerborg on Thu Jul 10, 2008 12:26 pm, edited 1 time in total.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Urgh, I'm sorry. I pulled a JP and didn't read your question fully. Of course you need X, Y and Z rotations. To get those, you just have to... uh... wait... I know this...
EPIC FAIL.
OK, hopefully someone else will know this or figure it out, but I don't see a general solution. I'm going to continue to assume that "direction" is based on +Z, not +X.
The X (pitch) and Y (yaw) rotations are sufficient to express the direction vector. That leaves the Z (roll) rotation to express the required up vector. However, there's no guarantee that the up vector is perpendicular to the direction vector, so there's no Z rotation that's guaranteed to produce it. I therefore can't solve for Z. I'm a Scotsman, not a mathematician, dammit!
EPIC FAIL.
OK, hopefully someone else will know this or figure it out, but I don't see a general solution. I'm going to continue to assume that "direction" is based on +Z, not +X.
The X (pitch) and Y (yaw) rotations are sufficient to express the direction vector. That leaves the Z (roll) rotation to express the required up vector. However, there's no guarantee that the up vector is perpendicular to the direction vector, so there's no Z rotation that's guaranteed to produce it. I therefore can't solve for Z. I'm a Scotsman, not a mathematician, dammit!
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Oh my SHATNER, I think I sprained my brain.
If I project the up vector so that it's always orthogonal to the direction, then I can get Eulers from it. It's... not pretty.
Seriously, I need to go and have a lie down.
In the meantime, doubtless hybrid or Vitek will rewrite the above in 3 lines, find a degenerate case, or point out that I misunderstood the problem (again).
Going to a dark room now.
Dumped in code snippets.
If I project the up vector so that it's always orthogonal to the direction, then I can get Eulers from it. It's... not pretty.
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;
}
In the meantime, doubtless hybrid or Vitek will rewrite the above in 3 lines, find a degenerate case, or point out that I misunderstood the problem (again).
Going to a dark room now.
Dumped in code snippets.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way