PointsPrimitivePtr mergePoints( const std::vector<const PointsPrimitive *> &pointsPrimitives ) { size_t totalPointCount = 0; typedef std::map<std::string, IECore::TypeId> FoundPrimvars; FoundPrimvars foundPrimvars; PrimitiveVariableMap constantPrimVars; std::vector<PointsPrimitivePtr> validatedPointsPrimitives( pointsPrimitives.size() ); // find out which primvars can be merged for( size_t i = 0; i < pointsPrimitives.size(); ++i ) { PointsPrimitivePtr pointsPrimitive = validatedPointsPrimitives[i] = pointsPrimitives[i]->copy(); totalPointCount += pointsPrimitive->getNumPoints(); PrimitiveVariableMap &variables = pointsPrimitive->variables; for( PrimitiveVariableMap::iterator it = variables.begin(); it != variables.end(); ++it ) { DataPtr data = it->second.data; const IECore::TypeId typeId = data->typeId(); PrimitiveVariable::Interpolation interpolation = it->second.interpolation; const std::string &name = it->first; bool bExistingConstant = constantPrimVars.find( name ) != constantPrimVars.end(); FoundPrimvars::const_iterator fIt = foundPrimvars.find( name ); bool bExistingVertex = fIt != foundPrimvars.end(); if( interpolation == PrimitiveVariable::Constant ) { if( bExistingVertex ) { std::string msg = boost::str( boost::format( "PointsAlgo::mergePoints mismatching primvar %s" ) % name ); throw InvalidArgumentException( msg ); } if( !bExistingConstant ) { constantPrimVars[name] = it->second; } continue; } if( interpolation == PrimitiveVariable::Vertex ) { PrimitiveVariableMap::const_iterator constantPrimVarIt = constantPrimVars.find( name ); if( constantPrimVarIt != constantPrimVars.end() ) { std::string msg = boost::str( boost::format( "PointsAlgo::mergePoints mismatching primvar %s" ) % name ); throw InvalidArgumentException( msg ); } if( !bExistingVertex ) { foundPrimvars[name] = typeId; } else { if( fIt->second != typeId ) { DataCastOpPtr castOp = new DataCastOp(); castOp->objectParameter()->setValue( data ); castOp->targetTypeParameter()->setNumericValue( fIt->second ); try { it->second.data = runTimeCast<Data>( castOp->operate() ); } catch( const IECore::Exception &e ) { std::string msg = boost::str( boost::format( "PointsAlgo::mergePoints unable to cast primvar %s (%s) " ) % name % e.what() ); throw InvalidArgumentException( msg ); } } } } } } // allocate the new points primitive and copy the primvars PointsPrimitivePtr newPoints = new PointsPrimitive( totalPointCount ); // copy constant primvars for( PrimitiveVariableMap::const_iterator it = constantPrimVars.begin(); it != constantPrimVars.end(); ++it ) { newPoints->variables[it->first] = it->second; } // merge vertex primvars for( FoundPrimvars::const_iterator it = foundPrimvars.begin(); it != foundPrimvars.end(); ++it ) { DataPtr mergedData = mergePrimVars( validatedPointsPrimitives, it->first, totalPointCount ); newPoints->variables[it->first] = PrimitiveVariable( PrimitiveVariable::Vertex, mergedData ); } return newPoints; }
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 ); } }