CacheMeshSampler::AttributeSet::AttributeSet( MFnMesh& mesh, const bool needUVs, const bool useBaseTessellation ) :fNumWires(0), fNumTriangles(0), fNumVerts(0) { // Refresh the internal shape, otherwise topo changes make mesh.numPolygons() crash. // Note that buildShaderAssignmentGroups() also call mesh.numPolygons(). mesh.syncObject(); MDagPath dagPath; mesh.getPath(dagPath); // build a geometry request and add requirements to it. MHWRender::MGeometryRequirements geomRequirements; // Build descriptors to request the positions, normals and UVs MVertexBufferDescriptor posDesc("", MGeometry::kPosition, MGeometry::kFloat, 3); MVertexBufferDescriptor normalDesc("", MGeometry::kNormal, MGeometry::kFloat, 3); MVertexBufferDescriptor uvDesc(mesh.currentUVSetName(), MGeometry::kTexture, MGeometry::kFloat, 2); // add the descriptors to the geometry requirements geomRequirements.addVertexRequirement(posDesc); geomRequirements.addVertexRequirement(normalDesc); if (needUVs) geomRequirements.addVertexRequirement(uvDesc); MString noName; // we do not need custom named index buffers here. // create a component to include all elements. MFnSingleIndexedComponent comp; MObject compObj = comp.create(MFn::kMeshPolygonComponent); comp.setCompleteData(mesh.numPolygons()); // create edge component MFnSingleIndexedComponent edgeComp; MObject edgeCompObj = edgeComp.create(MFn::kMeshEdgeComponent); edgeComp.setCompleteData(mesh.numEdges()); // Add the edge line index buffer to the requirements MIndexBufferDescriptor edgeDesc(MIndexBufferDescriptor::kEdgeLine, noName, MGeometry::kLines, 2, edgeCompObj); geomRequirements.addIndexingRequirement(edgeDesc); // add a triangle buffer to the requirements MIndexBufferDescriptor triangleDesc(MIndexBufferDescriptor::kTriangle, noName, MGeometry::kTriangles, 3, compObj); geomRequirements.addIndexingRequirement(triangleDesc); typedef IndexBuffer::index_t index_t; // We ignore the Smooth Preview option on the mesh shape node when // using base tessellation. int extractorOptions = MHWRender::kPolyGeom_Normal; if (useBaseTessellation) { extractorOptions |= MHWRender::kPolyGeom_BaseMesh; } // create an extractor to get the geometry MStatus status; MHWRender::MGeometryExtractor extractor(geomRequirements,dagPath, extractorOptions, &status); if (MS::kFailure==status) return; // get the number of vertices from the extractor unsigned int numVertices = extractor.vertexCount(); // get the number of primitives (triangles, lines, etc.) unsigned int numWires = extractor.primitiveCount(edgeDesc); // create the arrays that the generator will fill boost::shared_array<float> vertices(new float[numVertices*posDesc.stride()]); boost::shared_array<float> normals(new float[numVertices*normalDesc.stride()]); boost::shared_array<float> uvs(new float[numVertices*uvDesc.stride()]); unsigned int minBufferSize = extractor.minimumBufferSize(numWires, edgeDesc.primitive()); boost::shared_array<index_t> wireframeIdx(new index_t[minBufferSize]); // populate the index buffer for the edges if (MS::kFailure==extractor.populateIndexBuffer(wireframeIdx.get(), numWires, edgeDesc)) return; // populate the vertex buffers you are interested in. (pos, normal, and uv) if (MS::kFailure==extractor.populateVertexBuffer(vertices.get(), numVertices, posDesc)) return; if (MS::kFailure==extractor.populateVertexBuffer(normals.get(), numVertices, normalDesc)) return; if (needUVs && MS::kFailure==extractor.populateVertexBuffer(uvs.get(), numVertices, uvDesc)) return; // populate the index buffers for all the triangle components { std::vector<boost::shared_ptr<Array<index_t> > > trgIdxGrps; // get the index buffer count from the extractor unsigned int numTriangles = extractor.primitiveCount(triangleDesc); minBufferSize = extractor.minimumBufferSize(numTriangles, triangleDesc.primitive()); boost::shared_array<index_t> triangleIdx(new index_t[minBufferSize]); if (numTriangles != 0) { if (MS::kFailure==extractor.populateIndexBuffer(triangleIdx.get(), numTriangles, triangleDesc)) return; fNumTriangles += (size_t)numTriangles; } trgIdxGrps.push_back(SharedArray<index_t>::create( triangleIdx, 3 * numTriangles)); for(size_t i=0, offset=0; i<trgIdxGrps.size(); ++i) { fTriangleVertIndices.push_back(IndexBuffer::create( trgIdxGrps[0], offset, offset + trgIdxGrps[i]->size())); offset += trgIdxGrps[i]->size(); } } fNumWires = (size_t)numWires; fNumVerts = (size_t)numVertices; fWireVertIndices = IndexBuffer::create( SharedArray<index_t>::create( wireframeIdx, 2 * fNumWires)); fPositions = VertexBuffer::createPositions( SharedArray<float>::create( vertices, 3 * fNumVerts)); fNormals = VertexBuffer::createNormals( SharedArray<float>::create( normals, 3 * fNumVerts)); if (needUVs) { fUVs = VertexBuffer::createUVs( SharedArray<float>::create(uvs, 2 * fNumVerts)); } fBoundingBox = mesh.boundingBox(); // Check visibility fVisibility = ShapeVisibilityChecker(mesh.object()).isVisible(); }