adjust model to vectors
adjust model to vectors
Hello there,
i've got a problem adjusting a model to three given vectors(right vector, up vector and view vector). I'm able to compute them properly and the look in the direction i want them to look. I also changed the Irrlicht Code to override the relative Transformation routine to change the matrix by hand.
I came up integrating my 3 vectors directly into the matrix like the gluLookAt routine does.
The solution i wanted to achieve is to bypass the gimbal lock problem. But obviously it seems that i reprogrammed the normal rotation routine.
This is kinda ridiculous as the routines I used obviously worked for me in my engine's camera class.
Perhaps there is an easier solution than the one i'm going. If so, could someone tell me?
Thanks
i've got a problem adjusting a model to three given vectors(right vector, up vector and view vector). I'm able to compute them properly and the look in the direction i want them to look. I also changed the Irrlicht Code to override the relative Transformation routine to change the matrix by hand.
I came up integrating my 3 vectors directly into the matrix like the gluLookAt routine does.
The solution i wanted to achieve is to bypass the gimbal lock problem. But obviously it seems that i reprogrammed the normal rotation routine.
This is kinda ridiculous as the routines I used obviously worked for me in my engine's camera class.
Perhaps there is an easier solution than the one i'm going. If so, could someone tell me?
Thanks
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
OK, first stab:
Calculate the Euler rotations that will produce given direction and up vectors (the right vector is just the cross product of those, so we can ignore it).
You can then interpolate between the current rotation and this calculated rotation, although I can't guarantee that it'll be free of gimbal lock.
If that doesn't do what you want, then I can take another stab at it. Perhaps a hack, conceivably even a slash as well.
Sample app:
Calculate the Euler rotations that will produce given direction and up vectors (the right vector is just the cross product of those, so we can ignore it).
You can then interpolate between the current rotation and this calculated rotation, although I can't guarantee that it'll be free of gimbal lock.
If that doesn't do what you want, then I can take another stab at it. Perhaps a hack, conceivably even a slash as well.
Sample app:
Code: Select all
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
vector3df calculateRotations(vector3df const & direction,
vector3df const & up)
{
vector3df masterDirection(direction);
masterDirection.normalize();
vector3df masterUp(up);
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.
return eulers;
}
void makeRandomTargets(vector3df & targetDirection,
vector3df & targetUp)
{
do
{
targetDirection.set((f32)(rand() % 2000 - 1000),
(f32)(rand() % 2000 - 1000),
(f32)(rand() % 2000 - 1000));
targetUp.set((f32)(rand() % 2000 - 1000),
(f32)(rand() % 2000 - 1000),
(f32)(rand() % 2000 - 1000));
} while(equals(targetDirection.getLengthSQ(), 0.f) ||
equals(targetUp.getLengthSQ(), 0.f) ||
targetDirection == targetUp);
targetDirection.normalize();
targetUp.normalize();
}
bool rotateNode(ISceneNode * node, const vector3df & targetRotations, f32 delta)
{
vector3df rotation = node->getRotation();
vector3df deltaRotation = targetRotations - rotation;
if(equals(deltaRotation.getLengthSQ(), 0.f))
return false; // reached target
const f32 availableRotationMagnitude = delta * 45.f; // degrees per second
// You could also scale the speeds by the largest difference
if(deltaRotation.X < - availableRotationMagnitude)
deltaRotation.X = -availableRotationMagnitude;
else if(deltaRotation.X > availableRotationMagnitude)
deltaRotation.X = availableRotationMagnitude;
if(deltaRotation.Y < - availableRotationMagnitude)
deltaRotation.Y = -availableRotationMagnitude;
else if(deltaRotation.Y > availableRotationMagnitude)
deltaRotation.Y = availableRotationMagnitude;
if(deltaRotation.Z < - availableRotationMagnitude)
deltaRotation.Z = -availableRotationMagnitude;
else if(deltaRotation.Z > availableRotationMagnitude)
deltaRotation.Z = availableRotationMagnitude;
rotation += deltaRotation;
node->setRotation(rotation);
return true;
}
int main()
{
IrrlichtDevice *device =
createDevice( video::EDT_OPENGL, dimension2d<s32>(640, 480), 16,
false, false, false, 0);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
ISceneNode * MrCubey = smgr->addCubeSceneNode();
MrCubey->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
MrCubey->setMaterialFlag(video::EMF_LIGHTING, false);
(void)smgr->addCameraSceneNode(0, vector3df(0, 0, -30));
vector3df targetDirection;
vector3df targetUp;
makeRandomTargets(targetDirection, targetUp);
vector3df targetRotations = calculateRotations(targetDirection, targetUp);
SMaterial material;
material.setTexture(0, 0);
material.Lighting = false;
u32 then = device->getTimer()->getTime();
while(device->run())
{
const u32 now = device->getTimer()->getTime();
const f32 delta = (f32)(now - then) * 0.001f;
then = now;
if(!rotateNode(MrCubey, targetRotations, delta))
{
makeRandomTargets(targetDirection, targetUp);
targetRotations = calculateRotations(targetDirection, targetUp);
}
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->setTransform(video::ETS_WORLD, core::matrix4());
driver->setMaterial(material);
driver->draw3DLine(MrCubey->getAbsolutePosition(),
MrCubey->getAbsolutePosition() + 50.f * targetDirection,
SColor(255, 255, 0, 0));
driver->draw3DLine(MrCubey->getAbsolutePosition(),
MrCubey->getAbsolutePosition() + 50.f * targetUp,
SColor(255, 0, 255, 0));
driver->endScene();
}
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
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
i know this is a pretty old post, but tried out the code, and worked, except if the direction is vector3df(0,0,-1). then it wants to rotate vector3df(180, -5.0089557e-006, 180). what no matter how we see, not right. it should only rotate on Y axis.
after a lot of debugging, i got it, that the rotationFromTo function changed since 1.6
there is a block what wasnt there before
this returns the bad angle. is it irrlicht bug, or just the old code doesnt work, and should use somethign else?
Edit: OK tryed out the old code, and its even worse... XD (it tries to divide by zero, so the values becomes garbage to protect the world from apocalypse) what should i do?
after a lot of debugging, i got it, that the rotationFromTo function changed since 1.6
there is a block what wasnt there before
Code: Select all
else if (d <= -1.0f) // exactly opposite
{
core::vector3df axis(1.0f, 0.f, 0.f);
axis = axis.crossProduct(core::vector3df(X,Y,Z));
if (axis.getLength()==0)
{
axis.set(0.f,1.f,0.f);
axis.crossProduct(core::vector3df(X,Y,Z));
}
return this->fromAngleAxis(core::PI, axis);
}
Edit: OK tryed out the old code, and its even worse... XD (it tries to divide by zero, so the values becomes garbage to protect the world from apocalypse) what should i do?
hmmm, I don't know if this may help,
but for OpenSteer I had to deal with rotation from forward verctor and vice versa...
so I made this 2 little functions:remember that Vec3 is an OpenSteer vector and I added a vector3df() function to it for easy conversion between OpenSteer and Irrlicht...
for pure Irrlicht it should be like this (I guess ):
but for OpenSteer I had to deal with rotation from forward verctor and vice versa...
so I made this 2 little functions:
Code: Select all
//! convert rotation vector to forward vector
static Vec3 getForwardFromRotation(Vec3 r) {
irr::core::matrix4 mat;
mat.setRotationDegrees(r.vector3df());
Vec3 ff;
ff.set(mat(2,0), mat(2,1), mat(2,2));
ff.normalize();
return ff;
}
//! convert forward vector to rotation vector
static Vec3 getRotationFromForward(Vec3 r) {
Vec3 ff = r.vector3df().getHorizontalAngle();
return ff;
}
for pure Irrlicht it should be like this (I guess ):
Code: Select all
static irr::core::vector3df getForwardFromRotation(irr::core::vector3df r) {
irr::core::matrix4 mat;
mat.setRotationDegrees(r);
irr::core::vector3df ff(mat(2,0), mat(2,1), mat(2,2));
ff.normalize();
return ff;
}
//! convert forward vector to rotation vector
static irr::core::vector3df getRotationFromForward(irr::core::vector3df r) {
irr::core::vector3df ff = r.getHorizontalAngle();
return ff;
}
while(!asleep) sheep++;
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
I advise you to forget matrix and use quaternion they are free of gimbal lock and pretty easy to use! If you have a look in the irr::core::quaternion you'll be pleased! quaternion can be multiply just like matrix do and can be computed from 2 vectors. The only issue is they will take the shortest rotation between 2 vectors so won't care about your up vector. but in normal case you can rotate back the camera to suit your needs.