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() ); } }
GA_Detail::IOStatus GEO_CobIOTranslator::fileLoad( GEO_Detail *geo, UT_IStream &is, int ate_magic ) { ((UT_IFStream&)is).close(); ConstVisibleRenderablePtr renderable = 0; try { ReaderPtr reader = Reader::create( is.getLabel() ); if ( reader->isInstanceOf( ParticleReaderTypeId ) ) { reader->parameters()->parameter<IntParameter>( "realType" )->setNumericValue( ParticleReader::Float ); } renderable = runTimeCast<VisibleRenderable>( reader->read() ); } catch ( IECore::Exception e ) { return false; } if ( !renderable ) { return false; } ToHoudiniGeometryConverterPtr converter = ToHoudiniGeometryConverter::create( renderable ); if ( !converter ) { return false; } GU_DetailHandle handle; handle.allocateAndSet( (GU_Detail*)geo, false ); return converter->convert( handle ); }
GA_Detail::IOStatus GEO_CobIOTranslator::fileLoad( GEO_Detail *geo, UT_IStream &is, int ate_magic ) { ((UT_IFStream&)is).close(); ConstObjectPtr object = 0; try { ReaderPtr reader = Reader::create( is.getLabel() ); if ( !reader ) { return false; } object = reader->read(); } catch ( IECore::Exception e ) { return false; } if ( !object ) { return false; } ToHoudiniGeometryConverterPtr converter = ToHoudiniGeometryConverter::create( object.get() ); if ( !converter ) { return false; } GU_DetailHandle handle; handle.allocateAndSet( (GU_Detail*)geo, false ); return converter->convert( handle ); }
void IECoreMantra::ProceduralPrimitive::addVisibleRenderable( VisibleRenderablePtr renderable ) { ToHoudiniGeometryConverterPtr converter = ToHoudiniGeometryConverter::create( renderable ); if( !converter ) { msg( Msg::Warning, "ProceduralPrimitive::addVisibleRenderable", "converter could not be found" ); return; } GU_Detail *gdp = allocateGeometry(); GU_DetailHandle handle; handle.allocateAndSet( (GU_Detail*)gdp, false ); bool converted = converter->convert( handle ); if ( !converted ) { msg( Msg::Warning, "ProceduralPrimitive::addVisibleRenderable", "converter failed" ); return; } /// \todo ToHoudiniGeometryConverter does not create a Houdini style uv attribute. /// We make one from s and t. This code should probably live in a converter or in an Op that /// remaps IECore conventions to common Houdini ones. MeshPrimitivePtr mesh = runTimeCast<MeshPrimitive> (renderable); if ( mesh ) { gdp->addTextureAttribute( GA_ATTRIB_VERTEX ); GEO_AttributeHandle auv = gdp->getAttribute( GA_ATTRIB_VERTEX, "uv" ); GEO_AttributeHandle as = gdp->getAttribute( GA_ATTRIB_VERTEX, "s" ); GEO_AttributeHandle at = gdp->getAttribute( GA_ATTRIB_VERTEX, "t" ); if ( auv.isAttributeValid() && as.isAttributeValid() && at.isAttributeValid() ) { GA_GBPrimitiveIterator it( *gdp ); GA_Primitive *p = it.getPrimitive(); while ( p ) { for (int i = 0; i < p->getVertexCount(); ++i) { GA_Offset v = p->getVertexOffset(i); as.setVertex(v); at.setVertex(v); auv.setVertex(v); auv.setF( as.getF(0), 0 ); auv.setF( ((at.getF(0) * -1.0f) + 1.0f), 1 ); // wat, t arrives upside down for some reason. auv.setF( 0.0f, 2 ); } ++it; p = it.getPrimitive(); } } } if ( m_renderer->m_motionType == RendererImplementation::Geometry ) { msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:Geometry" ); if ( !m_renderer->m_motionTimes.empty() ) { if ( (size_t)m_renderer->m_motionSize == m_renderer->m_motionTimes.size() ) { openGeometryObject(); } addGeometry(gdp, m_renderer->m_motionTimes.front()); m_renderer->m_motionTimes.pop_front(); if ( m_renderer->m_motionTimes.empty() ) { applySettings(); closeObject(); } } } else if ( m_renderer->m_motionType == RendererImplementation::ConcatTransform || m_renderer->m_motionType == RendererImplementation::SetTransform ) { // It isn't clear that this will give correct results. // ConcatTransform may need to interpolate transform snapshots. msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:Transform" ); openGeometryObject(); addGeometry(gdp, 0.0f); while ( !m_renderer->m_motionTimes.empty() ) { setPreTransform( convert< UT_Matrix4T<float> >(m_renderer->m_motionTransforms.front()), m_renderer->m_motionTimes.front() ); m_renderer->m_motionTimes.pop_front(); m_renderer->m_motionTransforms.pop_front(); } applySettings(); closeObject(); m_renderer->m_motionType = RendererImplementation::Unknown; } else if ( m_renderer->m_motionType == RendererImplementation::Velocity ) { msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:Velocity" ); openGeometryObject(); addGeometry(gdp, 0.0f); addVelocityBlurGeometry(gdp, m_preBlur, m_postBlur); applySettings(); closeObject(); m_renderer->m_motionType = RendererImplementation::Unknown; } else { msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:None" ); openGeometryObject(); addGeometry( gdp, 0.0f ); setPreTransform( convert< UT_Matrix4T<float> >(m_renderer->m_transformStack.top()), 0.0f); applySettings(); closeObject(); } }
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; } }