IECore::ConstCompoundObjectPtr SceneReader::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { return parent->attributesPlug()->defaultValue(); } // read attributes SceneInterface::NameList nameList; s->attributeNames( nameList ); CompoundObjectPtr result = new CompoundObject; for( SceneInterface::NameList::iterator it = nameList.begin(); it != nameList.end(); ++it ) { // these internal attributes should be ignored: if( *it == SceneCache::animatedObjectTopologyAttribute ) { continue; } if( *it == SceneCache::animatedObjectPrimVarsAttribute ) { continue; } // the const cast is ok, because we're only using it to put the object into a CompoundObject that will // be treated as forever const after being returned from this function. result->members()[ std::string( *it ) ] = boost::const_pointer_cast<Object>( s->readAttribute( *it, context->getTime() ) ); } return result; }
static void loadSetWalk( const SceneInterface *s, const InternedString &setName, PathMatcher &set, const vector<InternedString> &path ) { if( s->hasTag( setName, SceneInterface::LocalTag ) ) { set.addPath( path ); } // Figure out if we need to recurse by querying descendant tags to see if they include // anything we're interested in. if( !s->hasTag( setName, SceneInterface::DescendantTag ) ) { return; } // Recurse to the children. SceneInterface::NameList childNames; s->childNames( childNames ); vector<InternedString> childPath( path ); childPath.push_back( InternedString() ); // room for the child name for( SceneInterface::NameList::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it ) { ConstSceneInterfacePtr child = s->child( *it ); childPath.back() = *it; loadSetWalk( child.get(), setName, set, childPath ); } }
void SceneCacheNode<BaseType>::descendantNames( const IECoreScene::SceneInterface *scene, std::vector<std::string> &descendants ) { if ( !scene ) { return; } SceneInterface::NameList children; scene->childNames( children ); std::string current = ""; if ( scene->name() != SceneInterface::rootName ) { SceneInterface::Path p; scene->path( p ); SceneInterface::pathToString( p, current ); } for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { descendants.push_back( current + "/" + it->value() ); } for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { descendantNames( scene->child( *it ).get(), descendants ); } };
void SOP_SceneCacheSource::loadObjects( const IECore::SceneInterface *scene, Imath::M44d transform, double time, Space space, const UT_StringMMPattern &shapeFilter, const std::string &attributeFilter, size_t rootSize ) { if ( scene->hasObject() && UT_String( scene->name() ).multiMatch( shapeFilter ) ) { ObjectPtr object = scene->readObject( time ); std::string name = relativePath( scene, rootSize ); bool hasAnimatedTopology = scene->hasAttribute( SceneCache::animatedObjectTopologyAttribute ); bool hasAnimatedPrimVars = scene->hasAttribute( SceneCache::animatedObjectPrimVarsAttribute ); std::vector<InternedString> animatedPrimVars; if ( hasAnimatedPrimVars ) { const ObjectPtr animatedPrimVarObj = scene->readAttribute( SceneCache::animatedObjectPrimVarsAttribute, 0 ); const InternedStringVectorData *animatedPrimVarData = IECore::runTimeCast<const InternedStringVectorData>( animatedPrimVarObj ); if ( animatedPrimVarData ) { const std::vector<InternedString> &values = animatedPrimVarData->readable(); animatedPrimVars.resize( values.size() ); std::copy( values.begin(), values.end(), animatedPrimVars.begin() ); } } modifyObject( object, name, hasAnimatedTopology, hasAnimatedPrimVars, animatedPrimVars ); Imath::M44d currentTransform; if ( space == Local ) { currentTransform = scene->readTransformAsMatrix( time ); } else if ( space != Object ) { currentTransform = transform; } // transform the object unless its an identity if ( currentTransform != Imath::M44d() ) { transformObject( object, currentTransform, hasAnimatedTopology, hasAnimatedPrimVars, animatedPrimVars ); } // convert the object to Houdini if ( !convertObject( object, name, attributeFilter, hasAnimatedTopology, hasAnimatedPrimVars, animatedPrimVars ) ) { addError( SOP_LOAD_UNKNOWN_BINARY_FLAG, ( "Could not convert " + name + " to houdini" ).c_str() ); } } SceneInterface::NameList children; scene->childNames( children ); for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { ConstSceneInterfacePtr child = scene->child( *it ); loadObjects( child, child->readTransformAsMatrix( time ) * transform, time, space, shapeFilter, attributeFilter, rootSize ); } }
IECore::ConstInternedStringVectorDataPtr SceneReader::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { return parent->childNamesPlug()->defaultValue(); } // get the child names InternedStringVectorDataPtr resultData = new InternedStringVectorData; vector<InternedString> &result = resultData->writable(); s->childNames( result ); // filter out any which don't have the right tags std::string tagsString = tagsPlug()->getValue(); if( !tagsString.empty() ) { typedef boost::tokenizer<boost::char_separator<char> > Tokenizer; Tokenizer tagsTokenizer( tagsString, boost::char_separator<char>( " " ) ); vector<InternedString> tags; std::copy( tagsTokenizer.begin(), tagsTokenizer.end(), back_inserter( tags ) ); vector<InternedString>::iterator newResultEnd = result.begin(); SceneInterface::NameList childTags; for( vector<InternedString>::const_iterator cIt = result.begin(), cEIt = result.end(); cIt != cEIt; ++cIt ) { ConstSceneInterfacePtr child = s->child( *cIt ); childTags.clear(); child->readTags( childTags, IECore::SceneInterface::EveryTag ); bool childMatches = false; for( SceneInterface::NameList::const_iterator tIt = childTags.begin(), tEIt = childTags.end(); tIt != tEIt; ++tIt ) { if( find( tags.begin(), tags.end(), *tIt ) != tags.end() ) { childMatches = true; break; } } if( childMatches ) { *newResultEnd++ = *cIt; } } result.erase( newResultEnd, result.end() ); } return resultData; }
void SceneCacheNode<BaseType>::objectNames( const IECore::SceneInterface *scene, std::vector<std::string> &objects ) { if ( scene->hasObject() ) { objects.push_back( scene->name() ); } SceneInterface::NameList children; scene->childNames( children ); for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { objectNames( scene->child( *it ), objects ); } };
bool SceneCacheNode<BaseType>::tagged( const IECore::SceneInterface *scene, const UT_StringMMPattern &filter ) { SceneInterface::NameList tags; scene->readTags( tags ); for ( SceneInterface::NameList::const_iterator it=tags.begin(); it != tags.end(); ++it ) { if ( UT_String( *it ).multiMatch( filter ) ) { return true; } } // an empty list should be equivalent to matching an empty string if ( tags.empty() && UT_String( "" ).multiMatch( filter ) ) { return true; } return false; }
void SceneShape::sceneShapeAttributeNames( const MDagPath &p, SceneInterface::NameList &attributeNames ) { MDagPath dagPath; SceneShape *sceneShape = findScene( p, false, &dagPath ); if ( !sceneShape ) { return; } SceneInterface::NameList sceneAttrNames; ConstSceneInterfacePtr scene = sceneShape->getSceneInterface(); if ( !scene ) { return; } scene->attributeNames( sceneAttrNames ); attributeNames.insert( attributeNames.end(), sceneAttrNames.begin(), sceneAttrNames.end() ); MFnDagNode fnChildDag( dagPath ); if( !fnChildDag.isIntermediateObject() && hasSceneShapeLink( p ) ) { attributeNames.push_back( LinkedScene::linkAttribute ); } }
OBJ_Node *OBJ_SceneCacheTransform::doExpandChild( const SceneInterface *scene, OP_Network *parent, const Parameters ¶ms ) { OP_Node *opNode = parent->createNode( OBJ_SceneCacheTransform::typeName, scene->name().c_str() ); OBJ_SceneCacheTransform *xform = reinterpret_cast<OBJ_SceneCacheTransform*>( opNode ); xform->referenceParent( pFile.getToken() ); xform->setPath( scene ); xform->setSpace( Local ); xform->setGeometryType( (OBJ_SceneCacheTransform::GeometryType)params.geometryType ); xform->setAttributeFilter( params.attributeFilter ); xform->setAttributeCopy( params.attributeCopy ); xform->setShapeFilter( params.shapeFilter ); xform->setFullPathName( params.fullPathName ); xform->setInt( pHierarchy.getToken(), 0, 0, params.hierarchy ); xform->setInt( pDepth.getToken(), 0, 0, params.depth ); SceneInterface::NameList children; scene->childNames( children ); if ( children.empty() && !scene->hasObject() ) { xform->setInt( pExpanded.getToken(), 0, 0, 1 ); } if ( tagged( scene, params.tagFilter ) ) { xform->setTagFilter( params.tagFilterStr ); } else { xform->setDisplay( false ); } if ( params.hierarchy == SubNetworks ) { xform->setIndirectInput( 0, parent->getParentInput( 0 ) ); } return xform; }
ROP_RENDER_CODE ROP_SceneCacheWriter::doWrite( const SceneInterface *liveScene, SceneInterface *outScene, double time ) { if ( liveScene != m_liveScene ) { outScene->writeTransform( liveScene->readTransform( time ), time ); } if ( liveScene->hasObject() ) { try { /// \todo: does an invisible node mean there is no object? outScene->writeObject( liveScene->readObject( time ), time ); } catch ( IECore::Exception &e ) { addError( ROP_MESSAGE, e.what() ); return ROP_ABORT_RENDER; } } SceneInterface::NameList children; liveScene->childNames( children ); for ( SceneInterface::NameList::iterator it = children.begin(); it != children.end(); ++it ) { /// \todo: does an invisible node mean its not a child? ConstSceneInterfacePtr liveChild = liveScene->child( *it ); SceneInterfacePtr outChild = outScene->child( *it, SceneInterface::CreateIfMissing ); ROP_RENDER_CODE status = doWrite( liveChild, outChild, time ); if ( status != ROP_CONTINUE_RENDER ) { return status; } } return ROP_CONTINUE_RENDER; }
void SceneCacheNode<BaseType>::buildTagFilterMenu( void *data, PRM_Name *menu, int maxSize, const PRM_SpareData *, const PRM_Parm * ) { SceneCacheNode<BaseType> *node = reinterpret_cast<SceneCacheNode<BaseType>*>( data ); if ( !node ) { return; } menu[0].setToken( "*" ); menu[0].setLabel( "*" ); std::string file; if ( !node->ensureFile( file ) ) { // mark the end of our menu menu[1].setToken( 0 ); return; } ConstSceneInterfacePtr scene = node->scene( file, node->getPath() ); if ( !scene ) { // mark the end of our menu menu[1].setToken( 0 ); return; } SceneInterface::NameList tags; scene->readTags( tags ); std::vector<std::string> tagStrings; for ( SceneInterface::NameList::const_iterator it=tags.begin(); it != tags.end(); ++it ) { tagStrings.push_back( *it ); } node->createMenu( menu, tagStrings ); }
IECore::ConstCompoundObjectPtr SceneReader::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { std::string fileName = fileNamePlug()->getValue(); if( !fileName.size() ) { return parent->attributesPlug()->defaultValue(); } ConstSceneInterfacePtr s = SharedSceneInterfaces::get( fileName ); s = s->scene( path ); // read attributes SceneInterface::NameList nameList; s->attributeNames( nameList ); CompoundObjectPtr result = new CompoundObject; for( SceneInterface::NameList::iterator it = nameList.begin(); it != nameList.end(); ++it ) { // these internal attributes should be ignored: if( *it == SceneCache::animatedObjectTopologyAttribute ) { continue; } if( *it == SceneCache::animatedObjectPrimVarsAttribute ) { continue; } // the const cast is ok, because we're only using it to put the object into a CompoundObject that will // be treated as forever const after being returned from this function. result->members()[ std::string( *it ) ] = constPointerCast<Object>( s->readAttribute( *it, context->getFrame() / g_frameRate ) ); } // read tags and turn them into attributes of the form "user:tag:tagName" nameList.clear(); s->readTags( nameList, IECore::SceneInterface::LocalTag ); for( SceneInterface::NameList::const_iterator it = nameList.begin(); it != nameList.end(); ++it ) { if( it->string().compare( 0, 11, "ObjectType:" ) == 0 ) { continue; } result->members()["user:tag:"+it->string()] = g_trueBoolData; } return result; }
void SceneReader::hashAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { h = parent->attributesPlug()->defaultValue()->Object::hash(); return; } SceneInterface::NameList attributeNames; s->attributeNames( attributeNames ); SceneInterface::NameList tagNames; s->readTags( tagNames, IECore::SceneInterface::LocalTag ); if( !attributeNames.size() && !tagNames.size() ) { h = parent->attributesPlug()->defaultValue()->Object::hash(); return; } FileSource::hashAttributes( path, context, parent, h ); bool animated = false; const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() ); if( !ss ) { animated = true; } else { for( SceneInterface::NameList::iterator it = attributeNames.begin(); it != attributeNames.end(); ++it ) { if( ss->numAttributeSamples( *it ) > 1 ) { animated = true; break; } } } if( animated ) { h.append( context->getFrame() ); } }
void OBJ_SceneCacheTransform::attributeNames( const OP_Node *node, SceneInterface::NameList &attrs ) { // make sure its a SceneCacheNode if ( !node->hasParm( pFile.getToken() ) || !node->hasParm( pRoot.getToken() ) ) { return; } const SceneCacheNode<OP_Node> *sceneNode = reinterpret_cast< const SceneCacheNode<OP_Node>* >( node ); /// \todo: do we need to ensure the file exists first? ConstSceneInterfacePtr scene = OBJ_SceneCacheTransform::scene( sceneNode->getFile(), sceneNode->getPath() ); if ( !scene ) { return; } scene->attributeNames( attrs ); const char *expanded = pExpanded.getToken(); if ( node->hasParm( expanded ) && !node->evalInt( expanded, 0, 0 ) ) { attrs.push_back( LinkedScene::linkAttribute ); } }
void SOP_SceneCacheSource::loadObjects( const IECore::SceneInterface *scene, Imath::M44d transform, double time, Space space, const UT_StringMMPattern &shapeFilter, const std::string &attributeFilter, GeometryType geometryType, size_t rootSize ) { UT_Interrupt *progress = UTgetInterrupt(); progress->setLongOpText( ( "Loading " + scene->name().string() ).c_str() ); if ( progress->opInterrupt() ) { return; } if ( scene->hasObject() && UT_String( scene->name() ).multiMatch( shapeFilter ) ) { // \todo See if there are ways to avoid the Object copy below. ObjectPtr object = scene->readObject( time )->copy(); std::string name = relativePath( scene, rootSize ); bool hasAnimatedTopology = scene->hasAttribute( SceneCache::animatedObjectTopologyAttribute ); bool hasAnimatedPrimVars = scene->hasAttribute( SceneCache::animatedObjectPrimVarsAttribute ); std::vector<InternedString> animatedPrimVars; if ( hasAnimatedPrimVars ) { const ConstObjectPtr animatedPrimVarObj = scene->readAttribute( SceneCache::animatedObjectPrimVarsAttribute, 0 ); const InternedStringVectorData *animatedPrimVarData = IECore::runTimeCast<const InternedStringVectorData>( animatedPrimVarObj ); if ( animatedPrimVarData ) { const std::vector<InternedString> &values = animatedPrimVarData->readable(); animatedPrimVars.resize( values.size() ); std::copy( values.begin(), values.end(), animatedPrimVars.begin() ); } } modifyObject( object, name, attributeFilter, hasAnimatedTopology, hasAnimatedPrimVars, animatedPrimVars ); Imath::M44d currentTransform; if ( space == Local ) { currentTransform = scene->readTransformAsMatrix( time ); } else if ( space != Object ) { currentTransform = transform; } // transform the object unless its an identity if ( currentTransform != Imath::M44d() ) { transformObject( object, currentTransform, hasAnimatedTopology, hasAnimatedPrimVars, animatedPrimVars ); } // load the Cortex object directly if ( geometryType == Cortex ) { holdObject( object, name, hasAnimatedTopology, hasAnimatedPrimVars, animatedPrimVars ); } else { // convert the object to Houdini if ( !convertObject( object, name, attributeFilter, geometryType, hasAnimatedTopology, hasAnimatedPrimVars, animatedPrimVars ) ) { std::string fullName; SceneInterface::Path path; scene->path( path ); SceneInterface::pathToString( path, fullName ); addWarning( SOP_MESSAGE, ( "Could not convert " + fullName + " to houdini" ).c_str() ); } } } if ( evalInt( pObjectOnly.getToken(), 0, 0 ) ) { return; } SceneInterface::NameList children; scene->childNames( children ); for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { ConstSceneInterfacePtr child = scene->child( *it ); loadObjects( child, child->readTransformAsMatrix( time ) * transform, time, space, shapeFilter, attributeFilter, geometryType, rootSize ); } }
void OBJ_SceneCacheTransform::doExpandChildren( const SceneInterface *scene, OP_Network *parent, const Parameters ¶ms ) { UT_Interrupt *progress = UTgetInterrupt(); progress->setLongOpText( ( "Expanding " + scene->name().string() ).c_str() ); if ( progress->opInterrupt() ) { return; } OP_Network *inputNode = parent; if ( params.hierarchy == Parenting ) { parent = parent->getParent(); } SceneInterface::NameList children; scene->childNames( children ); for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { ConstSceneInterfacePtr child = scene->child( *it ); OBJ_Node *childNode = 0; if ( params.hierarchy == SubNetworks ) { childNode = doExpandChild( child.get(), parent, params ); if ( params.depth == AllDescendants && child->hasObject() && tagged( child.get(), params.tagFilter ) ) { Parameters childParams( params ); childParams.depth = Children; doExpandObject( child.get(), childNode, childParams ); } } else if ( params.hierarchy == Parenting ) { if ( child->hasObject() ) { Parameters childParams( params ); childParams.depth = Children; childNode = doExpandObject( child.get(), parent, childParams ); } else { childNode = doExpandChild( child.get(), parent, params ); } childNode->setInput( 0, inputNode ); } if ( params.depth == AllDescendants ) { if ( params.hierarchy == SubNetworks && !tagged( child.get(), params.tagFilter ) ) { // we don't expand non-tagged children for SubNetwork mode, but we // do for Parenting mode, because otherwise the hierarchy would be // stuck in an un-expandable state. continue; } doExpandChildren( child.get(), childNode, params ); childNode->setInt( pExpanded.getToken(), 0, 0, 1 ); } } OP_Layout layout( parent ); #if UT_MAJOR_VERSION_INT >= 16 OP_SubnetIndirectInput *parentInput = parent->getParentInput( 0 ); layout.addLayoutItem( parentInput->getInputItem() ); for ( int i=0; i < parent->getNchildren(); ++i ) { layout.addLayoutItem( parent->getChild( i ) ); } #else layout.addLayoutOp( parent->getParentInput( 0 ) ); for ( int i=0; i < parent->getNchildren(); ++i ) { layout.addLayoutOp( parent->getChild( i ) ); } #endif layout.layoutOps( OP_LAYOUT_TOP_TO_BOT, parent, parent->getParentInput( 0 ) ); }
void SOP_SceneCacheSource::loadObjects( const IECore::SceneInterface *scene, Imath::M44d transform, double time, Space space, Parameters ¶ms, size_t rootSize ) { UT_Interrupt *progress = UTgetInterrupt(); progress->setLongOpText( ( "Loading " + scene->name().string() ).c_str() ); if ( progress->opInterrupt() ) { return; } if ( scene->hasObject() && UT_String( scene->name() ).multiMatch( params.shapeFilter ) && tagged( scene, params.tagFilter ) ) { std::string name = relativePath( scene, rootSize ); Imath::M44d currentTransform; if ( space == Local ) { currentTransform = scene->readTransformAsMatrix( time ); } else if ( space != Object ) { currentTransform = transform; } ConstObjectPtr object = 0; if ( params.geometryType == BoundingBox ) { Imath::Box3d bound = scene->readBound( time ); object = MeshPrimitive::createBox( Imath::Box3f( bound.min, bound.max ) ); params.hasAnimatedTopology = false; params.hasAnimatedPrimVars = true; params.animatedPrimVars.clear(); params.animatedPrimVars.push_back( "P" ); } else if ( params.geometryType == PointCloud ) { std::vector<Imath::V3f> point( 1, scene->readBound( time ).center() ); PointsPrimitivePtr points = new PointsPrimitive( new V3fVectorData( point ) ); std::vector<Imath::V3f> basis1( 1, Imath::V3f( currentTransform[0][0], currentTransform[0][1], currentTransform[0][2] ) ); std::vector<Imath::V3f> basis2( 1, Imath::V3f( currentTransform[1][0], currentTransform[1][1], currentTransform[1][2] ) ); std::vector<Imath::V3f> basis3( 1, Imath::V3f( currentTransform[2][0], currentTransform[2][1], currentTransform[2][2] ) ); points->variables["basis1"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis1 ) ); points->variables["basis2"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis2 ) ); points->variables["basis3"] = PrimitiveVariable( PrimitiveVariable::Vertex, new V3fVectorData( basis3 ) ); params.hasAnimatedTopology = false; params.hasAnimatedPrimVars = true; params.animatedPrimVars.clear(); params.animatedPrimVars.push_back( "P" ); params.animatedPrimVars.push_back( "basis1" ); params.animatedPrimVars.push_back( "basis2" ); params.animatedPrimVars.push_back( "basis3" ); object = points; } else { object = scene->readObject( time ); params.hasAnimatedTopology = scene->hasAttribute( SceneCache::animatedObjectTopologyAttribute ); params.hasAnimatedPrimVars = scene->hasAttribute( SceneCache::animatedObjectPrimVarsAttribute ); if ( params.hasAnimatedPrimVars ) { const ConstObjectPtr animatedPrimVarObj = scene->readAttribute( SceneCache::animatedObjectPrimVarsAttribute, 0 ); const InternedStringVectorData *animatedPrimVarData = IECore::runTimeCast<const InternedStringVectorData>( animatedPrimVarObj.get() ); if ( animatedPrimVarData ) { const std::vector<InternedString> &values = animatedPrimVarData->readable(); params.animatedPrimVars.clear(); params.animatedPrimVars.resize( values.size() ); std::copy( values.begin(), values.end(), params.animatedPrimVars.begin() ); } } } // modify the object if necessary object = modifyObject( object.get(), params ); // transform the object unless its an identity if ( currentTransform != Imath::M44d() ) { object = transformObject( object.get(), currentTransform, params ); } // convert the object to Houdini if ( !convertObject( object.get(), name, scene, params ) ) { std::string fullName; SceneInterface::Path path; scene->path( path ); SceneInterface::pathToString( path, fullName ); addWarning( SOP_MESSAGE, ( "Could not convert " + fullName + " to Houdini" ).c_str() ); } } if ( evalInt( pObjectOnly.getToken(), 0, 0 ) ) { return; } SceneInterface::NameList children; scene->childNames( children ); std::sort( children.begin(), children.end(), InternedStringSort() ); for ( SceneInterface::NameList::const_iterator it=children.begin(); it != children.end(); ++it ) { ConstSceneInterfacePtr child = scene->child( *it ); if ( tagged( child.get(), params.tagFilter ) ) { loadObjects( child.get(), child->readTransformAsMatrix( time ) * transform, time, space, params, rootSize ); } } }
static void loadSetsWalk( const SceneInterface *s, const vector<InternedString> &tags, const vector<PathMatcher *> &sets, const vector<InternedString> &path ) { // For each tag we wish to load, we need to determine if it exists at the current // location. The natural way to do this would be to call s->hasTag( tag ), but that // actually has pretty poor performance when calling hasTag() for many tags. So // we load all the local tags with readTags(), and then for each of them test to see // if they exist in the list of tags we wish to load. We test the local tags against // the tags because we're in control of the tags and can sort them beforehand for faster // searching, whereas the localTags just come as-is. Using binary search over linear // search isn't actually that big a win for a typical number of tags, simply because // InternedString equality tests are so quick, but there's a very slight benefit, which // should be more apparent should anyone create a very large number of tags at some point. vector<InternedString> sceneTags; s->readTags( sceneTags, SceneInterface::LocalTag ); for( vector<InternedString>::const_iterator it = sceneTags.begin(), eIt = sceneTags.end(); it != eIt; ++it ) { vector<InternedString>::const_iterator t = lower_bound( tags.begin(), tags.end(), *it ); if( t != tags.end() && *t == *it ) { /// \todo addPath() is doing a search to find the right node to insert at. /// If nodes were exposed by the PathMatcher, we could provide the right /// node to insert at by tracking it as we recurse the hierarchy. sets[t - tags.begin()]->addPath( path ); } } // Figure out if we need to recurse by querying descendant tags to see if they include // anything we're interested in. sceneTags.clear(); s->readTags( sceneTags, SceneInterface::DescendantTag ); bool recurse = false; for( vector<InternedString>::const_iterator it = sceneTags.begin(), eIt = sceneTags.end(); it != eIt; ++it ) { vector<InternedString>::const_iterator t = lower_bound( tags.begin(), tags.end(), *it ); if( t != tags.end() && *t == *it ) { recurse = true; break; } } if( !recurse ) { return; } // Recurse to the children. SceneInterface::NameList childNames; s->childNames( childNames ); vector<InternedString> childPath( path ); childPath.push_back( InternedString() ); // room for the child name for( SceneInterface::NameList::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it ) { ConstSceneInterfacePtr child = s->child( *it ); childPath[path.size()] = *it; loadSetsWalk( child.get(), tags, sets, childPath ); } }
bool SOP_SceneCacheSource::convertObject( const IECore::Object *object, const std::string &name, const SceneInterface *scene, Parameters ¶ms ) { ToHoudiniGeometryConverterPtr converter = nullptr; if ( params.geometryType == Cortex ) { converter = new ToHoudiniCortexObjectConverter( object ); } else { const VisibleRenderable *renderable = IECore::runTimeCast<const VisibleRenderable>( object ); if ( !renderable ) { return false; } converter = ToHoudiniGeometryConverter::create( renderable ); } if ( !converter ) { return false; } // we need to set the name regardless of whether // we're reusing prims or doing the full conversion // because this parameter can have an affect in // transferAttribs() as well as convert() converter->nameParameter()->setTypedValue( name ); // check the primitve range map to see if this shape exists already std::map<std::string, GA_Range>::iterator rIt = params.namedRanges.find( name ); if ( rIt != params.namedRanges.end() && !rIt->second.isEmpty() ) { GA_Range primRange = rIt->second; const Primitive *primitive = IECore::runTimeCast<const Primitive>( object ); if ( primitive && !params.hasAnimatedTopology && params.hasAnimatedPrimVars ) { // this means constant topology and primitive variables, even though multiple samples were written if ( params.animatedPrimVars.empty() ) { return true; } GA_Range pointRange( *gdp, primRange, GA_ATTRIB_POINT, GA_Range::primitiveref(), false ); // update the animated primitive variables only std::string animatedPrimVarStr = ""; for ( std::vector<InternedString>::const_iterator it = params.animatedPrimVars.begin(); it != params.animatedPrimVars.end(); ++it ) { animatedPrimVarStr += it->string() + " "; } converter->attributeFilterParameter()->setTypedValue( animatedPrimVarStr ); try { converter->transferAttribs( gdp, pointRange, primRange ); return true; } catch ( std::exception &e ) { addWarning( SOP_MESSAGE, e.what() ); return false; } catch ( ... ) { addWarning( SOP_MESSAGE, "Attribute transfer failed for unknown reasons" ); return false; } } else { // topology is changing, so destroy the exisiting primitives gdp->destroyPrimitives( primRange, true ); } } // fallback to full conversion converter->attributeFilterParameter()->setTypedValue( params.attributeFilter ); try { GA_Offset firstNewPrim = gdp->getPrimitiveMap().lastOffset() + 1; bool status = converter->convert( myGdpHandle ); // adds the full path in addition to the relative name const GA_IndexMap &primMap = gdp->getPrimitiveMap(); GA_Range newPrims( primMap, firstNewPrim, primMap.lastOffset() + 1 ); if ( params.fullPathName != "" ) { if ( newPrims.isValid() ) { std::string fullName; SceneInterface::Path path; scene->path( path ); SceneInterface::pathToString( path, fullName ); GA_RWAttributeRef pathAttribRef = ToHoudiniStringVectorAttribConverter::convertString( params.fullPathName, fullName, gdp, newPrims ); status = status && pathAttribRef.isValid(); } } if ( params.tagGroups ) { static UT_StringMMPattern convertTagFilter; if( convertTagFilter.isEmpty() ) { convertTagFilter.compile( "ObjectType:*" ); } SceneInterface::NameList tags; scene->readTags( tags, IECoreScene::SceneInterface::LocalTag ); for ( SceneInterface::NameList::const_iterator it=tags.begin(); it != tags.end(); ++it ) { UT_String tag( *it ); // skip this tag because it's used behind the scenes if ( tag.multiMatch( convertTagFilter ) ) { continue; } // replace this special character found in SCC tags that will prevent the group from being created tag.substitute(":", "_"); tag.prepend("ieTag_"); GA_PrimitiveGroup *group = gdp->findPrimitiveGroup(tag); if ( !group ) { group = gdp->newPrimitiveGroup(tag); } group->addRange(newPrims); } } return status; } catch ( std::exception &e ) { addWarning( SOP_MESSAGE, e.what() ); return false; } catch ( ... ) { addWarning( SOP_MESSAGE, "Conversion failed for unknown reasons" ); return false; } }