void ToHoudiniGeometryConverter::transferAttribValues( const Primitive *primitive, GU_Detail *geo, const GA_Range &points, const GA_Range &prims, PrimitiveVariable::Interpolation vertexInterpolation, PrimitiveVariable::Interpolation primitiveInterpolation, PrimitiveVariable::Interpolation pointInterpolation, PrimitiveVariable::Interpolation detailInterpolation ) const { GA_OffsetList offsets; if ( prims.isValid() ) { const GA_PrimitiveList &primitives = geo->getPrimitiveList(); for ( GA_Iterator it=prims.begin(); !it.atEnd(); ++it ) { const GA_Primitive *prim = primitives.get( it.getOffset() ); size_t numPrimVerts = prim->getVertexCount(); for ( size_t v=0; v < numPrimVerts; v++ ) { if ( prim->getTypeId() == GEO_PRIMPOLY ) { offsets.append( prim->getVertexOffset( numPrimVerts - 1 - v ) ); } else { offsets.append( prim->getVertexOffset( v ) ); } } } } GA_Range vertRange( geo->getVertexMap(), offsets ); UT_String filter( attributeFilterParameter()->getTypedValue() ); // match all the string variables to each associated indices variable /// \todo: replace all this logic with IECore::IndexedData once it exists... PrimitiveVariableMap stringsToIndices; for ( PrimitiveVariableMap::const_iterator it=primitive->variables.begin() ; it != primitive->variables.end(); it++ ) { if ( !primitive->isPrimitiveVariableValid( it->second ) ) { IECore::msg( IECore::MessageHandler::Warning, "ToHoudiniGeometryConverter", "PrimitiveVariable " + it->first + " is invalid. Ignoring." ); filter += UT_String( " ^" + it->first ); continue; } ToHoudiniAttribConverterPtr converter = ToHoudiniAttribConverter::create( it->second.data.get() ); if ( !converter ) { continue; } if ( it->second.data->isInstanceOf( StringVectorDataTypeId ) ) { std::string indicesVariableName = it->first + "Indices"; PrimitiveVariableMap::const_iterator indices = primitive->variables.find( indicesVariableName ); if ( indices != primitive->variables.end() && indices->second.data->isInstanceOf( IntVectorDataTypeId ) && primitive->isPrimitiveVariableValid( indices->second ) ) { stringsToIndices[it->first] = indices->second; filter += UT_String( " ^" + indicesVariableName ); } } } bool convertStandardAttributes = m_convertStandardAttributesParameter->getTypedValue(); if ( convertStandardAttributes && UT_String( "s" ).multiMatch( filter ) && UT_String( "t" ).multiMatch( filter ) ) { // convert s and t to uv PrimitiveVariableMap::const_iterator sPrimVar = primitive->variables.find( "s" ); PrimitiveVariableMap::const_iterator tPrimVar = primitive->variables.find( "t" ); if ( sPrimVar != primitive->variables.end() && tPrimVar != primitive->variables.end() ) { if ( sPrimVar->second.interpolation == tPrimVar->second.interpolation ) { const FloatVectorData *sData = runTimeCast<const FloatVectorData>( sPrimVar->second.data.get() ); const FloatVectorData *tData = runTimeCast<const FloatVectorData>( tPrimVar->second.data.get() ); if ( sData && tData ) { const std::vector<float> &s = sData->readable(); const std::vector<float> &t = tData->readable(); std::vector<Imath::V3f> uvw; uvw.reserve( s.size() ); for ( size_t i=0; i < s.size(); ++i ) { uvw.push_back( Imath::V3f( s[i], 1 - t[i], 0 ) ); } GA_Range range = vertRange; if ( sPrimVar->second.interpolation == pointInterpolation ) { range = points; } ToHoudiniAttribConverterPtr converter = ToHoudiniAttribConverter::create( new V3fVectorData( uvw ) ); converter->convert( "uv", geo, range ); filter += " ^s ^t"; } } } } UT_StringMMPattern attribFilter; attribFilter.compile( filter ); // add the primitive variables to the various GEO_AttribDicts based on interpolation type for ( PrimitiveVariableMap::const_iterator it=primitive->variables.begin() ; it != primitive->variables.end(); it++ ) { UT_String varName( it->first ); if ( !varName.multiMatch( attribFilter ) ) { continue; } PrimitiveVariable primVar = processPrimitiveVariable( primitive, it->second ); ToHoudiniAttribConverterPtr converter = ToHoudiniAttribConverter::create( primVar.data.get() ); if ( !converter ) { continue; } PrimitiveVariable::Interpolation interpolation = primVar.interpolation; if ( converter->isInstanceOf( (IECore::TypeId)ToHoudiniStringVectorAttribConverterTypeId ) ) { PrimitiveVariableMap::const_iterator indices = stringsToIndices.find( it->first ); if ( indices != stringsToIndices.end() ) { ToHoudiniStringVectorAttribConverter *stringVectorConverter = IECore::runTimeCast<ToHoudiniStringVectorAttribConverter>( converter.get() ); PrimitiveVariable indicesPrimVar = processPrimitiveVariable( primitive, indices->second ); stringVectorConverter->indicesParameter()->setValidatedValue( indicesPrimVar.data ); interpolation = indices->second.interpolation; } } const std::string name = ( convertStandardAttributes ) ? processPrimitiveVariableName( it->first ) : it->first; if ( interpolation == detailInterpolation ) { // add detail attribs try { converter->convert( name, geo ); } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Detail Attrib: " + e.what() ); } } else if ( interpolation == pointInterpolation ) { // add point attribs if ( name == "P" ) { // special case for P transferP( runTimeCast<const V3fVectorData>( primVar.data.get() ), geo, points ); } else { try { GA_RWAttributeRef attrRef = converter->convert( name, geo, points ); // mark rest as non-transforming so it doesn't get manipulated once inside Houdini if ( name == "rest" || name == "Pref" ) { attrRef.getAttribute()->setNonTransforming( true ); } } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Point Attrib: " + e.what() ); } } } else if ( interpolation == primitiveInterpolation ) { // add primitive attribs try { converter->convert( name, geo, prims ); } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Primitive Attrib: " + e.what() ); } } else if ( interpolation == vertexInterpolation ) { // add vertex attribs try { converter->convert( name, geo, vertRange ); } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Vertex Attrib: " + e.what() ); } } } // backwards compatibility with older data const StringData *nameData = primitive->blindData()->member<StringData>( "name" ); if ( nameData && prims.isValid() ) { ToHoudiniStringVectorAttribConverter::convertString( "name", nameData->readable(), geo, prims ); } }
void ToHoudiniGeometryConverter::transferAttribValues( const Primitive *primitive, GU_Detail *geo, const GA_Range &points, const GA_Range &prims, PrimitiveVariable::Interpolation vertexInterpolation, PrimitiveVariable::Interpolation primitiveInterpolation, PrimitiveVariable::Interpolation pointInterpolation, PrimitiveVariable::Interpolation detailInterpolation ) const { GA_OffsetList offsets; if ( prims.isValid() ) { const GA_PrimitiveList &primitives = geo->getPrimitiveList(); for ( GA_Iterator it=prims.begin(); !it.atEnd(); ++it ) { const GA_Primitive *prim = primitives.get( it.getOffset() ); size_t numPrimVerts = prim->getVertexCount(); for ( size_t v=0; v < numPrimVerts; v++ ) { if ( prim->getTypeId() == GEO_PRIMPOLY ) { offsets.append( prim->getVertexOffset( numPrimVerts - 1 - v ) ); } else { offsets.append( prim->getVertexOffset( v ) ); } } } } GA_Range vertRange( geo->getVertexMap(), offsets ); UT_String filter( attributeFilterParameter()->getTypedValue() ); bool convertStandardAttributes = m_convertStandardAttributesParameter->getTypedValue(); // process all primvars with UV interpretation for ( const auto &it : primitive->variables) { if ( !UT_String( it.first ).multiMatch( filter ) ) { continue; } if (const V2fVectorData *uvData = runTimeCast<const V2fVectorData> ( it.second.data.get() ) ) { if ( uvData->getInterpretation() != GeometricData::UV ) { continue; } PrimitiveVariable::IndexedView<Imath::V2f> uvIndexedView ( it.second ); // Houdini prefers a V3f uvw rather than V2f uv, // though they advise setting the 3rd component to 0. std::vector<Imath::V3f> uvw; uvw.reserve( uvIndexedView.size() ); for ( size_t i=0; i < uvIndexedView.size(); ++i ) { uvw.emplace_back( uvIndexedView[i][0], uvIndexedView[i][1], 0 ); } GA_Range range = vertRange; if ( it.second.interpolation == pointInterpolation ) { range = points; } V3fVectorData::Ptr uvwData = new V3fVectorData( uvw ); uvwData->setInterpretation( GeometricData::UV ); ToHoudiniAttribConverterPtr converter = ToHoudiniAttribConverter::create( uvwData.get() ); converter->convert( it.first, geo, range ); filter += " ^" + it.first; } } UT_StringMMPattern attribFilter; attribFilter.compile( filter ); // add the primitive variables to the various GEO_AttribDicts based on interpolation type for ( PrimitiveVariableMap::const_iterator it=primitive->variables.begin() ; it != primitive->variables.end(); it++ ) { if( !primitive->isPrimitiveVariableValid( it->second ) ) { IECore::msg( IECore::MessageHandler::Warning, "ToHoudiniGeometryConverter", "PrimitiveVariable " + it->first + " is invalid. Ignoring." ); continue; } UT_String varName( it->first ); if ( !varName.multiMatch( attribFilter ) ) { continue; } PrimitiveVariable primVar = processPrimitiveVariable( primitive, it->second ); DataPtr data = nullptr; ToHoudiniAttribConverterPtr converter = nullptr; if( primVar.indices && primVar.data->typeId() == StringVectorDataTypeId ) { // we want to process the indexed strings rather than the expanded strings converter = ToHoudiniAttribConverter::create( primVar.data.get() ); if( ToHoudiniStringVectorAttribConverter *stringVectorConverter = IECore::runTimeCast<ToHoudiniStringVectorAttribConverter>( converter.get() ) ) { stringVectorConverter->indicesParameter()->setValidatedValue( primVar.indices.get() ); } } else { // all other primitive variables must be expanded data = primVar.expandedData(); converter = ToHoudiniAttribConverter::create( data.get() ); } if ( !converter ) { continue; } const std::string name = ( convertStandardAttributes ) ? processPrimitiveVariableName( it->first ) : it->first; if ( primVar.interpolation == detailInterpolation ) { // add detail attribs try { converter->convert( name, geo ); } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Detail Attrib: " + e.what() ); } } else if ( primVar.interpolation == pointInterpolation ) { #if UT_MAJOR_VERSION_INT < 15 // add point attribs if ( name == "P" ) { // special case for P transferP( runTimeCast<const V3fVectorData>( primVar.data.get() ), geo, points ); } else #endif { try { GA_RWAttributeRef attrRef = converter->convert( name, geo, points ); // mark rest as non-transforming so it doesn't get manipulated once inside Houdini if ( name == "rest" || name == "Pref" ) { #if UT_MAJOR_VERSION_INT >= 15 attrRef.setTypeInfo( GA_TYPE_VOID ); #else attrRef.getAttribute()->setNonTransforming( true ); #endif } } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Point Attrib: " + e.what() ); } } } else if ( primVar.interpolation == primitiveInterpolation ) { // add primitive attribs try { converter->convert( name, geo, prims ); } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Primitive Attrib: " + e.what() ); } } else if ( primVar.interpolation == vertexInterpolation ) { // add vertex attribs try { converter->convert( name, geo, vertRange ); } catch ( std::exception &e ) { throw IECore::Exception( "PrimitiveVariable \"" + it->first + "\" could not be converted as a Vertex Attrib: " + e.what() ); } } } // backwards compatibility with older data const StringData *nameData = primitive->blindData()->member<StringData>( "name" ); if ( nameData && prims.isValid() ) { ToHoudiniStringVectorAttribConverter::convertString( "name", nameData->readable(), geo, prims ); } }