GA_RWHandleV3 SHelper::addFloatVectorDetailAttr(GU_Detail* gdp, const char* name, float* def) { GA_RWAttributeRef attr; if(def) attr = gdp->addFloatTuple(GA_ATTRIB_GLOBAL, name, 3, GA_Defaults(def, 3)); else attr = gdp->addFloatTuple(GA_ATTRIB_GLOBAL, name, 3); attr.setTypeInfo(GA_TYPE_VECTOR); return GA_RWHandleV3( attr.getAttribute() ); }
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 ); } }