//
// Populate a D3DGeometry object from a Maya mesh
//
bool D3DGeometry::Populate( const MDagPath& dagPath, ID3D11Device* D3D)
{
	HRESULT hr;

	Release();
	MFnMesh mesh( dagPath.node());

	// Figure out texturing
	//
	MString pn = dagPath.fullPathName();
	//printf("Convert shape %s\n", pn.asChar());
	bool haveTexture = false;
	int	numUVsets = mesh.numUVSets();
	MString uvSetName;
	MObjectArray textures;
	if (numUVsets > 0)
	{
		mesh.getCurrentUVSetName( uvSetName );
		// Always send down uvs for now, since we don't dirty the populate
		// based on material texture connection.
		//
		//MStatus status = mesh.getAssociatedUVSetTextures(uvSetName, textures);
		//if (status == MS::kSuccess && textures.length())
		int numCoords = mesh.numUVs( uvSetName ); 
		if (numCoords > 0)
		{
			haveTexture = true;
		}
	}

	bool haveColors = false;
	int	numColors = mesh.numColorSets();
	MString colorSetName;
	if (numColors > 0)
	{
		haveColors = true;
		mesh.getCurrentColorSetName(colorSetName);
	}

	bool useNormals = true;

	// Setup our requirements needs.
	MGeometryRequirements requirements;
	requirements.addPosition();
	if (useNormals)
		requirements.addNormal();
	if (haveTexture)
		requirements.addTexCoord( uvSetName );
	if (haveColors)
		requirements.addColor( colorSetName );

	// Test for tangents and binormals
	bool testBinormal = false;
	if (testBinormal)
		requirements.addBinormal( uvSetName );
	bool testTangent= false;
	if (testTangent)
		requirements.addTangent( uvSetName );

	MGeometry geom = MGeometryManager::getGeometry( dagPath, requirements, NULL );

	unsigned int numPrims = geom.primitiveArrayCount();
	if( numPrims)
	{
		const MGeometryPrimitive prim = geom.primitiveArray(0);

		NumIndices = prim.elementCount();
		if( NumIndices)
		{
			//MGeometryData::ElementType primType = prim.dataType();
			unsigned int *idx = (unsigned int *) prim.data();

			// Get the position data
			const MGeometryData pos = geom.position();
			float * posPtr = (float * )pos.data();
			if( !idx || !posPtr) return false;
			NumVertices = pos.elementCount();

			// Start building our vertex format. We always have position, so
			// start with that and add in all the elements we find along the way
			Stride = sizeof( float) * 3;

			// Get the normals data
			float * normPtr = NULL;
			if( useNormals)
			{
				const MGeometryData norm = geom.normal();				
				normPtr = (float * )norm.data();
				Stride += sizeof( float) * 3;
			}

			// Get the texture coordinate data
			float *uvPtr = NULL;
			if( haveTexture)
			{
				const MGeometryData uvs = geom.texCoord( uvSetName );
				uvPtr = (float *)uvs.data();
				Stride += sizeof( float) * 2;
			}

			// Always using FixedFunctionVertex for now
			Stride = sizeof(FixedFunctionVertex);
			useNormals = true;
			haveTexture = true;

			// Copy our vertex data into the buffer
			//
			int FloatsPerVertex = Stride / sizeof( float);
			float* vertBuffer = new float[ NumVertices * FloatsPerVertex ];
			float* VertexData = vertBuffer;
			int StrideOffset = FloatsPerVertex - 3;
			//MGlobal::displayInfo( MString( "Allocating buffers for ") + NumVertices + MString( " verts and ") + NumIndices + MString( " indices\n"));
			for( unsigned int i = 0; i < NumVertices; i++)
			{
				*VertexData++ = *posPtr++;
				*VertexData++ = *posPtr++;
				*VertexData++ = *posPtr++;
				VertexData += StrideOffset;
			}
			VertexData -= NumVertices * FloatsPerVertex - 3;

			if( normPtr)
			{
				for( unsigned int i = 0; i < NumVertices; i++)
				{
					*VertexData++ = *normPtr++;
					*VertexData++ = *normPtr++;
					*VertexData++ = *normPtr++;
					VertexData += StrideOffset;
				}
				VertexData -= NumVertices * FloatsPerVertex - 3;
			}

			if( uvPtr)
			{
				StrideOffset = FloatsPerVertex - 2;
				for( unsigned int i = 0; i < NumVertices; i++)
				{
					*VertexData++ = *uvPtr++;
					*VertexData++ = 1.0f - *uvPtr++;
					VertexData += StrideOffset;
				}
				VertexData -= NumVertices * FloatsPerVertex - 2;
			}

			// Allocate our vertex buffer
			//
			D3D11_BUFFER_DESC bd;
			ZeroMemory( &bd, sizeof(bd) );
			bd.Usage = D3D11_USAGE_DEFAULT;
			bd.ByteWidth = Stride * NumVertices;
			bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
			bd.CPUAccessFlags = 0;
			D3D11_SUBRESOURCE_DATA InitData;
			ZeroMemory( &InitData, sizeof(InitData) );
			InitData.pSysMem = vertBuffer;
			hr = D3D->CreateBuffer( &bd, &InitData, &VertexBuffer );
			if ( FAILED( hr ) )
			{
				MGlobal::displayWarning( "DX11 renderer : Unable to allocate vertex buffer\n");
				return false;
			}

			delete [] vertBuffer;

			// Allocate our index buffer
			//
			bd.Usage = D3D11_USAGE_DEFAULT;
			bd.ByteWidth = NumIndices * sizeof( DWORD);
			bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
			bd.CPUAccessFlags = 0;
			InitData.pSysMem = idx;
			hr = D3D->CreateBuffer( &bd, &InitData, &IndexBuffer );
			if ( FAILED( hr ) )
			{
				MGlobal::displayWarning( "DX11 renderer : Unable to allocate index buffer\n");
				return false;
			}
		}
	}
	return IndexBuffer && VertexBuffer;
}
void geometryReplicatorGeometryOverride::populateGeometry(
	const MGeometryRequirements& requirements,
	const MRenderItemList& renderItems,
	MGeometry& data)
{
	if (!fPath.isValid())
		return;

	// MGeometryExtractor::MGeometryExtractor.
	// here, fPath is the path of the linked object instead of the plugin node; it
	// is used to determine the right type of the geometry shape, e.g., polygon
	// or NURBS surface.
	// The sharing flag (true here) is just for the polygon shape.
	MStatus status;
	MPolyGeomOptions options = kPolyGeom_Normal;
	if( isBaseMesh() ) options = options|kPolyGeom_BaseMesh;
	MGeometryExtractor extractor(requirements, fPath, options, &status);
	if (MS::kFailure == status)
		return;

	// fill vertex buffer
	const MVertexBufferDescriptorList& descList = requirements.vertexRequirements();
	for (int reqNum = 0; reqNum < descList.length(); ++reqNum)
	{
		MVertexBufferDescriptor desc;
		if (!descList.getDescriptor(reqNum, desc))
		{
			continue;
		}

		switch (desc.semantic())
		{
		case MGeometry::kPosition:
		case MGeometry::kNormal:
		case MGeometry::kTexture:
		case MGeometry::kTangent:
		case MGeometry::kBitangent:
		case MGeometry::kColor:
			{
				MVertexBuffer* vertexBuffer = data.createVertexBuffer(desc);
				if (vertexBuffer) {
					// MGeometryExtractor::vertexCount and MGeometryExtractor::populateVertexBuffer.
					// since the plugin node has the same vertex data as its linked scene object,
					// call vertexCount to allocate vertex buffer of the same size, and then call
					// populateVertexBuffer to copy the data.
					unsigned int vertexCount = extractor.vertexCount();
					float* data = (float*)vertexBuffer->acquire(vertexCount, true /*writeOnly - we don't need the current buffer values*/);
					if (data) {
						status = extractor.populateVertexBuffer(data, vertexCount, desc);
						if (MS::kFailure == status)
							return;
						vertexBuffer->commit(data);
					}
				}
			}
			break;

		default:
			// do nothing for stuff we don't understand
			break;
		}
	}

	// fill index buffer
	for (int i = 0; i < renderItems.length(); ++i)
	{
		const MRenderItem* item = renderItems.itemAt(i);
		if (!item) continue;

		MIndexBuffer* indexBuffer = data.createIndexBuffer(MGeometry::kUnsignedInt32);
		if (!indexBuffer) continue;

		// MGeometryExtractor::primitiveCount and MGeometryExtractor::populateIndexBuffer.
		// since the plugin node has the same index data as its linked scene object,
		// call primitiveCount to allocate index buffer of the same size, and then call
		// populateIndexBuffer to copy the data.
		if (item->primitive() == MGeometry::kTriangles)
		{
			MIndexBufferDescriptor triangleDesc(MIndexBufferDescriptor::kTriangle, MString(), MGeometry::kTriangles, 3);
			unsigned int numTriangles = extractor.primitiveCount(triangleDesc);

			unsigned int* indices = (unsigned int*)indexBuffer->acquire(3 * numTriangles, true /*writeOnly - we don't need the current buffer values*/);
			status = extractor.populateIndexBuffer(indices, numTriangles, triangleDesc);
			if (MS::kFailure == status)
				return;
			indexBuffer->commit(indices);
		}
		else if (item->primitive() == MGeometry::kLines)
		{
			MIndexBufferDescriptor edgeDesc(MIndexBufferDescriptor::kEdgeLine, MString(), MGeometry::kLines, 2);
			unsigned int numEdges = extractor.primitiveCount(edgeDesc);

			unsigned int* indices = (unsigned int*)indexBuffer->acquire(2 * numEdges, true /*writeOnly - we don't need the current buffer values*/);
			status = extractor.populateIndexBuffer(indices, numEdges, edgeDesc);
			if (MS::kFailure == status)
				return;
			indexBuffer->commit(indices);
		}

		item->associateWithIndexBuffer(indexBuffer);
	}
}
Exemple #3
0
//
// Populate a D3DGeometry object from a Maya mesh
//
bool D3DGeometry::Populate( const MDagPath& dagPath, LPDIRECT3DDEVICE9 D3D)
{
	Release();
	MFnMesh mesh( dagPath.node());

	// Figure out texturing
	//
	bool haveTexture = false;
	int	numUVsets = mesh.numUVSets();
	MString uvSetName;
	MObjectArray textures;
	if (numUVsets > 0)
	{
		mesh.getCurrentUVSetName( uvSetName );
		// Always send down uvs for now, since we don't dirty the populate
		// based on material texture connection.
		//
		//MStatus status = mesh.getAssociatedUVSetTextures(uvSetName, textures);
		//if (status == MS::kSuccess && textures.length())
		{
			haveTexture = true;
		}
	}

	bool haveColors = false;
	int	numColors = mesh.numColorSets();
	MString colorSetName;
	if (numColors > 0)
	{
		haveColors = true;
		mesh.getCurrentColorSetName(colorSetName);
	}

	bool useNormals = true;

	// Setup our requirements needs.
	MGeometryRequirements requirements;
	requirements.addPosition();
	if (useNormals)
		requirements.addNormal();
	if (haveTexture)
		requirements.addTexCoord( uvSetName );
	if (haveColors)
		requirements.addColor( colorSetName );

	// Test for tangents and binormals
	bool testBinormal = false;
	if (testBinormal)
		requirements.addBinormal( uvSetName );
	bool testTangent= false;
	if (testTangent)
		requirements.addTangent( uvSetName );

	MGeometry geom = MGeometryManager::getGeometry( dagPath, requirements, NULL );

	unsigned int numPrims = geom.primitiveArrayCount();
	if( numPrims)
	{
		const MGeometryPrimitive prim = geom.primitiveArray(0);

		NumIndices = prim.elementCount();
		if( NumIndices)
		{
			//MGeometryData::ElementType primType = prim.dataType();
			unsigned int *idx = (unsigned int *) prim.data();

			// Get the position data
			const MGeometryData pos = geom.position();
			float * posPtr = (float * )pos.data();
			if( !idx || !posPtr) return false;
			NumVertices = pos.elementCount();

			// Start building our vertex format. We always have position, so
			// start with that and add in all the elements we find along the way
			FVF = D3DFVF_XYZ;
			Stride = sizeof( float) * 3;

			// Get the normals data
			float * normPtr = NULL;
			if( useNormals)
			{
				const MGeometryData norm = geom.normal();				
				normPtr = (float * )norm.data();
				Stride += sizeof( float) * 3;
				FVF |= D3DFVF_NORMAL;
			}

			// Get the texture coordinate data
			float *uvPtr = NULL;
			if( haveTexture)
			{
				const MGeometryData uvs = geom.texCoord( uvSetName );
				uvPtr = (float *)uvs.data();
				Stride += sizeof( float) * 2;
				FVF |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);
			}

			unsigned int numColorComponents = 4;
			float *clrPtr = NULL;
			if (haveColors)
			{
				const MGeometryData clrs = geom.color( colorSetName );
				clrPtr = (float *)clrs.data();
			}
			else if (testBinormal)
			{
				const MGeometryData binorm = geom.binormal( uvSetName );
				clrPtr = (float *)binorm.data();
				numColorComponents = 3;
			}
			else if (testTangent)
			{
				const MGeometryData tang = geom.tangent( uvSetName );
				clrPtr = (float *)tang.data();
				numColorComponents = 3;
			}

			// Allocate our vertex buffer
			//
			if( D3D->CreateVertexBuffer( Stride * NumVertices, D3DUSAGE_WRITEONLY, FVF, 
											D3DPOOL_DEFAULT, &VertexBuffer, NULL) != D3D_OK)
			{
				MGlobal::displayWarning( "Direct3D renderer : Unable to allocate vertex buffer\n");
				return false;
			}

			// Copy our vertex data into the buffer
			//
			float* VertexData = NULL;
			int FloatsPerVertex = Stride / sizeof( float);
			int StrideOffset = FloatsPerVertex - 3;
			//MGlobal::displayInfo( MString( "Allocating buffers for ") + NumVertices + MString( " verts and ") + NumIndices + MString( " indices\n"));
			VertexBuffer->Lock( 0, 0, (void**)&VertexData, D3DLOCK_DISCARD);
			for( unsigned int i = 0; i < NumVertices; i++)
			{
				*VertexData++ = *posPtr++;
				*VertexData++ = *posPtr++;
				*VertexData++ = *posPtr++;
				VertexData += StrideOffset;
			}
			VertexData -= NumVertices * FloatsPerVertex - 3;

			if( normPtr)
			{
				for( unsigned int i = 0; i < NumVertices; i++)
				{
					*VertexData++ = *normPtr++;
					*VertexData++ = *normPtr++;
					*VertexData++ = *normPtr++;
					VertexData += StrideOffset;
				}
				VertexData -= NumVertices * FloatsPerVertex - 3;
			}

			if( uvPtr)
			{
				StrideOffset = FloatsPerVertex - 2;
				for( unsigned int i = 0; i < NumVertices; i++)
				{
					*VertexData++ = *uvPtr++;
					*VertexData++ = 1.0f - *uvPtr++;
					VertexData += StrideOffset;
				}
				VertexData -= NumVertices * FloatsPerVertex - 2;
			}

			VertexBuffer->Unlock();

			// Allocate our index buffer
			//
			if( D3D->CreateIndexBuffer( NumIndices * sizeof( DWORD), 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &IndexBuffer, NULL) != D3D_OK)
			{
				MGlobal::displayWarning( "Direct3D renderer : Unable to allocate index buffer\n");
				return false;
			}

			// Copy our index data into the buffer
			//
			unsigned int* IndexData = NULL;
			IndexBuffer->Lock( 0, 0, (void**)&IndexData, D3DLOCK_DISCARD);
			memcpy( IndexData, idx, NumIndices * sizeof(DWORD));
			IndexBuffer->Unlock();
		}
	}
	return IndexBuffer && VertexBuffer;
}