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; }
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 ); return true; }
Geo2Emp::ErrorCode Geo2Emp::loadMeshShape( const Nb::Body* pBody ) { if (!_gdp) { //If we don't have a GDP for writing data into Houdini, return error. return EC_NULL_WRITE_GDP; } LogInfo() << "=============== Loading mesh shape ===============" << std::endl; const Nb::TriangleShape* pShape; pShape = pBody->queryConstTriangleShape(); if (!pShape) { //NULL mesh shape, so return right now. return EC_NO_TRIANGLE_SHAPE; } //Get access to shapes we need to loading a mesh (point and triangle) const Nb::TriangleShape& triShape = pBody->constTriangleShape(); const Nb::PointShape& ptShape = pBody->constPointShape(); //Retrieve the number of points and channels int64_t size = ptShape.size(); int channelCount = ptShape.channelCount(); //Attribute Lookup Tables std::vector< GEO_AttributeHandle > attribLut; std::vector<GeoAttributeInfo> attribInfo; //houdini types for the naiad channels. GeoAttributeInfo* pInfo; GEO_AttributeHandle attr; std::string attrName; float zero3f[3] = {0,0,0}; float zero1f = 0; int zero3i[3] = {0,0,0}; int zero1i = 0; const void* data; attribLut.clear(); attribInfo.clear(); attribLut.resize( channelCount ); attribInfo.resize( channelCount ); //Prepare for a blind copy of Naiad channels to Houdini attributes. //Iterate over the channels and create the corresponding attributes in the GDP for (int i = 0; i < channelCount; i++) { //std::cout << "channel: " << i << std::endl; const Nb::ChannelCowPtr& chan = ptShape.channel(i); if ( _empAttribMangle.find( chan->name() ) != _empAttribMangle.end() ) attrName = _empAttribMangle[ chan->name() ]; else attrName = chan->name(); LogDebug() << "Processing EMP Channel: " << chan->name() << "; mangled: " << attrName << std::endl; //Determine the attribute type, and store it pInfo = &(attribInfo[ i ]); pInfo->supported = false; pInfo->size = 0; pInfo->use64 = false; switch ( chan->type() ) { case Nb::ValueBase::IntType: LogDebug() << "IntType " << std::endl; pInfo->type = GB_ATTRIB_INT; pInfo->entries = 1; pInfo->size = sizeof(int); pInfo->supported = true; data = &zero1i; break; case Nb::ValueBase::Int64Type: //NOTE: This might need to be handled differently ... just remember this 'hack' pInfo->type = GB_ATTRIB_INT; pInfo->entries = 1; pInfo->size = sizeof(int); pInfo->supported = true; data = &zero1i; break; case Nb::ValueBase::FloatType: LogDebug() << "FloatType " << std::endl; pInfo->type = GB_ATTRIB_FLOAT; pInfo->size = sizeof(float); pInfo->entries = 1; pInfo->supported = true; data = &zero1f; break; case Nb::ValueBase::Vec3fType: LogDebug() << "Vec3fType " << std::endl; pInfo->type = GB_ATTRIB_VECTOR; pInfo->size = sizeof(float); pInfo->entries = 3; pInfo->supported = true; data = &zero3f; break; default: pInfo->supported = false; break; } //If the attribute is not supported, then continue with the next one. if (!pInfo->supported) { LogVerbose() << "Unsupported attribute. Skipping:" << attrName << std::endl; continue; } //Check whether the attribute exists or not attr = _gdp->getPointAttribute( attrName.c_str() ); if ( !attr.isAttributeValid() ) { LogDebug() << "Creating attribute in GDP:" << attrName << std::endl; _gdp->addPointAttrib( attrName.c_str(), pInfo->size * pInfo->entries, pInfo->type, data); attr = _gdp->getPointAttribute( attrName.c_str() ); } //Put the attribute handle in a Lut for easy access later (during transfer) attribLut[i] = attr; } //Get index buffer from the triangle shape const Nb::Buffer3i& bufIndex ( triShape.constBuffer3i("index") ); int64_t indexBufSize = bufIndex.size(); //Before we start adding points to the GDP, just record how many points are already there. int initialPointCount = _gdp->points().entries(); GEO_Point *ppt; //Now, copy all the points into the GDP. for (int ptNum = 0; ptNum < ptShape.size(); ptNum ++) { ppt = _gdp->appendPoint(); //Iterate over the channels in the point shape and copy the data for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { pInfo = &(attribInfo[ channelIndex ]); //If the attribute is not supported then skip it if (!pInfo->supported) { continue; } attribLut[ channelIndex ].setElement( ppt ); //Transfer supported attributes (this includes the point Position) switch ( pInfo->type ) { case GB_ATTRIB_INT: { const Nb::Buffer1i& channelData = ptShape.constBuffer1i(channelIndex); //Get the Houdini point attribute using the name list we built earlier. attribLut[channelIndex].setI( channelData(ptNum) ); } break; case GB_ATTRIB_FLOAT: { //TODO: Handle more that 1 entry here, if we ever get something like that ... although I doubt it would happen. const Nb::Buffer1f& channelData( ptShape.constBuffer1f(channelIndex) ); //Get the Houdini point attribute using the name list we built earlier. attribLut[channelIndex].setF( channelData(ptNum) ); } break; case GB_ATTRIB_VECTOR: { const Nb::Buffer3f& channelData = ptShape.constBuffer3f(channelIndex); //Get the Houdini point attribute using the name list we built earlier. attribLut[channelIndex].setV3( UT_Vector3( channelData(ptNum)[0], channelData(ptNum)[1], channelData(ptNum)[2] ) ); } break; default: //not yet implemented. continue; break; } } } //Now that all the points are in the GDP, build the triangles GU_PrimPoly *pPrim; for (int tri = 0; tri < indexBufSize; tri++) { pPrim = GU_PrimPoly::build(_gdp, 3, GU_POLY_CLOSED, 0); //Build a closed poly with 3 points, but don't add them to the GDP. //Set the three vertices of the triangle for (int i = 0; i < 3; i++ ) { pPrim->setVertex(i, _gdp->points()[ initialPointCount + bufIndex(tri)[i] ] ); } } return EC_SUCCESS; }