Esempio n. 1
0
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;
}
Esempio n. 3
0
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;
}