osgEarth 2.1.1
Classes | Functions

anonymous_namespace{FeatureStencilModelSource.cpp} Namespace Reference

Classes

struct  BuildData
class  StencilVolumeNodeFactory
class  FeatureStencilModelSource

Functions

osg::Node * createColorNode (const osg::Vec4f &color)
void tessellate (osg::Geometry *geom)
osg::Geode * createVolume (osgEarth::Symbology::Geometry *geom, double offset, double height, const FilterContext &context)

Function Documentation

osg::Node* anonymous_namespace{FeatureStencilModelSource.cpp}::createColorNode ( const osg::Vec4f &  color)

Creates a full-screen quad to fill in the colors on the stencil volume.

Definition at line 60 of file FeatureStencilModelSource.cpp.

    {
        // make a full screen quad:
        osg::Geometry* quad = new osg::Geometry();
        osg::Vec3Array* verts = new osg::Vec3Array(4);
        (*verts)[0].set( 0, 1, 0 );
        (*verts)[1].set( 0, 0, 0 );
        (*verts)[2].set( 1, 0, 0 );
        (*verts)[3].set( 1, 1, 0 );
        quad->setVertexArray( verts );
        quad->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
        osg::Vec4Array* colors = new osg::Vec4Array(1);
        (*colors)[0] = color;
        quad->setColorArray( colors );
        quad->setColorBinding( osg::Geometry::BIND_OVERALL );
        osg::Geode* quad_geode = new osg::Geode();
        quad_geode->addDrawable( quad );

        osg::StateSet* quad_ss = quad->getOrCreateStateSet();
        quad_ss->setMode( GL_CULL_FACE, OFF_PROTECTED );
        quad_ss->setMode( GL_DEPTH_TEST, OFF_PROTECTED );
        quad_ss->setMode( GL_LIGHTING, OFF_PROTECTED );
        osg::MatrixTransform* abs = new osg::MatrixTransform();
        abs->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
        abs->setMatrix( osg::Matrix::identity() );
        abs->addChild( quad_geode );

        osg::Projection* proj = new osg::Projection();
        proj->setMatrix( osg::Matrix::ortho(0, 1, 0, 1, 0, -1) );
        proj->addChild( abs );

        proj->getOrCreateStateSet()->setMode( GL_BLEND, 1 );    

        return proj;
    }

Here is the caller graph for this function:

osg::Geode* anonymous_namespace{FeatureStencilModelSource.cpp}::createVolume ( osgEarth::Symbology::Geometry geom,
double  offset,
double  height,
const FilterContext context 
)

