cdrwolfe wrote:before setting either lets say we have node A with position 1,1,1 and node B position 5,5,5
If you were to set node A to be a child of node B then does it retain it's orignal position and simply change it to be relative to the parent so it will read 1,1,1 but really be 4,4,4? in absolute position sense.
The relative position of the node will not be updated when the object is reparented. If we assume that A and B are parented to the root scene node, then their relative positions are their absolute positions. If you set A to be a child of B, A will be offset from the absolute position of B by its own relative position. So the new absolute position of A will be (5, 5, 5) + (1, 1, 1), the relative position will remain (1, 1, 1).
If you want to reparent a node without affecting its absolute position, you need to calculate the new position, and then apply it. I belive that the following code would do the trick. Of course if you want the node to be oriented and scaled correctly, you can use the absolute transformations to do something similar...
Code: Select all
// ensure position is up to date
A->updateAbsolutePosition();
// get the current world position of A
core::vector3df pos = A->getAbsolutePosition();
// transform that position into B's coordinate system
B->getAbsoluteTransformation().inverseTranslateVect(pos);
// set A as a child of B
A->setParent (B);
// move A into B's coordinate system
A->setPosition (pos);
// update the absolute transformation of A
A->updateAbsolutePosition ();
If this is true above, when does it exactly become fact, i've been told that absolute positions are updated every frame so any change inbetween one isn't applied yet.
The absolute positions are updated automatically inside the
smgr->drawAll(). If you want to update the absolute position explicitly, you can do it with
updateAbsolutePosition().
I've been fiddling with updateabsoluteposition() but this doesn't seem to be having the effect i would expect.
It does work, you just have to update the absolute positions of all of the nodes up to the root.
If i create a node, then create a parent node. Set the parent nodes position to that of the first node, make it a parent of the first node and then move the parent node to another position, even if i call updateabsoluteposition() several times the first node always shows the same absolute position which is the same as its relative position.
Yes, like I said, you need to update the absolute positions of all nodes involved. By default the
AbsoluteTransformation of each scene node is the identity matrix. If you call
updateAbsolutePosition(), the relative position, rotation and scale are applied to the
AbsoluteTransformation matrix in addition to the
AbsoluteTransformation of the parent scene node. But if the parent matrix hasn't been updated, then the child position won't include the parent position, rotation and scale.
The following function can update the position of a node and its ancestors, thus getting it the most up to date
AbsoluteTransformation.
Code: Select all
void ISceneNode_updateAbsolutePosition (scene::ISceneNode* node)
{
scene::ISceneNode* parent = node->getParent ();
if (parent)
ISceneNode_updateAbsolutePosition (parent);
node->updateAbsolutePosition ();
}
Surly you would expect both nodes to be either placed in the same position or for the first node to be slightly displaced becuase it is relative to the parent now, however it seems its position is only finally set correctly when the next frame is invoked.
If you specify the position as a parameter to the
add*SceneNode function, the
AbsoluteTransformation will be updated before the
add*SceneNode call returns. If you do this for all scene nodes, then all objects will be placed at the correct positions.
If you have a full scene graph that you want to update, the following code will do just that...
Code: Select all
void ISceneNode_updateAll (scene::ISceneNode* node)
{
node->updateAbsolutePosition();
core::list<scene::ISceneNode*>::ConstIterator beg = node->getChildren ().begin();
core::list<scene::ISceneNode*>::ConstIterator end = node->getChildren ().end ();
for (/**/; beg != end; ++beg)
ISceneNode_updateAll (*beg);
}
void ISceneManager_updateAll (scene::ISceneManager* smgr)
{
ISceneNode_updateAll (smgr->getRootSceneNode ());
}
Travis