Rotation interpolation
Rotation interpolation
I have two rotations, a target and a current(old) rotation vector. I need to animate a smooth transition between the two.
How do I get a rotation that is between the two vector3fs?
How do I get a rotation that is between the two vector3fs?
-
- Posts: 153
- Joined: Mon Mar 03, 2008 8:42 am
- Location: Suceava - Romania
- Contact:
Code: Select all
vector3df base,target;
irr::f32 speed;
... //assign them here
vector3df move=(target-base).normalise();
base+=move*speed*delta; //delta is a value to make it framerate independent
//assign base to your node via ->setRotation()
night_hawk: thanks heaps for your code =D
I would love a method that checked for the shortest path. for example if the original X was at 20, and the target X was at 270 it would be quicker to go down instead of up...
My code for doing this looks like someone threw it up, and it still doesn't work right, at certain angles it goes the wrong way.
I would love a method that checked for the shortest path. for example if the original X was at 20, and the target X was at 270 it would be quicker to go down instead of up...
My code for doing this looks like someone threw it up, and it still doesn't work right, at certain angles it goes the wrong way.
the "shortest" path is easily defined. consider a rotation around, lets say, the Y axis. any rotation R bigger than 180° can be described as "long", and the shorter path is -(360°-R). so, after calculating your rotation vector [edit: but BEFORE normalizing it], check for each axis if the rotation is bigger than 180° (and maybe also -180°) and set the shorter angle if yes [edit: or just change the sign of that axis].
edit:
in fact, it IS a problem if you have rotations on all axes - you really should therefore stick to quaternions' slerp(). otherwise you'll have to handle some special cases (for example when your object makes a looping) as the rotation vector will not be returned continously, but there will be some "jumps".
edit:
in fact, it IS a problem if you have rotations on all axes - you really should therefore stick to quaternions' slerp(). otherwise you'll have to handle some special cases (for example when your object makes a looping) as the rotation vector will not be returned continously, but there will be some "jumps".
Thanks morris. I tried to work out the interpolation using this code:
as you can tell it didn't work. I'll read up more about slerp now. I still don't understand exactly what it does.
Code: Select all
core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const u32 &interpolation){
core::vector3df base = actualCamera;
core::vector3df move = (actualCamera-orginalRotation);
if(move.Y > 180)
move.Y = -move.Y;
if(move.Y < -180)
move.Y = -move.Y;
if(move.X > 180)
move.X = -move.X;
if(move.X < -180)
move.X = -move.X;
if(move.Z > 180)
move.Z = -move.Z;
if(move.Z < -180)
move.Z = -move.Z;
move = move.normalize ();
base -= move * interpolation;
return base;
};
I got closer with the previous method than this one:
It's most likely not working because I don't really understand what the slerp code does. The code looks like someone threw up :/
Code: Select all
core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const f32 &interpolation){
core::quaternion tmp;
tmp.slerp( core::quaternion(actualCamera), core::quaternion(orginalRotation), interpolation);
core::vector3df ret;
tmp.toEuler (ret);
return ret;
};
For some strange reason the quaternion classes take radians... Or is it: for some strange reason scene nodes use degrees?
Code: Select all
core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const f32 &interpolation){
core::quaternion tmp;
tmp.slerp( core::quaternion(actualCamera * core::DEGTORAD), core::quaternion(orginalRotation * core::DEGTORAD), interpolation);
core::vector3df ret;
tmp.toEuler (ret);
return ret * core::RADTODEG;
};
EDIT:xDan wrote:For some strange reason the quaternion classes take radians... Or is it: for some strange reason scene nodes use degrees?
Code: Select all
core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const f32 &interpolation){ core::quaternion tmp; tmp.slerp( core::quaternion(actualCamera * core::DEGTORAD), core::quaternion(orginalRotation * core::DEGTORAD), interpolation); core::vector3df ret; tmp.toEuler (ret); return ret * core::RADTODEG; };
I am curious as to why you are passing 'interpolation' as a constant reference. Correct me if I am wrong, but if you have SSE/SSE2/SEE3 they have 128-bit registers which makes the passing of float/double values by reference unneeded.
Otherwise, that is a good code snippet right there.
Last edited by Halifax on Sat Mar 15, 2008 4:27 pm, edited 1 time in total.
TheQuestion = 2B || !2B
MMX is for integers.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net