Rotation by quarterions or matrixes?
-
Spartak
Rotation by quarterions or matrixes?
Somebody can help me to rotate node around vector? Should I use It is not clear in Irrlicht.
-
Baal Cadar
- Posts: 377
- Joined: Fri Oct 28, 2005 10:28 am
- Contact:
What does "around vector" mean? as an axis?
If this is not what you want, put more effort into phrasing a question.
As an aside, I really wonder if the quaternion class is actively used. The interface ist uncomfortable, inconsistent and lacking.
Code: Select all
vector3df myaxis;
float myangle;
vector3df myrotation;
quaternion q;
q.fromAngleAxis(myangle, myaxis);
q.toEuler(myrotation);
mynode->setRotation(myrotation);
As an aside, I really wonder if the quaternion class is actively used. The interface ist uncomfortable, inconsistent and lacking.
-
Spartak
Thank you Baal! You did understand well. I have a node and I want to rotate it around my axis A(0.5, 0.5, 0.5).
1.Should my axis be "normalized vector of length =1"?
2.Should I move my node to 0,0,0 before rotation?
3.Why when I try
vector3df myaxis = core::vector3df( 0, 1, 0);
float myangle = 45;
the rotation that I see is very small?
I have read that quaternion is the better way for rotation then eulers angles and matrixes, but irrlicht has no examples for any way of rotation! In the forum I have read that a lot of users use for rotation newton and ect. because in irrlicht it is too complicated.
1.Should my axis be "normalized vector of length =1"?
2.Should I move my node to 0,0,0 before rotation?
3.Why when I try
vector3df myaxis = core::vector3df( 0, 1, 0);
float myangle = 45;
the rotation that I see is very small?
I have read that quaternion is the better way for rotation then eulers angles and matrixes, but irrlicht has no examples for any way of rotation! In the forum I have read that a lot of users use for rotation newton and ect. because in irrlicht it is too complicated.
-
Baal Cadar
- Posts: 377
- Joined: Fri Oct 28, 2005 10:28 am
- Contact:
Yes, the axis has to be normalised.Spartak wrote: 1.Should my axis be "normalized vector of length =1"?
Don't think so. This should be done by Irrlicht internally, if it applies transforms in the standard order: scale -> rotation -> translation. Not 100% sure, you could look it up in the source or just experiment a bit. Though if you want to rotate the node around its local coordinate systems origin independently from the translation, you need to introduce an intermediate IDummyTransformationSceneNode. See API docs for how to use it.Spartak wrote: 2.Should I move my node to 0,0,0 before rotation?
Because the angle is not given in degree, but in radian. Convert it to radian and it should work. radian = degree*PI/180.0fSpartak wrote: 3.Why when I try
vector3df myaxis = core::vector3df( 0, 1, 0);
float myangle = 45;
the rotation that I see is very small?
It is true, that matrix and quaternion are both better suited than euler angles. Euler angles have an inherent flaw, the so called gimbal lock. With certain angles, a degree of freedom is lost and thus some rotations can not be expressed by euler angles when applied in a strict order, like it is done in Irrlicht. Also doing calculations with euler angles is awkward.Spartak wrote: I have read that quaternion is the better way for rotation then eulers angles and matrixes, but irrlicht has no examples for any way of rotation! In the forum I have read that a lot of users use for rotation newton and ect. because in irrlicht it is too complicated.
Whether matrices or quaternions are better is debatable, though quaternions have a slight advantage overall, imho.
Btw, doing calculation with quaternions and then applying the result as euler angles to the node, does not prevent the gimbal lock problem. I don't know an easy way to work around this. I'd be happy if someone could point it out.
-
Spartak
In order to prevent "gimbal lock" in eulers angels I use matrixes:
void RotateNode(scene::ISceneNode *node, vector3df aIVectorDeg)
{
vector3df lIVec = node->getRotation(); //get current rotation (euler)
matrix4 lmxFirst;
lmxFirst.setRotationDegrees(lIVec);//set firsth matrix to current rotation
matrix4 lmxSecond;
lmxSecond.setRotationDegrees(aIVectorDeg); //set second matrix
lmxFirst *= lmxSecond; //multipy them
lIVec = lmxFirst.getRotationDegrees();//get rotation vector from matrix(euler)
node->setRotation(lIVec);//rotate node
}
void RotateNode(scene::ISceneNode *node, vector3df aIVectorDeg)
{
vector3df lIVec = node->getRotation(); //get current rotation (euler)
matrix4 lmxFirst;
lmxFirst.setRotationDegrees(lIVec);//set firsth matrix to current rotation
matrix4 lmxSecond;
lmxSecond.setRotationDegrees(aIVectorDeg); //set second matrix
lmxFirst *= lmxSecond; //multipy them
lIVec = lmxFirst.getRotationDegrees();//get rotation vector from matrix(euler)
node->setRotation(lIVec);//rotate node
}
-
Spartak
I think you should use quaternion composition for rotation something like this:
code:
const irr::f64 GRAD_PI = 180.0 / 3.14159;
core::vector3df Target;
core::vector3df CurrAngels = node->getRotation();
// current rotation of the node in eulers angels
core::quaternion QStart(CurrAngels .X , CurrAngels.Y , CurrAngels.Z ,1);
// Initial rotation quaternion
core::vector3df Rotation(0.5f, 0.0f, 0.5f);
// Your rotation vector
irr::f64 Degrees = 160.0f / GRAD_PI; // degrees around vector
core::quaternion QRotation(Rotation.X,Rotation.Y,Rotation.Z,Degrees);
// or use QRotation.fromAngleAxis(Rotation)
QStart *= QRotation; // calculate rotation
QStart.toEuler(Target); // store in new vector as Euler rotation for use with irrlight setRotation function
Target *= GRAD_PI; // convert back to degrees
RotateNode(node, core::vector3df(Target.X, 0, 0));
RotateNode(node, core::vector3df( 0, Target.Y, 0));
RotateNode(node, core::vector3df(0, 0, Target.Z));
What do you think about it?
code:
const irr::f64 GRAD_PI = 180.0 / 3.14159;
core::vector3df Target;
core::vector3df CurrAngels = node->getRotation();
// current rotation of the node in eulers angels
core::quaternion QStart(CurrAngels .X , CurrAngels.Y , CurrAngels.Z ,1);
// Initial rotation quaternion
core::vector3df Rotation(0.5f, 0.0f, 0.5f);
// Your rotation vector
irr::f64 Degrees = 160.0f / GRAD_PI; // degrees around vector
core::quaternion QRotation(Rotation.X,Rotation.Y,Rotation.Z,Degrees);
// or use QRotation.fromAngleAxis(Rotation)
QStart *= QRotation; // calculate rotation
QStart.toEuler(Target); // store in new vector as Euler rotation for use with irrlight setRotation function
Target *= GRAD_PI; // convert back to degrees
RotateNode(node, core::vector3df(Target.X, 0, 0));
RotateNode(node, core::vector3df( 0, Target.Y, 0));
RotateNode(node, core::vector3df(0, 0, Target.Z));
What do you think about it?
-
Baal Cadar
- Posts: 377
- Joined: Fri Oct 28, 2005 10:28 am
- Contact:
This doesn't fix the problem. You still end up with an euler angle, you use to set the node rotation. The loss of the degree of freedom can be in it anyway. This is an inherent problem, you can't work around this, without changing the rotation representation in Irrlicht itself. At least I don't see another way.
Your code doesn't work anyway. The 4 float quaternion constructor doesn't take in angel/axis, but the actual components xyzw. So QRotation is not what you expect and it is not even a rotation at all, since it is not of unit length.
Your code doesn't work anyway. The 4 float quaternion constructor doesn't take in angel/axis, but the actual components xyzw. So QRotation is not what you expect and it is not even a rotation at all, since it is not of unit length.
-
Spartak
-
Spartak
Im my opinion it works not bad! Try it:
void main()
{
vector3df myaxis = core::vector3df( x, y, z);
float myangle = 77*180/3.14;
vector3df myrotation;
quaternion q;
q.fromAngleAxis(myangle, myaxis);
q.toEuler(myrotation);
RotateNode(point,myrotation);
}
void RotateNode(scene::ISceneNode *node, vector3df aIVectorDeg)
{
vector3df lIVec = node->getRotation(); //get current rotation (euler)
matrix4 lmxFirst;
lmxFirst.setRotationDegrees(lIVec);//set firsth matrix to current rotation
matrix4 lmxSecond;
lmxSecond.setRotationDegrees(aIVectorDeg); //set second matrix
lmxFirst *= lmxSecond; //multipy them
lIVec = lmxFirst.getRotationDegrees();//get rotation vector from matrix(euler)
node->setRotation(lIVec);//rotate node
}
Now I wanna know how can I translate global coordinates to relative coordinates of node. If I will know, I can control rotation of my node!
void main()
{
vector3df myaxis = core::vector3df( x, y, z);
float myangle = 77*180/3.14;
vector3df myrotation;
quaternion q;
q.fromAngleAxis(myangle, myaxis);
q.toEuler(myrotation);
RotateNode(point,myrotation);
}
void RotateNode(scene::ISceneNode *node, vector3df aIVectorDeg)
{
vector3df lIVec = node->getRotation(); //get current rotation (euler)
matrix4 lmxFirst;
lmxFirst.setRotationDegrees(lIVec);//set firsth matrix to current rotation
matrix4 lmxSecond;
lmxSecond.setRotationDegrees(aIVectorDeg); //set second matrix
lmxFirst *= lmxSecond; //multipy them
lIVec = lmxFirst.getRotationDegrees();//get rotation vector from matrix(euler)
node->setRotation(lIVec);//rotate node
}
Now I wanna know how can I translate global coordinates to relative coordinates of node. If I will know, I can control rotation of my node!
-
jreuschel1
- Posts: 25
- Joined: Sun Nov 12, 2006 7:51 pm
- Contact:
Dude, this thread was 2 years ago... you can't even post as guest anymore.
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
You still can post there. If you are registered.Dude, this thread was 2 years ago... you can't even post as guest anymore.
And yes methods used there can be useful to Spartak. They do the same stuff just use matrix instead of quaternion. Irrlicht do use matrix for most if not all of the transformation stuff. Rotations including.