Hi Robert, I have a very strange bug. The code I have written to render one bin 
twice works fine in the project code-base that I am working on. I took the 
class and integrated into the OSGForest example, and there it does not work as 
expected. In the OSGForest example:- The bin is rendered two times, as 
expected.- The state-set that is added to only one of the bins are now used 
when both bins are rendered. And there is the bug :-/ I would appreciate it if 
you could take a look at the code and try it out. I have attached my class to 
this mail, and below here is the new main function for OSGForest. Just keep the 
rest of the osgforest.cpp file as it is. Only add the include and the green 
code at the bottom of main. 
#include "TransparencyGlitchFixNode.h"
int main( int argc, char **argv )
{
 
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);
   
    // construct the viewer.
    osgViewer::Viewer viewer(arguments);
 
    float numTreesToCreates = 10000;
    arguments.read('--trees',numTreesToCreates);
    
    osg::ref_ptr<ForestTechniqueManager> ttm = new ForestTechniqueManager;
    
    viewer.addEventHandler(new TechniqueEventHandler(ttm.get()));
    viewer.addEventHandler(new 
osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
 
    // add model to viewer.
    TransparencyGlitchFixNode* root = new TransparencyGlitchFixNode();
    root->addChild( ttm->createScene((unsigned int)numTreesToCreates) );
    viewer.setSceneData( root );
 
 
    return viewer.run();
}
 
Here is what to expect:
- The forest will be rendered twice.
- First pass will be additive blend without depth-buffer write.
- Second pass shall be a normal render of the forest.
- The bug is so that the state-set is used both times, so both get 
additive-blend.
 
The additive-blend is something I have added only to ease the visual debugging. 
The final code shall only have the state for turning off depth-buffer write. If 
everything works smoothly then you are supposed to see the forest as normal but 
with high-lighting due to the additive blend at all places where the trees are 
transparent.
 
 
Regards,Viggo

From: [EMAIL PROTECTED]: [EMAIL PROTECTED]: Fri, 25 Jul 2008 10:42:08 
+0200Subject: Re: [osg-users] Robert: I figured it out :-) (was: Is it possible 
to know when the node-graph is 'dirty'?)


Hi Robert, > Hi Viggo,> > The rendering backend uses ref_ptr<>'s so there 
shouldn't be any leak,> assigning the new RenderBin will lead to the previous 
one being> deleted.> Yep I figured out that one :-)> Rather than second guess 
what will be need might I suggest you> maintain a recycling list of ref_ptr<> 
to your custom RenderBin, then> traverse this list to find an entry that has a 
referenceCount() of> one, then take ownership of this.> I took into usage a 
std::list which starts off empty. I am currently counting how many times 
cull-traverse is called and increasing the list at need.  Your idea of checking 
the reference count is better. It will make the system more robust.I will 
continue using a std::list for this.I will keep track of what was the last used 
element of the list, so when I need a new one then I will traverse the list 
from that point. This should increase the chance of finding a free entry 
immediately.If I parse through the whole list, then I will insert a new element 
to the list and use that one. The list will thus grow to the maximum needed 
size and stay there until the class is deleted. Future changes of number of 
cameras or what ever re-configurations that can cause one thread to hold data 
longer will thus automatically work. I am also ensuring that the original 
RenderBinList of RenderStage is not changed anywhere else than for element 10. 
I used to add a new bin to element 9, but that may be in usage already. Element 
10 will instead point to a new bin that contain it's own bin #9 and #10. Both 
will point to the original content that RenderStage pointed to in it's bin 
#10.> Robert.> _______________________________________________> osg-users 
mailing list> osg-users@lists.openscenegraph.org> 
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Få Hotmail du også. Windows Live Hotmail nå med 5000 MB gratis lagringsplass. 

_________________________________________________________________
Morsomme klipp, kjendiser og mer på MSN Video.
http://video.msn.com/?mkt=nb-no&from=HMTAG
#include "TransparencyGlitchFixNode.h"
#include <osg/Depth>
#include <osg/BlendFunc>
#include <osg/StateSet>
#include <osgUtil/CullVisitor>

