Also this statement has made me want to bring this up again for discussion:
The idea is, that I want to cascade needUpdate() down to the leafs so that each node gets mNeedParentUpdate set to true when one of its parents above it moves and therfore can update its derived rotation/position when _getDerivedRotation()/Translation() is called.CABAListic wrote:In principle, the plan is to add back non-prefixed functions getWorldXXX that will always return the expected values, but so far this hasn't been investigated fully to find the proper way to implement those functions.
My implementation:
Later Edit: version without extra flag, using mNeedParentUpdate as indication whether to cascade down or not.
In a call to Node::needUpdate() check mNeedParentUpdate and cascade the call down if needed:
Code: Select all
void Node::needUpdate(bool forceParentUpdate)
{
[b][u] //mNeedParentUpdate = true; //don't set this here[/u][/b]
mNeedChildUpdate = true;
mCachedTransformOutOfDate = true;
// Make sure we're not root and parent hasn't been notified before
if (mParent && (!mParentNotified || forceParentUpdate))
{
mParent->requestUpdate(this, forceParentUpdate);
mParentNotified = true ;
}
[b][u] //inform children that their combined transforms are out of date if they haven't been notified before
if(!mNeedParentUpdate )
{
ChildNodeMap::iterator i, iend;
iend = mChildren.end();
for (i = mChildren.begin(); i != iend; ++i)
{
i->second->needUpdate(false);
}
mNeedParentUpdate = true ;
}[/u][/b]
// all children will be updated
mChildrenToUpdate.clear();
}
And in _update() don't cascade this to its children with parentHasChanged = true, since the children will now know whether they need to update from their parent or not. Maybe i would now remove this parameter completly but this would definetly mess things up with other classes.
Code: Select all
void Node::_update(bool updateChildren, bool parentHasChanged)
{
// always clear information about parent notification
mParentNotified = false;
// See if we should process everyone
if (mNeedParentUpdate || parentHasChanged)
{
// Update transforms from parent
_updateFromParent();
}
if(updateChildren)
{
if (mNeedChildUpdate || parentHasChanged)
{
ChildNodeMap::iterator it, itend;
itend = mChildren.end();
for (it = mChildren.begin(); it != itend; ++it)
{
Node* child = it->second;
[b][u] child->_update(true, false); //no longer call this with parentHasChanged = true, children are notified when parent moves.[/u][/b]
}
}
else
{
// Just update selected children
ChildUpdateSet::iterator it, itend;
itend = mChildrenToUpdate.end();
for(it = mChildrenToUpdate.begin(); it != itend; ++it)
{
Node* child = *it;
child->_update(true, false);
}
}
mChildrenToUpdate.clear();
mNeedChildUpdate = false;
}
}
The actual transforms are calculated anyway in the next call to _update(), the only thing changed is that it is now possible to prepone this if _getDerivedOrientation()/Position() is called in which case it is no longer calculated in _updated() unless a parent moves again after the calculation.