简体   繁体   中英

How to remove a node from its callback function?

There is a Geode whose Geometry is a ball with a MatrixTransform() assigned above it. It's callback function makes it falls. When the ball intersects with the ground, I hope to remove it from the scene.

The following code throws exception:

//inside the ball's callback

virtual void operator()(osg::Node* node ,osg::NodeVisitor* nv)
{
    using namespace osg;
    MatrixTransform* matrix_node = dynamic_cast<MatrixTransform*>(node);
    Matrix matrix = matrix_node->getMatrix();

    velocity += Vec3(0, 0, -0.002);

    matrix.postMultTranslate(velocity);

    matrix_node->setMatrix(matrix);

    Vec3 now_position = start_position * matrix;

    osgUtil::IntersectVisitor ivXY; 

    osg::ref_ptr<osg::LineSegment> lineXY = new osg::LineSegment(now_position, now_position+velocity); 

    ivXY.addLineSegment(lineXY);

    GAME.main_camera->m_pHostViewer->getSceneData()->accept(ivXY) ;
    if(ivXY.hits())
    {
        node->getParent(0)->removeChild(node);
    }
    return;
}

How to do it correctly? Thank you!

This is an excerpt from the OpenSceneGraph Group class (from which MatrixTransform inherits):

void Group::traverse(NodeVisitor& nv)
{
        for(NodeList::iterator itr=_children.begin();
        itr!=_children.end();
        ++itr)
    {
        (*itr)->accept(nv);
    }
}

bool Group::removeChild( Node *child )
{
    unsigned int pos = getChildIndex(child);
    if (pos<_children.size()) return removeChildren(pos,1);
    else return false;
}

Your code (which is called from traverse) throws an exception probably because the iterator gets invalidated in the middle of the loop, when removeChild is called. To remove the node you would have to wait at least until your node callback returns.

To resolve this I would just use a node mask to control whether the ball is displayed or not. Initially, set the ball node mask to the "visible" value. When the ball hits the ground, set the node mask to the "hidden" value. The node will not be traversed/rendered, but will still be in memory.

If memory is an issue, you can move the code to the parent node or outside the update traversal (eg use a modified Viewer::run method).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM