//
// 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;
}
Exemple #2
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;
}