// // 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); } }
// // 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; }