bool ToHoudiniPolygonsConverter::doConversion( const VisibleRenderable *renderable, GU_Detail *geo ) const { const MeshPrimitive *mesh = static_cast<const MeshPrimitive *>( renderable ); if ( !mesh ) { return false; } GA_Range newPoints = appendPoints( geo, mesh->variableSize( PrimitiveVariable::Vertex ) ); if ( !newPoints.isValid() || newPoints.empty() ) { return false; } GA_OffsetList pointOffsets; pointOffsets.reserve( newPoints.getEntries() ); for ( GA_Iterator it=newPoints.begin(); !it.atEnd(); ++it ) { pointOffsets.append( it.getOffset() ); } const std::vector<int> &vertexIds = mesh->vertexIds()->readable(); const std::vector<int> &verticesPerFace = mesh->verticesPerFace()->readable(); GA_OffsetList offsets; offsets.reserve( verticesPerFace.size() ); size_t vertCount = 0; size_t numPrims = geo->getNumPrimitives(); for ( size_t f=0; f < verticesPerFace.size(); f++ ) { GU_PrimPoly *poly = GU_PrimPoly::build( geo, 0, GU_POLY_CLOSED, 0 ); offsets.append( geo->primitiveOffset( numPrims + f ) ); for ( size_t v=0; v < (size_t)verticesPerFace[f]; v++ ) { poly->appendVertex( pointOffsets.get( vertexIds[ vertCount + verticesPerFace[f] - 1 - v ] ) ); } vertCount += verticesPerFace[f]; } GA_Range newPrims( geo->getPrimitiveMap(), offsets ); transferAttribs( geo, newPoints, newPrims ); // add the interpolation type if ( newPrims.isValid() ) { std::string interpolation = ( mesh->interpolation() == "catmullClark" ) ? "subdiv" : "poly"; StringVectorDataPtr interpolationVectorData = new StringVectorData(); interpolationVectorData->writable().push_back( interpolation ); std::vector<int> indexValues( newPrims.getEntries(), 0 ); IntVectorDataPtr indexData = new IntVectorData( indexValues ); ToHoudiniStringVectorAttribConverterPtr converter = new ToHoudiniStringVectorAttribConverter( interpolationVectorData ); converter->indicesParameter()->setValidatedValue( indexData ); converter->convert( "ieMeshInterpolation", geo, newPrims ); } return true; }
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 ); 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 ); const FloatVectorData *tData = runTimeCast<const FloatVectorData>( tPrimVar->second.data ); 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 ); 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 ); 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 converter->convert( name, geo ); } else if ( interpolation == pointInterpolation ) { // add point attribs if ( name == "P" ) { // special case for P transferP( runTimeCast<const V3fVectorData>( primVar.data ), geo, points ); } else { converter->convert( name, geo, points ); } } else if ( interpolation == primitiveInterpolation ) { // add primitive attribs converter->convert( name, geo, prims ); } else if ( interpolation == vertexInterpolation ) { // add vertex attribs converter->convert( name, geo, vertRange ); } } // add the name attribute based on blindData const StringData *nameData = primitive->blindData()->member<StringData>( "name" ); if ( nameData ) { if ( prims.isValid() ) { StringVectorDataPtr nameVectorData = new StringVectorData(); nameVectorData->writable().push_back( nameData->readable() ); std::vector<int> indexValues( prims.getEntries(), 0 ); IntVectorDataPtr indexData = new IntVectorData( indexValues ); ToHoudiniStringVectorAttribConverterPtr converter = new ToHoudiniStringVectorAttribConverter( nameVectorData ); converter->indicesParameter()->setValidatedValue( indexData ); converter->convert( "name", geo, prims ); } } }