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