// ----------------------------------------------------------------------------
/*!
 * \par Actions:
 *      - Creates one state-set that will be used multiple places.
 *      - Creates two helper-bins to be ready for use (see traverse function).
 */
TransparencyGlitchFixNode::TransparencyGlitchFixNode()
: osg::Group ()
, _stateSet  ( 0 )
{
    // Create the state-set that we use to turn off depth-buffer write
    _stateSet = new osg::StateSet();
    _stateSet->ref();
    _stateSet->setMode( GL_DEPTH_TEST, osg::StateAttribute::ON  | 
osg::StateAttribute::OVERRIDE );
    _stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::LESS, 0.0, 1.0, 
false), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );

    // Create the helper bins
    _listHelperBin.clear();
    _listHelperBin.push_back( createHelperBin() );
    _listHelperBin.push_back( createHelperBin() );
    _nextHelperBin = _listHelperBin.begin();

    // Extra state-set settings to highlight the first render-pass (to ease 
visual debugging)
#if 1
    // This enables first pass rendered to use additive blend
    osg::BlendFunc* blendFunc = new osg::BlendFunc( osg::BlendFunc::ONE
                                                  , osg::BlendFunc::ONE
                                                  );
    _stateSet->setAttributeAndModes( blendFunc, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE );
#endif
}

// ----------------------------------------------------------------------------
/*!
 * \par Actions:
 *      - Calls unref on all objects this class has referenced.
 */
TransparencyGlitchFixNode::~TransparencyGlitchFixNode( void )
{
    // Release the helper-bins
    for(   _nextHelperBin  = _listHelperBin.begin();
           _nextHelperBin != _listHelperBin.end();
         ++_nextHelperBin )
    {
        // Release the sub-bin
        ((*_nextHelperBin)->getRenderBinList())[9]->unref();

        // Release the helper-bin
        (*_nextHelperBin)->unref();
    }
    _listHelperBin.clear();

    // Release the state-set
    _stateSet->unref();
}

// ----------------------------------------------------------------------------
/*!
 * \return Pointer to new render-bin.
 * \par Actions:
 *      - Creates a render-bin which contans a sub render-bin.
 *      - Sub render-bin use the _stateSet.
 *
 * The sub-bin is located in the new render-bin's RenderBinList as element 9.
 */
osgUtil::RenderBin* TransparencyGlitchFixNode::createHelperBin()
{
    osgUtil::RenderBin* newBin = new osgUtil::RenderBin();
    osgUtil::RenderBin* subBin = new osgUtil::RenderBin();
    newBin->ref();
    subBin->ref();
    subBin->setStateSet( _stateSet );
    (newBin->getRenderBinList())[9] = subBin;

    // This is the setup:
    //
    //   (newBin)
    //      |
    //      +---(RenderBinList[9]) = (subBin)
    //

    return newBin;
}

// ----------------------------------------------------------------------------
/*!
 * \param nv : The node visitor.
 * \par Actions:
 *      - Runs the traverse.
 *      - Looks for render-bin 10 in the result.
 *      - Ensures that render-bin 10 is rendered twice:
 *          - Once with depth-buffer write turned off.
 *          - Once with depth-buffer write turned on.
 *
 */
