Local to World Coordinates and Vice Versa
-
- Posts: 18
- Joined: Fri Sep 11, 2009 4:31 am
Local to World Coordinates and Vice Versa
SceneNode->GetWorldPosition(0,10,0);
Would return a global position.
SceneNode->GetWorldAngles(0,90,0);
Would return a global angle.
Would return a global position.
SceneNode->GetWorldAngles(0,90,0);
Would return a global angle.
-
- Posts: 18
- Joined: Fri Sep 11, 2009 4:31 am
Paid a trip to geometry-land.
Is there any default code in Irrlicht I could use instead of this messy coding?
Code: Select all
vector3df toWorldPos(IAnimatedMeshSceneNode* scene, vector3df vec)
{
vector3df pos = scene->getPosition();
vector3df ang = scene->getRotation().rotationToDirection(vec);
return pos+ang;
}
vector3df toLocalPos(IAnimatedMeshSceneNode* scene, vector3df vec)
{
vector3df pos = scene->getPosition();
vector3df ang = (-scene->getRotation()).rotationToDirection(vec-pos);
return ang;
}
vector3df toWorldAng(IAnimatedMeshSceneNode* scene, vector3df vec)
{
return scene->getRotation()+vec;
}
vector3df toLocalAng(IAnimatedMeshSceneNode* scene, vector3df vec)
{
return scene->getRotation()-vec;
}
-
- Posts: 18
- Joined: Fri Sep 11, 2009 4:31 am
To transform from the nodes local coordinate system to the world coordinate system, you use the nodes absolute transformation matrix.
Rotations are handled similarly.
Travis
Code: Select all
core::vector3df toWorldPos(scene::ISceneNode* node, const core::vector3df pos_in_node_space)
{
core::vector3df pos_in_world_space(pos_in_node_space);
node->getAbsoluteTransformation().transformVect(pos_in_world_space);
return pos_in_world_space;
}
core::vector3df toLocalPos(scene::ISceneNode* node, const core::vector3df pos_in_world_space)
{
core::vector3df pos_in_node_space(pos_in_world_space);
core::matrix4 world_to_local = node->getAbsoluteTransformation();
world_to_local.makeInverse();
world_to_local.transformVect(pos_in_world_space);
return pos_in_world_space;
}
Travis
-
- Posts: 1638
- Joined: Mon Apr 30, 2007 3:24 am
- Location: Montreal, CANADA
- Contact:
Re: Local to World Coordinates and Vice Versa
Hi, I tried this to convert a node world space angle to a local space angle:
It seem logical that this work for the rotations... But it doesnt give me the correct angle.
For testing this I have put 2 object: 1 using the local angle (parented) and 1 that is using the world angle (not parented)). The object matches their position but not their angle (update at every frame). For the node positionning the code Vitek provided worked perfectly.
I used this to set the node:and this to retrieve it:
Here is the output that I have on the console:
- gameobject is the object rotation after it was set with the "local angle"
- Parent angle is the parent object current rotation values
- Combined angle is the parent object angle + local angle check if it match the world angle
Code: Select all
vector3df toLocalAng(IAnimatedMeshSceneNode* scene, vector3df vec)
{
return scene->getRotation()-vec;
}
For testing this I have put 2 object: 1 using the local angle (parented) and 1 that is using the world angle (not parented)). The object matches their position but not their angle (update at every frame). For the node positionning the code Vitek provided worked perfectly.
I used this to set the node:
Code: Select all
node->setRotation(Mylocalangle);
Code: Select all
Mylocalangle = node->getRotation()
- gameobject is the object rotation after it was set with the "local angle"
- Parent angle is the parent object current rotation values
- Combined angle is the parent object angle + local angle check if it match the world angle
World angle is: 272.629272,269.999969,0.000000
Local angle is: 272.629272,87.370682,-182.629288
Game object: 272.629272,87.370682,-182.629288
Parent angle: 0.000000,182.629288,182.629288
Combined Angle:272.629272,269.999969,0.000000
Last edited by christianclavet on Thu Jul 14, 2011 6:28 pm, edited 1 time in total.
Re: Local to World Coordinates and Vice Versa
Are you adding Euler angles component-wise? How can this possibly work?
Doesn't "adding" angles mean "multiplying" the rotation matrices?
Doesn't "adding" angles mean "multiplying" the rotation matrices?
Re: Local to World Coordinates and Vice Versa
I'm not sure if I understand you correctly, but if by "node world space angle" you mean the "world rotation of a node" then I think what you need to do is "un-rotate" a node when given its world transformation (matrix). Or at least get a tool that will tranform some 3D element back into the node's local space? That way you could have something that will change any object in world space into the local space of a node. Is that right?
If so, you need to 1) get the scene node's absolute transformation (as represented by a ) matrix: getAbsoluteTransformation().
2) Use that matrix to create an inverse matrix that represents the transformation back into local space: getInverse().
3) Then use that matrix to apply a transformation to whatever vector/element you want to have local coordinates: transformVect(), transformBox(), transformPlane(), etc.
Although setInverseRotationDegrees() might be quicker for steps 2 and 3.
Also, you may need to update the scene node's transformation first, before doing all this.
If so, you need to 1) get the scene node's absolute transformation (as represented by a ) matrix: getAbsoluteTransformation().
2) Use that matrix to create an inverse matrix that represents the transformation back into local space: getInverse().
3) Then use that matrix to apply a transformation to whatever vector/element you want to have local coordinates: transformVect(), transformBox(), transformPlane(), etc.
Although setInverseRotationDegrees() might be quicker for steps 2 and 3.
Also, you may need to update the scene node's transformation first, before doing all this.
"Computers don't make mistakes! What they do they do on purpose!!"
-Dale Gribble
-Dale Gribble
-
- Posts: 1638
- Joined: Mon Apr 30, 2007 3:24 am
- Location: Montreal, CANADA
- Contact:
Re: Local to World Coordinates and Vice Versa
Hi, Thanks for the replies... Still it doesnt work.
What I want to achieve is to send the WORLD rotation value and get the LOCAL rotation for a node. So I'll be able to match a WORLD rotation, from a parented node.
I tried the same matrix transformation used to get the local coordinate (position), (vitek post) but this doesnt work (the parented node rotation seem to turn at every frame instead of matching the object in world coordinates), using the setInverseRotationDegrees did not do better.
Actually im using this (getting the parented node the proper local angle to match another object world angle):
Then this for getting back later the world angle (the angle value return the previous good value):
Sometimes, it can match, sometimes not (depend of the angle of the world object), but the object is at least not continually rotating from frame to frame. With a lot of testing, I found out that if I'm rotating only the Y axis, I got it matched all the time. If I'm trying another axe or doing a combination, the match doesnt work all the time.
I really don't know what I'm missing. My local object (object parented) don't match the rotation of the object that is world space)
Can this be a problem with gimbal lock? (I think the local angle is good, but perhaps the parented node can't set at the desired angle?)
All the angles are in degrees. The object I'm rotating in world space is rotated in all 3 axes (xyz) by a rotate animator.
What I want to achieve is to send the WORLD rotation value and get the LOCAL rotation for a node. So I'll be able to match a WORLD rotation, from a parented node.
I tried the same matrix transformation used to get the local coordinate (position), (vitek post) but this doesnt work (the parented node rotation seem to turn at every frame instead of matching the object in world coordinates), using the setInverseRotationDegrees did not do better.
Actually im using this (getting the parented node the proper local angle to match another object world angle):
Code: Select all
core::vector3df localangle = worldangle - parentednode->getRotation();
Code: Select all
core::vector3df worldangle = parentednode->getRotation()+localangle;
I really don't know what I'm missing. My local object (object parented) don't match the rotation of the object that is world space)
Can this be a problem with gimbal lock? (I think the local angle is good, but perhaps the parented node can't set at the desired angle?)
All the angles are in degrees. The object I'm rotating in world space is rotated in all 3 axes (xyz) by a rotate animator.
Re: Local to World Coordinates and Vice Versa
Can I tell you once again that you CANNOT ADD EULER ANGLES COMPONENT-WISE? It only works, as you have said, if only one component is non-zero.
I would suggest you convert the angles to quaternions, multiply them together, then convert the result back to Euler angles.
I would suggest you convert the angles to quaternions, multiply them together, then convert the result back to Euler angles.
-
- Posts: 1638
- Joined: Mon Apr 30, 2007 3:24 am
- Location: Montreal, CANADA
- Contact:
Re: Local to World Coordinates and Vice Versa
Thanks! That would finally make sense! I never worked with quaternion before.. Following what you proposed I wrote that and tested it. The angle seem to get wrong again. Can you correct me?
Is that the proper way to multiply a quaternion? Do you have a link to a place that explain why I must multiply the quaternion in order to get the local angle?
What do I do to get the reverse? (A local angle to a world angle)
Is that the proper way to multiply a quaternion? Do you have a link to a place that explain why I must multiply the quaternion in order to get the local angle?
Code: Select all
core::vector3df ConvertToLocal (scene::ISceneNode, core::vector3df worldtoangle)
{
// Create first quaternion from the current "worldangle"
core::quaternion quat=core::quaternion(core::DEGTORAD*worldangle);
// Create the second quaternion from the parent node reference
core::quaternion quat2=core::quaternion(core::DEGTORAD*Node->getRotation());
// Multiply the quaternion?
quat=quat*quat2;
core::vector3df radianLocal = core::vector3df(0,0,0);
quat.toEuler(radianLocal);
return core::vector3df(radianLocal*core::RADTODEG);
}
Re: Local to World Coordinates and Vice Versa
I haven't done a lot of transformation work. But looking at your line of code
if this is "nearly" correct, then what you would need to do is
This gives you the two angles as quaternion rotations. Two combine them, you need to apply the first rotation (quaternion) followed by the second. If they're in the order written, this should be
(I think Irrlicht multiplies them "backwards".)
So, I don't really understand what you are trying to do, but this, I believe, is how you need to combine transformations. In Irrlicht we have quaternions, in OpenGL you would need to use matrices.
You can get the inverse of a quaternion by changing the direction of the "vector" part:
(X, Y, Z) is the axis of rotation of the quaternion and W is the cosine of the half-angle. Reversing the vector results in a rotation in the other direction (or, same direction but upside-down).
Code: Select all
core::vector3df worldangle = parentednode->getRotation()+localangle;
Code: Select all
quaternion q1(DEGTORAD*parentednode->getRotation());
quaternion q2(DEGTORAD*localangle);
Code: Select all
q2 *= q1;
So, I don't really understand what you are trying to do, but this, I believe, is how you need to combine transformations. In Irrlicht we have quaternions, in OpenGL you would need to use matrices.
You can get the inverse of a quaternion by changing the direction of the "vector" part:
Code: Select all
q.X = -q.X;
q.Y = -q.Y;
q.Z = -q.Z;
-
- Posts: 1638
- Joined: Mon Apr 30, 2007 3:24 am
- Location: Montreal, CANADA
- Contact:
Re: Local to World Coordinates and Vice Versa
Thanks a lot for your efforts... I started to read more about the quaternion. Since the only way I see to rotate a node is to use node->setRotation(); it will surely not work as it will produce the same problem (now I'm pretty sure the problem is a gimbal lock problem).
I know we can retrieve the transformation matrix from the node, but can we modify it. Perhaps the "irr::scene::IDummyTransformationSceneNode " could do the trick if we can modify the reference to the matrix... I don't know. But the node will not be able to get the proper rotation until there is a way to bypass it. I don't see anywere we could change the rotation of a node based on quaternions.
This is now getting beyond my current knowledge (not C++ but my shitty math knowledge). My brain is going to explode!
So working with parented nodes is really not suggested for me at the moment, because of gimbal lock problems and no easy way to get it working.
Thanks to you (mongoose) and Travis that provided me with a working solution for positions (that is working 100%). If someone find a way to reposition a node to a local rotation based on a world rotation, then theses should be added to IRRlicht as it would provide an easy way to support "dynamic parenting" of nodes.
I know we can retrieve the transformation matrix from the node, but can we modify it. Perhaps the "irr::scene::IDummyTransformationSceneNode " could do the trick if we can modify the reference to the matrix... I don't know. But the node will not be able to get the proper rotation until there is a way to bypass it. I don't see anywere we could change the rotation of a node based on quaternions.
This is now getting beyond my current knowledge (not C++ but my shitty math knowledge). My brain is going to explode!
So working with parented nodes is really not suggested for me at the moment, because of gimbal lock problems and no easy way to get it working.
Thanks to you (mongoose) and Travis that provided me with a working solution for positions (that is working 100%). If someone find a way to reposition a node to a local rotation based on a world rotation, then theses should be added to IRRlicht as it would provide an easy way to support "dynamic parenting" of nodes.
Re: Local to World Coordinates and Vice Versa
To do transformation related to rotation try:
multiply it with the needed transformation, and get the angle back with:
By "dynamic parenting", do you mean this?
(You might want to updateAbsolutePosition() first.)
Code: Select all
core::matrix4 m;
m.setRotationDegrees(...);
Code: Select all
m.getRotationDegrees();
Code: Select all
void parentAndKeepTransformation(scene::ISceneNode* child, scene::ISceneNode* parent){
core::matrix4 m(core::matrix4::EM4CONST_NOTHING);
parent->getAbsoluteTransformation().getInverse(m);
m *= child->getAbsoluteTransformation();
child->setPosition(m.getTranslation());
child->setRotation(m.getRotationDegrees());
child->setScale(m.getScale());
child->setParent(parent);
}