Definition at line 106 of file FeatureStencilModelSource.cpp.

    {
        if ( !geom ) return 0L;

        int numRings = 0;

        // start by offsetting the input data and counting the number of rings
        {
            osgEarth::Symbology::GeometryIterator i( geom );
            while( i.hasMore() )
            {
                osgEarth::Symbology::Geometry* part = i.next();

                if (offset != 0.0)
                {
                    for( osg::Vec3dArray::iterator j = part->begin(); j != part->end(); j++ )
                    {
                        if ( context.isGeocentric() )
                        {
                            osg::Vec3d world = context.toWorld( *j );
                            // TODO: get the proper up vector; this is spherical.. or does it really matter for
                            // stencil volumes?
                            osg::Vec3d offset_vec = world;
                            offset_vec.normalize();
                            *j = context.toLocal( world + offset_vec * offset ); //(*j) += offset_vec * offset;
                        }
                        else
                        {
                            (*j).z() += offset;
                        }
                    }
                }

                // in the meantime, count the # of closed geoms. We will need to know this in 
                // order to pre-allocate the proper # of verts.
                if ( part->getType() == osgEarth::Symbology::Geometry::TYPE_POLYGON || part->getType() == osgEarth::Symbology::Geometry::TYPE_RING )
                {
                    numRings++;
                }
            }
        }

        // now, go thru and remove any coplanar segments from the geometry. The tesselator will
        // not work include a vert connecting two colinear segments in the tesselation, and this
        // will break the stenciling logic.
    #define PARALLEL_EPSILON 0.01
        osgEarth::Symbology::GeometryIterator i( geom );
        while( i.hasMore() )
        {
            osgEarth::Symbology::Geometry* part = i.next();
            if ( part->size() >= 3 )
            {
                osg::Vec3d prevVec = part->front() - part->back();
                prevVec.normalize();

                for( osg::Vec3dArray::iterator j = part->begin(); part->size() >= 3 && j != part->end(); )
                {
                    osg::Vec3d& p0 = *j;
                    osg::Vec3d& p1 = j+1 != part->end() ? *(j+1) : part->front();
                    osg::Vec3d vec = p1-p0; vec.normalize();

                    // if the vectors are essentially parallel, remove the extraneous vertex.
                    if ( (prevVec ^ vec).length() < PARALLEL_EPSILON )
                    {
                        j = part->erase( j );
                        //OE_NOTICE << "removed colinear segment" << std::endl;
                    }
                    else
                    {
                        ++j;
                        prevVec = vec;
                    }
                }
            }
        }


        bool made_geom = true;
        const SpatialReference* srs = context.profile()->getSRS();

        // total up all the points so we can pre-allocate the vertex arrays.
        int num_cap_verts = geom->getTotalPointCount();
        int num_wall_verts = 2 * (num_cap_verts + numRings); // add in numRings b/c we need to close each wall

        osg::Geometry* walls = new osg::Geometry();
        osg::Vec3Array* verts = new osg::Vec3Array( num_wall_verts );
        walls->setVertexArray( verts );

        osg::Geometry* top_cap = new osg::Geometry();
        osg::Vec3Array* top_verts = new osg::Vec3Array( num_cap_verts );
        top_cap->setVertexArray( top_verts );

        osg::Geometry* bottom_cap = new osg::Geometry();
        osg::Vec3Array* bottom_verts = new osg::Vec3Array( num_cap_verts );
        bottom_cap->setVertexArray( bottom_verts );

        int wall_vert_ptr = 0;
        int top_vert_ptr = 0;
        int bottom_vert_ptr = 0;

        //double target_len = height;

        // now generate the extruded geometry.
        osgEarth::Symbology::GeometryIterator k( geom );
        while( k.hasMore() )
        {
            osgEarth::Symbology::Geometry* part = k.next();

            unsigned int wall_part_ptr = wall_vert_ptr;
            unsigned int top_part_ptr = top_vert_ptr;
            unsigned int bottom_part_ptr = bottom_vert_ptr;
            double part_len = 0.0;

            GLenum prim_type = part->getType() == osgEarth::Symbology::Geometry::TYPE_POINTSET ? GL_LINES : GL_TRIANGLE_STRIP;

            for( osg::Vec3dArray::const_iterator m = part->begin(); m != part->end(); ++m )
            {
                osg::Vec3d extrude_vec;

                if ( srs )
                {
                    osg::Vec3d m_world = context.toWorld( *m ); //*m * context.inverseReferenceFrame();
                    if ( context.isGeocentric() )
                    {
                        osg::Vec3d p_vec = m_world; // todo: not exactly right; spherical

                        osg::Vec3d unit_vec = p_vec; 
                        unit_vec.normalize();
                        p_vec = p_vec + unit_vec*height;

                        extrude_vec = context.toLocal( p_vec ); //p_vec * context.referenceFrame();
                    }
                    else
                    {
                        extrude_vec.set( m_world.x(), m_world.y(), height );
                        extrude_vec = context.toLocal( extrude_vec ); //extrude_vec * context.referenceFrame();
                    }
                }
                else
                {
                    extrude_vec.set( m->x(), m->y(), height );
                }

                (*top_verts)[top_vert_ptr++] = extrude_vec;
                (*bottom_verts)[bottom_vert_ptr++] = *m;
                 
                part_len += wall_vert_ptr > (int)wall_part_ptr?
                    (extrude_vec - (*verts)[wall_vert_ptr-2]).length() :
                    0.0;

                int p;

                p = wall_vert_ptr++;
                (*verts)[p] = extrude_vec;

                p = wall_vert_ptr++;
                (*verts)[p] = *m;
            }

            // close the wall if it's a ring/poly:
            if ( part->getType() == osgEarth::Symbology::Geometry::TYPE_RING || part->getType() == osgEarth::Symbology::Geometry::TYPE_POLYGON )
            {
                part_len += wall_vert_ptr > (int)wall_part_ptr?
                    ((*verts)[wall_part_ptr] - (*verts)[wall_vert_ptr-2]).length() :
                    0.0;

                int p;

                p = wall_vert_ptr++;
                (*verts)[p] = (*verts)[wall_part_ptr];

                p = wall_vert_ptr++;
                (*verts)[p] = (*verts)[wall_part_ptr+1];
            }

            walls->addPrimitiveSet( new osg::DrawArrays(
                prim_type,
                wall_part_ptr, wall_vert_ptr - wall_part_ptr ) );

            top_cap->addPrimitiveSet( new osg::DrawArrays(
                osg::PrimitiveSet::LINE_LOOP,
                top_part_ptr, top_vert_ptr - top_part_ptr ) );

            // reverse the bottom verts so the front face is down:
            std::reverse( bottom_verts->begin()+bottom_part_ptr, bottom_verts->begin()+bottom_vert_ptr );

            bottom_cap->addPrimitiveSet( new osg::DrawArrays(
                osg::PrimitiveSet::LINE_LOOP,
                bottom_part_ptr, bottom_vert_ptr - bottom_part_ptr ) );
        }

        // build solid surfaces for the caps:
        tessellate( top_cap );
        tessellate( bottom_cap );

        osg::Geode* geode = new osg::Geode();
        geode->addDrawable( walls );
        geode->addDrawable( top_cap );
        geode->addDrawable( bottom_cap );

        return geode;
    }

Here is the call graph for this function:

Here is the caller graph for this function:

void anonymous_namespace{FeatureStencilModelSource.cpp}::tessellate ( osg::Geometry *  geom)

Definition at line 96 of file FeatureStencilModelSource.cpp.

    {
        osgUtil::Tessellator tess;
        tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
        tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
    //    tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );
        tess.retessellatePolygons( *geom );
    }

Here is the caller graph for this function:

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines