Raymond,

We had a similar problem with a few, older, air field models.  Luckily the 
polygons that represent the stripes where positioned in the models scene-graph 
to draw last (with respect to the model).  All that was required was for us to 
turn off depth for the sections that needed it (indicated by comments at the 
nodes that mattered).

//////////////////////////////////////////////////////////////////////////////
class SetAllNodesToNoDepth : public osg::NodeVisitor
{
public:
    SetAllNodesToNoDepth():
      osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
      {}

      void apply( osg::Node& node )
      {
          osg::StateSet* stateset = node.getStateSet();

          if ( stateset )
          {
              stateset->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );

              node.setStateSet( stateset );
          }

          traverse(node);
      }
};

...

model->accept( new SetAllNodesToNoDepth() );

...


I think the order can be managed with render bins as well.

There are a few ways to skin that cat.

Good luck!

-B


-----Original Message-----
From: osg-users-boun...@lists.openscenegraph.org 
[mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of Raymond Bosman
Sent: Monday, November 28, 2011 8:25 AM
To: osg-users@lists.openscenegraph.org
Subject: Re: [osg-users] How to create a decal on a road segment?

To demonstrate the problem here is a screenshot.
[Image: http://forum.openscenegraph.org/files/ramp_segment_587.png ]

The code below shows a simplified version of the problem. When you look at the 
same angle as shown in the screenshot, the 'lanes' (red triangles) will appear 
through the 'road' (green rectangles).


Code:

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/ShapeDrawable>
#include <osg/Depth>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osgDB/WriteFile>

#include <vector>


#include <osg/Stencil>


osg::Geometry * createGeometry( const std::vector<float> &roadheight, float 
width, osg::Vec4Array *color, bool isDecal )
{
  osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;

  // Geometry
  osg::Vec3Array* vertices = new osg::Vec3Array;
  for( int i = 0; i < roadheight.size(); ++i )
  {
    vertices->push_back(osg::Vec3( (float) i, 0 , roadheight[i]));

    if( !isDecal || i % 2 == 1 )
    {
      vertices->push_back(osg::Vec3( (float) i, width , roadheight[i]));
    }
  }

  geometry->setVertexArray(vertices);

  // Set color
  geometry->setColorArray(color);
  geometry->setColorBinding(osg::Geometry::BIND_OVERALL);

  // Normals, all upwards for now
  osg::Vec3Array* normals = new osg::Vec3Array;
  normals->push_back(osg::Vec3(0.0f,0.0f,1.0f));
  geometry->setNormalArray(normals);
  geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);

  geometry->addPrimitiveSet(new osg::DrawArrays( ( isDecal ? 
osg::PrimitiveSet::TRIANGLES : osg::PrimitiveSet::TRIANGLE_STRIP ) 
,0,vertices->size()));

  return geometry.release();
}


osg::Geode*  stencilGeometry( osg::Geometry *road, osg::Geometry *decal)
{
  osg::Geode *geode = new osg::Geode; 

    // Write to stencil buffer
   {
    osg::Stencil* stencil = new osg::Stencil;
    stencil->setFunction(osg::Stencil::ALWAYS, 1,~0u); // Always pass where we 
draw. Write 1 to stencil buffer.
    stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::REPLACE, 
osg::Stencil::REPLACE);

    osg::StateSet *stateset = road->getOrCreateStateSet();
    stateset->setRenderBinDetails(1,"RenderBin");
    stateset->setAttributeAndModes(stencil,osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);
    stateset->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);
    stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);
   }

    geode->addDrawable( road );

    {
    osg::Stencil* stencil = new osg::Stencil;
    stencil->setFunction(osg::Stencil::EQUAL, 1, ~0u); // Draw only if 1.
    stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, 
osg::Stencil::KEEP);

    osg::StateSet *stateset = decal->getOrCreateStateSet();
    stateset->setRenderBinDetails(1,"RenderBin");
    stateset->setAttributeAndModes(stencil,osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);
    stateset->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);
    stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF | 
osg::StateAttribute::OVERRIDE);
    stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);
    }
 
    geode->addDrawable( decal );

    return geode;
}


osg::Geode* multipassGeometry( osg::Geometry *road, osg::Geometry *decal)
{
  osg::Geode *geode = new osg::Geode; 

  // road
  {
    osg::StateSet *stateset = road->getOrCreateStateSet();
    stateset->setRenderBinDetails(1,"RenderBin");
    stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF | 
osg::StateAttribute::OVERRIDE);

    geode->addDrawable( road );
  }

  // Decal
  {
    osg::StateSet *stateset = decal->getOrCreateStateSet();
    stateset->setRenderBinDetails(1,"RenderBin");
    stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);
    stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);

    geode->addDrawable( decal );
  }

  // road again
  {
    osg::Geometry *road2 = (osg::Geometry *) 
road->clone(osg::CopyOp::DEEP_COPY_STATESETS);

    osg::StateSet *stateset = road2->getOrCreateStateSet();
    stateset->setRenderBinDetails(1,"RenderBin");
    stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON | 
osg::StateAttribute::OVERRIDE);

    osg::ColorMask *mask = new osg::ColorMask(false, false, false, false);
    stateset->setAttributeAndModes(mask, osg::StateAttribute::ON); 

    geode->addDrawable( road2 );
  }
  return geode;
}


int main(int argc, char *argv[])
{
    const bool ENABLE_STENCILING = false;

    osg::DisplaySettings::instance()->setMinimumNumStencilBits(1);

    osg::ArgumentParser args(&argc, argv);
    osgViewer::Viewer viewer(args);

    unsigned int clearMask = viewer.getCamera()->getClearMask();
    viewer.getCamera()->setClearMask(clearMask | GL_STENCIL_BUFFER_BIT);
    viewer.getCamera()->setClearStencil(0);

    osg::Group* root = new osg::Group;

    std::vector<float> roadHeight;
    roadHeight.push_back( 1.0f );
    roadHeight.push_back( 1.0f );
    roadHeight.push_back( 0.0f );
    roadHeight.push_back( 0.0f );

    // Create the 'road'.
    osg::Vec4Array* green = new osg::Vec4Array;
    green->push_back( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f ));
    osg::Geometry *geometry = createGeometry( roadHeight, 1.0f, green, false );

    // Create the 'lane markers'
    osg::Vec4Array* red = new osg::Vec4Array;
    red->push_back( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );
    osg::Geometry *decalGeom = createGeometry( roadHeight, 1.0f, red ,true  );
    osg::Geode* geode = 0;

    if ( ENABLE_STENCILING )
    {
      geode = stencilGeometry( geometry, decalGeom );
    }
    else
    {
      geode = multipassGeometry(geometry, decalGeom );
    }

    if( geode )
    {
      viewer.setSceneData( geode );
    }
    viewer.run();
        
    return 0;
}





Raymond.

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=44074#44074




Attachments: 
http://forum.openscenegraph.org//files/ramp_segment_587.png


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

Reply via email to