|
osgEarth 2.1.1
|
Inheritance diagram for osgEarth::Features::SubstituteModelFilter:
Collaboration diagram for osgEarth::Features::SubstituteModelFilter:Public Member Functions | |
| SubstituteModelFilter (const Style &style=Style()) | |
| void | setClustering (bool value) |
| bool | getClustering () const |
| void | setMergeGeometry (bool value) |
| bool | getMergeGeometry () const |
| void | setFeatureNameExpr (const StringExpression &expr) |
| const StringExpression & | getFeatureNameExpr () const |
| virtual osg::Node * | push (FeatureList &input, FilterContext &context) |
Static Public Member Functions | |
| static bool | isSupported () |
Protected Types | |
| typedef LRUCache< URI, osg::ref_ptr< MarkerResource > > | MarkerCache |
Protected Member Functions | |
| bool | process (const FeatureList &features, const MarkerSymbol *symbol, Session *session, osg::Group *ap, FilterContext &context) |
| bool | cluster (const FeatureList &features, const MarkerSymbol *symbol, Session *session, osg::Group *ap, FilterContext &context) |
Protected Attributes | |
| Style | _style |
| bool | _cluster |
| bool | _merge |
| StringExpression | _featureNameExpr |
| MarkerCache | _markerCache |
Feature filter that will substitute external nodes for feature geometry.
TODO:
Definition at line 50 of file SubstituteModelFilter.
typedef LRUCache<URI, osg::ref_ptr<MarkerResource> > osgEarth::Features::SubstituteModelFilter::MarkerCache [protected] |
Definition at line 86 of file SubstituteModelFilter.
Construct a new sub-model filter that will operate on the given style
Definition at line 47 of file SubstituteModelFilter.cpp.
| bool SubstituteModelFilter::cluster | ( | const FeatureList & | features, |
| const MarkerSymbol * | symbol, | ||
| Session * | session, | ||
| osg::Group * | ap, | ||
| FilterContext & | context | ||
| ) | [protected] |
Definition at line 295 of file SubstituteModelFilter.cpp.
{
MarkerToFeatures markerToFeatures;
// first, sort the features into buckets, each bucket corresponding to a
// unique marker.
for (FeatureList::const_iterator i = features.begin(); i != features.end(); ++i)
{
Feature* f = i->get();
// resolve the URI for the marker:
StringExpression uriEx( *symbol->url() );
URI markerURI( f->eval( uriEx ), uriEx.uriContext() );
// find and load the corresponding marker model. We're using the session-level
// object store to cache models. This is thread-safe sine we are always going
// to CLONE the model before using it.
osg::Node* model = context.getSession()->getObject<osg::Node>( markerURI.full() );
if ( !model )
{
osg::ref_ptr<MarkerResource> mres = new MarkerResource();
mres->uri() = markerURI;
model = mres->createNode();
if ( model )
{
context.getSession()->putObject( markerURI.full(), model );
}
}
if ( model )
{
MarkerToFeatures::iterator itr = markerToFeatures.find( model );
if (itr == markerToFeatures.end())
markerToFeatures[ model ].push_back( f );
else
itr->second.push_back( f );
}
}
//For each model, cluster the features that use that marker
for (MarkerToFeatures::iterator i = markerToFeatures.begin(); i != markerToFeatures.end(); ++i)
{
osg::Node* prototype = i->first;
// we're using the Session cache since we know we'll be cloning.
if ( prototype )
{
osg::Node* clone = osg::clone( prototype, osg::CopyOp::DEEP_COPY_ALL );
// ..and apply the clustering to the copy.
ClusterVisitor cv( i->second, symbol, this, context );
clone->accept( cv );
attachPoint->addChild( clone );
}
}
return true;
}
Here is the call graph for this function:
Here is the caller graph for this function:| bool osgEarth::Features::SubstituteModelFilter::getClustering | ( | ) | const [inline] |
Definition at line 62 of file SubstituteModelFilter.
{ return _cluster; }
| const StringExpression& osgEarth::Features::SubstituteModelFilter::getFeatureNameExpr | ( | ) | const [inline] |
Definition at line 73 of file SubstituteModelFilter.
{ return _featureNameExpr; }
| bool osgEarth::Features::SubstituteModelFilter::getMergeGeometry | ( | ) | const [inline] |
Definition at line 66 of file SubstituteModelFilter.
{ return _merge; }
| static bool osgEarth::Features::SubstituteModelFilter::isSupported | ( | ) | [inline, static] |
Definition at line 54 of file SubstituteModelFilter.
{ return true; }
Here is the caller graph for this function:| bool SubstituteModelFilter::process | ( | const FeatureList & | features, |
| const MarkerSymbol * | symbol, | ||
| Session * | session, | ||
| osg::Group * | ap, | ||
| FilterContext & | context | ||
| ) | [protected] |
Definition at line 56 of file SubstituteModelFilter.cpp.
{
bool makeECEF = context.getSession()->getMapInfo().isGeocentric();
// first, go through the features and build the model cache. Apply the model matrix' scale
// factor to any AutoTransforms directly (cloning them as necessary)
std::map< std::pair<URI, float>, osg::ref_ptr<osg::Node> > uniqueModels;
//std::map< Feature*, osg::ref_ptr<osg::Node> > featureModels;
StringExpression uriEx = *symbol->url();
NumericExpression scaleEx = *symbol->scale();
for( FeatureList::const_iterator f = features.begin(); f != features.end(); ++f )
{
Feature* input = f->get();
// evaluate the marker URI expression:
StringExpression uriEx = *symbol->url();
URI markerURI( input->eval(uriEx), uriEx.uriContext() );
// find the corresponding marker in the cache
MarkerResource* marker = 0L;
MarkerCache::Record rec = _markerCache.get( markerURI );
if ( rec.valid() ) {
marker = rec.value();
}
else {
marker = new MarkerResource();
marker->uri() = markerURI;
_markerCache.insert( markerURI, marker );
}
// evalute the scale expression (if there is one)
float scale = 1.0f;
osg::Matrixd scaleMatrix;
if ( symbol->scale().isSet() )
{
scale = input->eval( scaleEx );
if ( scale == 0.0 )
scale = 1.0;
scaleMatrix = osg::Matrix::scale( scale, scale, scale );
}
// how that we have a marker source, create a node for it
std::pair<URI,float> key( markerURI, scale );
osg::ref_ptr<osg::Node>& model = uniqueModels[key];
if ( !model.valid() )
{
model = context.resourceCache()->getMarkerNode( marker );
if ( scale != 1.0f && dynamic_cast<osg::AutoTransform*>( model.get() ) )
{
// clone the old AutoTransform, set the new scale, and copy over its children.
osg::AutoTransform* oldAT = dynamic_cast<osg::AutoTransform*>(model.get());
osg::AutoTransform* newAT = osg::clone( oldAT );
// make a scaler and put it between the new AutoTransform and its kids
osg::MatrixTransform* scaler = new osg::MatrixTransform(osg::Matrix::scale(scale,scale,scale));
for( unsigned i=0; i<newAT->getNumChildren(); ++i )
scaler->addChild( newAT->getChild(0) );
newAT->removeChildren(0, newAT->getNumChildren());
newAT->addChild( scaler );
model = newAT;
}
}
if ( model.valid() )
{
GeometryIterator gi( input->getGeometry(), false );
while( gi.hasMore() )
{
Geometry* geom = gi.next();
for( unsigned i=0; i<geom->size(); ++i )
{
osg::Matrixd mat;
osg::Vec3d point = (*geom)[i];
if ( makeECEF )
{
// the "rotation" element lets us re-orient the instance to ensure it's pointing up. We
// could take a shortcut and just use the current extent's local2world matrix for this,
// but if the tile is big enough the up vectors won't be quite right.
osg::Matrixd rotation;
ECEF::transformAndGetRotationMatrix( context.profile()->getSRS(), point, point, rotation );
mat = rotation * scaleMatrix * osg::Matrixd::translate( point ) * _world2local;
}
else
{
mat = scaleMatrix * osg::Matrixd::translate( point ) * _world2local;
}
osg::MatrixTransform* xform = new osg::MatrixTransform();
xform->setMatrix( mat );
xform->addChild( model.get() );
attachPoint->addChild( xform );
// name the feature if necessary
if ( !_featureNameExpr.empty() )
{
const std::string& name = input->eval( _featureNameExpr );
if ( !name.empty() )
xform->setName( name );
}
}
}
}
}
return true;
}
Here is the call graph for this function:
Here is the caller graph for this function:| osg::Node * SubstituteModelFilter::push | ( | FeatureList & | input, |
| FilterContext & | context | ||
| ) | [virtual] |
Processes a new feature list
Implements osgEarth::Features::FeaturesToNodeFilter.
Definition at line 360 of file SubstituteModelFilter.cpp.
{
if ( !isSupported() ) {
OE_WARN << "SubstituteModelFilter support not enabled" << std::endl;
return 0L;
}
if ( _style.empty() ) {
OE_WARN << LC << "Empty style; cannot process features" << std::endl;
return 0L;
}
const MarkerSymbol* symbol = _style.getSymbol<MarkerSymbol>();
if ( !symbol ) {
OE_WARN << LC << "No MarkerSymbol found in style; cannot process feautres" << std::endl;
return 0L;
}
FilterContext newContext( context );
computeLocalizers( context );
osg::Group* group = createDelocalizeGroup();
bool ok = true;
if ( _cluster )
{
ok = cluster( features, symbol, context.getSession(), group, newContext );
}
else
{
process( features, symbol, context.getSession(), group, newContext );
#if 0
// speeds things up a bit, at the expense of creating tons of geometry..
// this optimizer pass will remove all the MatrixTransform nodes that we
// used to offset each instance
osgUtil::Optimizer optimizer;
optimizer.optimize( group, osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS_DUPLICATING_SHARED_SUBGRAPHS );
#endif
}
return group;
}
Here is the call graph for this function:
Here is the caller graph for this function:| void osgEarth::Features::SubstituteModelFilter::setClustering | ( | bool | value | ) | [inline] |
Whether to cluster all the model instances into a single geode. Default is false.
Definition at line 61 of file SubstituteModelFilter.
{ _cluster = value; }
Here is the caller graph for this function:| void osgEarth::Features::SubstituteModelFilter::setFeatureNameExpr | ( | const StringExpression & | expr | ) | [inline] |
The matrix with which to transform each model instance after placement.
Definition at line 72 of file SubstituteModelFilter.
{ _featureNameExpr = expr; }
Here is the caller graph for this function:| void osgEarth::Features::SubstituteModelFilter::setMergeGeometry | ( | bool | value | ) | [inline] |
Whether to merge marker geometries into geodes
Definition at line 65 of file SubstituteModelFilter.
{ _merge = value; }
bool osgEarth::Features::SubstituteModelFilter::_cluster [protected] |
Definition at line 81 of file SubstituteModelFilter.
Definition at line 84 of file SubstituteModelFilter.
Definition at line 87 of file SubstituteModelFilter.
bool osgEarth::Features::SubstituteModelFilter::_merge [protected] |
Definition at line 82 of file SubstituteModelFilter.
Definition at line 80 of file SubstituteModelFilter.
1.7.3