void TransparencyGlitchFixNode::traverse( osg::NodeVisitor& nv )
{
    // Traverse children
    osg::Group::traverse( nv );

    // Fix rendering glitches by rendering bin 10 twice
    if( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>( &nv );
        if( cv )
        {
            // Act if we have a RenderStage pointer
            if( osgUtil::RenderStage* renderStage = cv->getRenderStage() )
            {
                // Get the RenderStage's render-bin list
                osgUtil::RenderBin::RenderBinList& renderStageBinList = 
renderStage->getRenderBinList();

                // Only proceed if bin 10 is used
                if( renderStageBinList.find(10) != renderStageBinList.end() )
                {
                    // Find an available bin
                    if( (*_nextHelperBin)->referenceCount() != 1 )
                    {
                        // Traverse the list to look for a free one (refCount 
== 1).
                        // We traverse the whole list one time. If none is 
found, then
                        // we add a new entry to the list.
                        //
                        std::list<osgUtil::RenderBin*>::iterator targetBin = 
_nextHelperBin;
                        while( 1 )
                        {
                            // Move iterator one step ahead in list (wraps to 
start if at end)
                            if( ++targetBin == _listHelperBin.end() )
                            {
                                targetBin = _listHelperBin.begin();
                            }

                            // Did we find a free one?
                            if( (*targetBin)->referenceCount() == 1 )
                            {
                                break;
                            }

                            // Did we go a full circle?
                            if( targetBin == _nextHelperBin )
                            {
                                // Insert a new bin and use that one.
                                // _nextHelperBin still points to the one that 
is most
                                // probable to be available first, so we insert 
the new
                                // one in front of that one.
                                //
                                targetBin = _listHelperBin.insert( targetBin, 
createHelperBin() );
                                break;
                            }
                        }
                        _nextHelperBin = targetBin;
                    }

                    // We have the following pointed to by _nextHelperBin:
                    //
                    // Label N = Our new render-bin (*_nextHelperBin).
                    // Label S = The sub-bin of our new render-bin.
                    // Label R = Content pointed to from RenderStage's 
RenderBinList[10].
                    //
                    // The original setup looks like this:
                    //
                    //     (N) (New render bin)
                    //      |
                    //      +---(RenderBinList[9]) = (S) (New render bin's 
sub-bin)
                    //
                    // We shall set it up to render bin number 10 (from 
RenderStage) twice:
                    //
                    //     (N)
                    //      |
                    //      +---(RenderBinList[9]) = (S)
                    //      |                         |
                    //      |                         +---(RenderBinList[10]) = 
(R)
                    //      |
                    //      +---(RenderBinList[10]) = (R)
                    //
                    //
                    osgUtil::RenderBin::RenderBinList& newBinList = 
(*_nextHelperBin)->getRenderBinList();
                    osgUtil::RenderBin::RenderBinList& subBinList = 
newBinList[9]->getRenderBinList();
                    subBinList[10] = renderStageBinList[10];
                    newBinList[10] = renderStageBinList[10];

                    // RenderStage's RenderBinList[10] shall now point to 
                    // our render bin (N) instead of what it used to point to 
(R).
                    // Remember that bin (R) is pointed to two times from (N).
                    //
                    //  (RenderStage)
                    //        |
                    //        +---(RenderBinList[10]) = (N)
                    //
                    renderStageBinList[10] = *_nextHelperBin;

                    // Advance to most probable free bin
                    if( ++_nextHelperBin == _listHelperBin.end() )
                    {
                        _nextHelperBin = _listHelperBin.begin();
                    }
                }
            }
        }
    }
}
#pragma once

//#include "msvcdefs.h"
#include <list>
#include <osg/Group>
#include <osgUtil/RenderBin>

class TransparencyGlitchFixNode : public osg::Group
{
public:
        //! Constructs a proper %TransparencyGlitchFixNode object.
        TransparencyGlitchFixNode();

        META_Node( Jalla, TransparencyGlitchFixNode ); 

    //! Node-tree traverse function
    virtual void traverse( osg::NodeVisitor& nv );

protected:
        //! Destructor
        virtual ~TransparencyGlitchFixNode( void );

private:
        TransparencyGlitchFixNode( const TransparencyGlitchFixNode& rhs
                             , const osg::CopyOp&           copyop = 
osg::CopyOp::SHALLOW_COPY
                             ){};
        TransparencyGlitchFixNode& operator=( TransparencyGlitchFixNode& rhs );

    osgUtil::RenderBin* createHelperBin();

    std::list<osgUtil::RenderBin*>           _listHelperBin;
    std::list<osgUtil::RenderBin*>::iterator _nextHelperBin;
    osg::StateSet*                           _stateSet;

};
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to