bool SOP_SceneCacheSource::convertObject( const IECore::Object *object, const std::string &name, const std::string &attributeFilter, GeometryType geometryType, bool hasAnimatedTopology, bool hasAnimatedPrimVars, const std::vector<InternedString> &animatedPrimVars ) { ToHoudiniGeometryConverterPtr converter = 0; if ( 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; } // attempt to optimize the conversion by re-using animated primitive variables const Primitive *primitive = IECore::runTimeCast<const Primitive>( object ); GA_ROAttributeRef nameAttrRef = gdp->findStringTuple( GA_ATTRIB_PRIMITIVE, "name" ); GA_Range primRange = gdp->getRangeByValue( nameAttrRef, name.c_str() ); if ( primitive && !hasAnimatedTopology && hasAnimatedPrimVars && nameAttrRef.isValid() && !primRange.isEmpty() ) { // this means constant topology and primitive variables, even though multiple samples were written if ( animatedPrimVars.empty() ) { return true; } GA_Range pointRange( *gdp, primRange, GA_ATTRIB_POINT, GA_Range::primitiveref(), false ); std::string animatedPrimVarStr = ""; for ( std::vector<InternedString>::const_iterator it = animatedPrimVars.begin(); it != animatedPrimVars.end(); ++it ) { animatedPrimVarStr += it->string() + " "; } converter->attributeFilterParameter()->setTypedValue( animatedPrimVarStr ); converter->transferAttribs( gdp, pointRange, primRange ); return true; } else { gdp->destroyPrimitives( primRange, true ); } // fallback to full conversion converter->nameParameter()->setTypedValue( name ); converter->attributeFilterParameter()->setTypedValue( attributeFilter ); return converter->convert( myGdpHandle ); }
void SOP_CortexConverter::doConvert( const GU_DetailHandle &handle, const std::string &name, ResultType type, const std::string &attributeFilter, bool convertStandardAttributes ) { if ( handle.isNull() ) { addError( SOP_MESSAGE, ( "Could not extract the geometry named " + name ).c_str() ); return; } FromHoudiniGeometryConverterPtr fromConverter = FromHoudiniGeometryConverter::create( handle ); if ( !fromConverter ) { addError( SOP_MESSAGE, ( "Could not convert the geometry named " + name ).c_str() ); return; } IECore::ObjectPtr result = fromConverter->convert(); if ( !result ) { addError( SOP_MESSAGE, ( "Could not find Cortex Object named " + name + " on input geometry" ).c_str() ); return; } if ( IECore::ParameterisedProcedural *procedural = IECore::runTimeCast<IECore::ParameterisedProcedural>( result.get() ) ) { IECore::CapturingRendererPtr renderer = new IECore::CapturingRenderer(); // We are acquiring and releasing the GIL here to ensure that it is released when we render. This has // to be done because a procedural might jump between c++ and python a few times (i.e. if it spawns // subprocedurals that are implemented in python). In a normal call to cookMySop, this wouldn't be an // issue, but if cookMySop was called from HOM, hou.Node.cook appears to be holding onto the GIL. IECorePython::ScopedGILLock gilLock; { IECorePython::ScopedGILRelease gilRelease; { IECore::WorldBlock worldBlock( renderer ); procedural->render( renderer.get() ); } } result = boost::const_pointer_cast<IECore::Object>( IECore::runTimeCast<const IECore::Object>( renderer->world() ) ); } ToHoudiniGeometryConverterPtr converter = ( type == Cortex ) ? new ToHoudiniCortexObjectConverter( result.get() ) : ToHoudiniGeometryConverter::create( result.get() ); converter->nameParameter()->setTypedValue( name ); converter->attributeFilterParameter()->setTypedValue( attributeFilter ); converter->convertStandardAttributesParameter()->setTypedValue( convertStandardAttributes ); if ( !converter->convert( myGdpHandle ) ) { addError( SOP_MESSAGE, ( "Could not convert the Cortex Object named " + name + " to Houdini geometry" ).c_str() ); } }
bool ToHoudiniGroupConverter::doConversion( const VisibleRenderable *renderable, GU_Detail *geo ) const { const Group *group = IECore::runTimeCast<const Group>( renderable ); if ( !group ) { return false; } Imath::M44f transform = ( runTimeCast<const M44fData>( m_transformParameter->getValue() ) )->readable(); const Transform *groupTransform = group->getTransform(); if ( groupTransform ) { transform = transform * groupTransform->transform(); } TransformOpPtr transformOp = new TransformOp(); M44fDataPtr transformData = new M44fData( transform ); transformOp->matrixParameter()->setValue( transformData ); std::string groupName = nameParameter()->getTypedValue(); if ( groupName == "" ) { // backwards compatibility with older data if ( const StringData *groupNameData = group->blindData()->member<StringData>( "name" ) ) { groupName = groupNameData->readable(); } } const std::string &attribFilter = attributeFilterParameter()->getTypedValue(); bool convertStandardAttributes = convertStandardAttributesParameter()->getTypedValue(); size_t i = 0; const Group::ChildContainer &children = group->children(); for ( Group::ChildContainer::const_iterator it=children.begin(); it != children.end(); ++it, ++i ) { ConstVisibleRenderablePtr child = *it; ConstPrimitivePtr primitive = runTimeCast<const Primitive>( child ); if ( primitive ) { transformOp->inputParameter()->setValue( constPointerCast<Primitive>( primitive ) ); child = staticPointerCast<VisibleRenderable>( transformOp->operate() ); } ToHoudiniGeometryConverterPtr converter = ToHoudiniGeometryConverter::create( child ); if ( !converter ) { continue; } std::string name = groupName; if ( const StringData *childNameData = child->blindData()->member<StringData>( "name" ) ) { const std::string &childName = childNameData->readable(); if ( childName != "" ) { if ( groupName != "" ) { name += "/"; } name += childName; } } converter->nameParameter()->setTypedValue( name ); converter->attributeFilterParameter()->setTypedValue( attribFilter ); converter->convertStandardAttributesParameter()->setTypedValue( convertStandardAttributes ); ToHoudiniGroupConverter *groupConverter = runTimeCast<ToHoudiniGroupConverter>( converter ); if ( groupConverter ) { groupConverter->transformParameter()->setValue( transformData ); } GU_DetailHandle handle; handle.allocateAndSet( geo, false ); if ( !converter->convert( handle ) ) { continue; } } return true; }
bool SOP_SceneCacheSource::convertObject( const IECore::Object *object, const std::string &name, const SceneInterface *scene, Parameters ¶ms ) { ToHoudiniGeometryConverterPtr converter = 0; 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 ); if ( params.fullPathName != "" ) { // 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 ( 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(); } } return status; } catch ( std::exception &e ) { addWarning( SOP_MESSAGE, e.what() ); return false; } catch ( ... ) { addWarning( SOP_MESSAGE, "Conversion failed for unknown reasons" ); return false; } }