Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Tags in this Discussion

How to cast from TransformSharedPtr to TransformWeakPtr?

  • Hey guys, sry for this silly question.
    Anyone knows how to do this cast?

    here is were i need this code:
    the goal is to find the boundbox of a subtree of the scene.
    [code]
    GroupReadLock roGroup(transform);
    for( Group::ChildrenConstIterator it=roGroup->beginChildren(); it != roGroup->endChildren(); ++it ) {
    NodeReadLock node(*it);
    int oc = node->getObjectCode();
    if ( oc == OC_TRANSFORM ) {
    TransformSharedPtr transf(*it);
    TransformWeakPtr t = *transf.get(); // <============ doesnt work! :(
    bbt = recursivelyFindBoundingBox(t); // bbt is a Box3f. This function expects a TransformWeakPtr as input param.
    }
    [/code]

    thanks for any help and sorry for such simple question. Still learning ;)
  • 3 Comments sorted by
  • Vote Up0Vote Down Detlef Roettger
    Posts: 330 Accepted Answer
    Should be something like this:

    GroupReadLock roGroup(root);
    for ( Group::ChildrenConstIterator it = roGroup->beginChildren();
    it != roGroup->endChildren(); ++it )
    {
    if ( NodeReadLock(*it)->getObjectCode() == OC_TRANSFORM )
    {
    bbt = recursivelyFindBoundingBox( sharedPtr_cast<Transform>(*it).get() );
    }
    }

    But it's not clear what special thing you are doing which is not handled by the provided getBoundingBox() function on Object which is handling the whole subtree:

    {
    GroupReadLock roGroup(root);
    Box3f b = roGroup->getBoundingBox();
    }


    BTW, instead of getObjectCode() another way to find out if an object is of a specific type is to use the isPtrTo<> templates in Object.h. There are two versions for SharedPtr and WeakPtr, they are a little mightier but maybe slower than the getObjectCode() because they use a dynamic_cast. The examples are full of them, normally to figure out a camera type.
  • It works!! cool.

    I had written 2 versions of a long answer explaining the cause of that recursive function and each time i did i found myself a better way to solve the problem. lol.

    To be very short it is because not all the objects should be counted in the calculation of the BoundingBox. There are some "control" geometries that need to be discarded (like a external grid to show the selection) and there is other nodes of other subtree that could be possible counted too.

    Even then i think i could use a searchTraverser... i don't have much sure, but i think i will try it (probably it is LOT faster than my recursive funtion ;)

    Anyway, thanks a LOT Detlef. As always, you helped so much!

    best regards,
    - Luís
  • Mind that the result of a SearchTraverser is the unique path to the node in the graph. It's a graph, not a tree, so the whole path needs to be considered to uniquely identify an object.
    The SearchTraverser has been sped up in SceniX 7.2 and also uses less memory. You can follow the path's WeakPtrs and drill down to individual objects. There are multiple examples handling the nodes WeakPtr in these paths, for example the QtForwardShadowMapping example the SceneRendererFSM::getShadowCamera() function used that to accumulate transforms.

    Now what you describe sounds more like you could also just implement a custom Traverser which walks over the scene graph nodes and handles the ones you're interested in the way you need, and let the other nodes just be traversed be the baseclass (Shared- or ExclusiveTraverser).
    That is the way algorithms on the scene graph are always implemented in SceniX. If you have done it once, it's super easy.

    Basically derive a class from SharedTraverser if you do not want to edit the graph during the traversal, implement the virtual handle*() functions of the nodes and let them calculate the results you need.
    One of the simplest traversers inside SceniX is the DeindexTraverser I use here as skeleton because it only overrides two virtual functions. That would be all for a traverser which only cares about Primitive nodes for example.


    // In SceniX this one is based on ExclusiveTraverser because it edits the scene contents!
    class DeindexTraverser : public ExclusiveTraverser
    {
    public:
    //! Constructor
    NVSG_API DeindexTraverser(void);

    protected:
    //! Protected destructor to prevent instantiation of a DeindexTraverser.
    NVSG_API virtual ~DeindexTraverser(void);

    NVSG_API virtual void doApply( const nvsg::NodeSharedPtr & root );
    NVSG_API virtual void handlePrimitive( nvsg::Primitive *p );
    };

    DeindexTraverser::DeindexTraverser(void) {}
    DeindexTraverser::~DeindexTraverser(void) {}

    // This is also not needed unless you want to do something
    // traverser-specific before or after the scene traversal.
    void DeindexTraverser::doApply( const NodeSharedPtr & root )
    {
    // (Omitted: The DeindexTraverser calls a DestrippingTraverser before it starts
    // its own traversal here, that's why the doApply() entry point is overridden at all.)
    ExclusiveTraverser::doApply(root);
    }

    void DeindexTraverser::handlePrimitive( Primitive *p )
    {
    // TODO Put code here if you want to handle things before the baseclass traversal.
    ExclusiveTraverser::handlePrimitive( p ); // Always call the baseclass traversal!
    // TODO Put code here if you want to handle things after the baseclass traversal.
    }


    That's it, a custom (Exclusive-) Traverser implementation!

    There was only one SharedTraverser implementation inside the examples needed, look for the class SceniXSceneItemModelTraverser : public nvtraverser::SharedTraverser inside the Viewer which has a more complete set of virtual functions overloaded.