|
osgEarth 2.1.1
|
Inheritance diagram for anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory:
Collaboration diagram for anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory:Public Member Functions | |
| StencilVolumeNodeFactory (const FeatureStencilModelOptions &options, int renderBinStart) | |
| bool | createOrUpdateNode (FeatureCursor *cursor, const Style &style, const FilterContext &context, osg::ref_ptr< osg::Node > &node) |
| osg::Group * | getOrCreateStyleGroup (const Style &style, Session *session) |
Protected Attributes | |
| const FeatureStencilModelOptions | _options |
| int | _renderBinStart |
| BuildData | _buildData |
Definition at line 351 of file FeatureStencilModelSource.cpp.
| anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::StencilVolumeNodeFactory | ( | const FeatureStencilModelOptions & | options, |
| int | renderBinStart | ||
| ) | [inline] |
Definition at line 359 of file FeatureStencilModelSource.cpp.
: _options(options), _buildData( renderBinStart ) { }
| bool anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::createOrUpdateNode | ( | FeatureCursor * | cursor, |
| const Style & | style, | ||
| const FilterContext & | context, | ||
| osg::ref_ptr< osg::Node > & | node | ||
| ) | [inline, virtual] |
Render (or update) a list of features into a node according to the specified style.
Implements osgEarth::Features::FeatureNodeFactory.
Definition at line 365 of file FeatureStencilModelSource.cpp.
{
const MapInfo& mi = context.getSession()->getMapInfo();
// A processing context to use locally
FilterContext cx = context;
// make a working copy of the feature data.
FeatureList featureList;
cursor->fill( featureList );
//for (FeatureList::const_iterator it = features.begin(); it != features.end(); ++it)
// featureList.push_back(osg::clone((*it).get(),osg::CopyOp::DEEP_COPY_ALL));
// establish the extrusion distance for the stencil volumes
double extrusionDistance = 1;
double densificationThreshold = 1.0;
if ( _options.extrusionDistance().isSet() )
{
extrusionDistance = *_options.extrusionDistance();
}
else
{
if ( mi.isGeocentric() )
extrusionDistance = 300000.0; // meters geocentric
else if ( mi.getProfile()->getSRS()->isGeographic() )
extrusionDistance = 5.0; // degrees-as-meters
else
extrusionDistance = 12000.0; // meters
}
densificationThreshold = *_options.densificationThreshold();
// Scan the geometry to see if it includes line data, since that will require buffering:
bool hasLines = false;
for( FeatureList::const_iterator i = featureList.begin(); i != featureList.end(); ++i )
{
Feature* feature = (*i).get();
Geometry* geom = feature->getGeometry();
if ( geom &&
( geom->getComponentType() == Geometry::TYPE_LINESTRING ||
geom->getComponentType() == Geometry::TYPE_RING ) )
{
hasLines = true;
break;
}
}
// If the geometry is lines, we need to buffer them before they will work with stenciling
if ( hasLines )
{
const LineSymbol* line = style.getSymbol<LineSymbol>();
if (line)
{
BufferFilter buffer;
buffer.distance() = 0.5 * line->stroke()->width().value();
buffer.capStyle() = line->stroke()->lineCap().value();
cx = buffer.push( featureList, cx );
}
}
// Transform them into the map's SRS, localizing the verts along the way:
TransformFilter xform( mi.getProfile()->getSRS() );
xform.setMakeGeocentric( mi.isGeocentric() );
xform.setLocalizeCoordinates( !mi.isGeocentric() );
cx = xform.push( featureList, cx );
if ( mi.isGeocentric() )
{
// We need to make sure that on a round globe, the points are sampled such that
// long segments follow the curvature of the earth. By the way, if a Buffer was
// applied, that will also remove colinear segment points. Resample the points to
// achieve a usable tesselation.
ResampleFilter resample;
resample.maxLength() = densificationThreshold;
resample.minLength() = 0.0;
resample.perturbationThreshold() = 0.1;
cx = resample.push( featureList, cx );
}
// Extrude and cap the geometry in both directions to build a stencil volume:
osg::Group* volumes = 0L;
for( FeatureList::iterator i = featureList.begin(); i != featureList.end(); ++i )
{
Feature* feature = (*i).get();
Geometry* geom = feature->getGeometry();
osg::Node* volume = createVolume( geom, -extrusionDistance, extrusionDistance * 2.0, cx );
if ( volume )
{
if ( !volumes )
volumes = new osg::Group();
volumes->addChild( volume );
}
}
if ( volumes )
{
// Resolve the localizing reference frame if necessary:
if ( cx.hasReferenceFrame() )
{
osg::MatrixTransform* xform = new osg::MatrixTransform( cx.inverseReferenceFrame() );
xform->addChild( volumes );
volumes = xform;
}
// Apply an LOD if required:
if ( _options.minRange().isSet() || _options.maxRange().isSet() )
{
osg::LOD* lod = new osg::LOD();
lod->addChild( volumes, _options.minRange().value(), _options.maxRange().value() );
volumes = lod;
}
// Add the volumes to the appropriate style group.
StencilVolumeNode* styleNode = dynamic_cast<StencilVolumeNode*>( getOrCreateStyleGroup( style, cx.getSession() ) );
styleNode->addVolumes( volumes );
}
node = 0L; // always return null, since we added our geom to the style group.
return volumes != 0L;
}
Here is the call graph for this function:| osg::Group* anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::getOrCreateStyleGroup | ( | const Style & | style, |
| Session * | session | ||
| ) | [inline, virtual] |
Creates a group that will contain all the geometry corresponding to a given style. The subclass has the option of overriding this in order to create a custom implementation.
Reimplemented from osgEarth::Features::FeatureNodeFactory.
Definition at line 494 of file FeatureStencilModelSource.cpp.
{
if ( _options.showVolumes() == true )
{
return new osg::Group();
}
else
{
StencilVolumeNode* styleNode = 0L;
if ( !_buildData.getStyleNode(style.getName(), styleNode, true) )
{
// did not find; write-lock it and try again (double-check pattern)
Threading::ScopedWriteLock exclusiveLock( _buildData._mutex );
if ( !_buildData.getStyleNode(style.getName(), styleNode, false) )
{
OE_INFO << LC << "Create style group \"" << style.getName() << "\"" << std::endl;
styleNode = new StencilVolumeNode( *_options.mask(), *_options.inverted() );
if ( _options.mask() == false )
{
osg::Vec4f maskColor = osg::Vec4(1,1,0,1);
if (/*hasLines &&*/ style.getSymbol<LineSymbol>())
{
const LineSymbol* line = style.getSymbol<LineSymbol>();
maskColor = line->stroke()->color();
}
else
{
const PolygonSymbol* poly = style.getSymbol<PolygonSymbol>();
if (poly)
maskColor = poly->fill()->color();
}
styleNode->addChild( createColorNode(maskColor) );
osg::StateSet* ss = styleNode->getOrCreateStateSet();
ss->setMode( GL_LIGHTING, _options.enableLighting() == true?
osg::StateAttribute::ON | osg::StateAttribute::PROTECTED :
osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
}
_buildData._renderBin = styleNode->setBaseRenderBin( _buildData._renderBin );
_buildData._styleGroups.push_back( BuildData::StyleGroup(style.getName(), styleNode) );
}
}
return styleNode;
}
}
Here is the call graph for this function:BuildData anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::_buildData [protected] |
Definition at line 356 of file FeatureStencilModelSource.cpp.
const FeatureStencilModelOptions anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::_options [protected] |
Definition at line 354 of file FeatureStencilModelSource.cpp.
int anonymous_namespace{FeatureStencilModelSource.cpp}::StencilVolumeNodeFactory::_renderBinStart [protected] |
Definition at line 355 of file FeatureStencilModelSource.cpp.
1.7.3