virtual void createVertexStream( const MDagPath &dagPath, MVertexBuffer &vertexBuffer, const MComponentDataIndexing &targetIndexing, const MComponentDataIndexing &, const MVertexBufferArray &) const { #else virtual void createVertexStream( const MDagPath &dagPath, MVertexBuffer &vertexBuffer, const MComponentDataIndexing &targetIndexing) const { #endif const MVertexBufferDescriptor &desc = vertexBuffer.descriptor(); MFnMesh meshFn(dagPath); int nVertices = meshFn.numVertices(); #if MAYA_API_VERSION >= 201350 float *buffer = static_cast<float*>(vertexBuffer.acquire(nVertices, true)); #else float *buffer = static_cast<float*>(vertexBuffer.acquire(nVertices)); #endif float *dst = buffer; if (_normal) { MFloatVectorArray normals; meshFn.getVertexNormals(true, normals); for (int i = 0; i < nVertices; ++i) { *dst++ = normals[i].x; *dst++ = normals[i].y; *dst++ = normals[i].z; } } else { MFloatPointArray points; meshFn.getPoints(points); for (int i = 0; i < nVertices; ++i) { *dst++ = points[i].x; *dst++ = points[i].y; *dst++ = points[i].z; } } vertexBuffer.commit(buffer); } static MPxVertexBufferGenerator *positionBufferCreator() { return new OsdBufferGenerator(/*normal = */false); } static MPxVertexBufferGenerator *normalBufferCreator() { return new OsdBufferGenerator(/*normal = */true); } private:
virtual void createVertexStream( #if MAYA_API_VERSION >= 201400 const MObject &object, #else const MDagPath &dagPath, #endif MVertexBuffer &vertexBuffer, const MComponentDataIndexing &targetIndexing, const MComponentDataIndexing &, const MVertexBufferArray &) const { #else virtual void createVertexStream( const MDagPath &dagPath, MVertexBuffer &vertexBuffer, const MComponentDataIndexing &targetIndexing) const { #endif #if MAYA_API_VERSION >= 201400 MFnMesh meshFn(object); #else MFnMesh meshFn(dagPath); #endif int nVertices = meshFn.numVertices(); #if MAYA_API_VERSION >= 201350 float *buffer = static_cast<float*>(vertexBuffer.acquire(nVertices, true)); #else float *buffer = static_cast<float*>(vertexBuffer.acquire(nVertices)); #endif float *dst = buffer; if (_normal) { MFloatVectorArray normals; meshFn.getVertexNormals(true, normals); for (int i = 0; i < nVertices; ++i) { *dst++ = normals[i].x; *dst++ = normals[i].y; *dst++ = normals[i].z; } } else { MFloatPointArray points; meshFn.getPoints(points); for (int i = 0; i < nVertices; ++i) { *dst++ = points[i].x; *dst++ = points[i].y; *dst++ = points[i].z; } } vertexBuffer.commit(buffer); }
const MVertexBufferArray &) const #else virtual void createVertexStream(const MDagPath &dagPath, MVertexBuffer &vertexBuffer, const MComponentDataIndexing &targetIndexing) const #endif { const MVertexBufferDescriptor &desc = vertexBuffer.descriptor(); MFnMesh meshFn(dagPath); int nVertices = meshFn.numVertices(); if (!_normal) { MFloatPointArray points; meshFn.getPoints(points); #ifdef MAYA2013_PREVIEW float *buffer = (float*)vertexBuffer.acquire(nVertices, true); #else float *buffer = (float*)vertexBuffer.acquire(nVertices); #endif float *dst = buffer; for(int i=0; i < nVertices; ++i){ *dst++ = points[i].x; *dst++ = points[i].y; *dst++ = points[i].z; } vertexBuffer.commit(buffer); } else { MFloatVectorArray normals; meshFn.getVertexNormals(true, normals); #ifdef MAYA2013_PREVIEW float *buffer = (float*)vertexBuffer.acquire(nVertices, true); #else float *buffer = (float*)vertexBuffer.acquire(nVertices); #endif float *dst = buffer; for(int i=0; i < nVertices; ++i){ *dst++ = normals[i].x; *dst++ = normals[i].y; *dst++ = normals[i].z; } vertexBuffer.commit(buffer); } }
virtual void createVertexStream(const MObject& object, MVertexBuffer& vertexBuffer, const MComponentDataIndexing& targetIndexing, const MComponentDataIndexing& /*sharedIndexing*/, const MVertexBufferArray& /*sourceStreams*/) const { // get the descriptor from the vertex buffer. // It describes the format and layout of the stream. const MVertexBufferDescriptor& descriptor = vertexBuffer.descriptor(); // we are expecting a float stream. if (descriptor.dataType() != MGeometry::kFloat) return; // we are expecting a float2 if (descriptor.dimension() != 2) return; // we are expecting a texture channel if (descriptor.semantic() != MGeometry::kTexture) return; // get the mesh from the current path // if it is not a mesh we do nothing. MStatus status; MFnMesh mesh(object, &status); if (!status) return; // failed const MUintArray& indices = targetIndexing.indices(); unsigned int vertexCount = indices.length(); if (vertexCount <= 0) return; // acquire the buffer to fill with data. float* buffer = (float*)vertexBuffer.acquire(vertexCount, true /*writeOnly - we don't need the current buffer values*/); float* start = buffer; for(unsigned int i = 0; i < vertexCount; ++i) { // Here we are embedding some custom data into the stream. // The included effects (vertexBufferGeneratorGL.cgfx and // vertexBufferGeneratorDX11.fx) will alternate // red, green, and blue vertex colored triangles based on this input. *(buffer++) = 1.0f; *(buffer++) = (float)indices[i]; // color index } // commit the buffer to signal completion. vertexBuffer.commit(start); }
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); } }
virtual void createVertexStream(const MObject& object, MVertexBuffer& vertexBuffer, const MComponentDataIndexing& targetIndexing, const MComponentDataIndexing& /*sourceIndexing*/, const MVertexBufferArray& sourceStreams) const { // get the descriptor from the vertex buffer. // It describes the format and layout of the stream. const MVertexBufferDescriptor& descriptor = vertexBuffer.descriptor(); // we are expecting a float or int stream. MGeometry::DataType dataType = descriptor.dataType(); if (dataType != MGeometry::kFloat && dataType != MGeometry::kInt32) return; // we are expecting a dimension of 3 or 4 int dimension = descriptor.dimension(); if (dimension != 4 && dimension != 3) return; // we are expecting a texture channel if (descriptor.semantic() != MGeometry::kTexture) return; // get the mesh from the current path // if it is not a mesh we do nothing. MStatus status; MFnMesh mesh(object, &status); if (!status) return; // failed const MUintArray& indices = targetIndexing.indices(); unsigned int vertexCount = indices.length(); if (vertexCount <= 0) return; MVertexBuffer *positionStream = sourceStreams.getBuffer( "Position" ); if(positionStream == NULL || positionStream->descriptor().dataType() != MGeometry::kFloat) return; int positionDimension = positionStream->descriptor().dimension(); if(positionDimension != 3 && positionDimension != 4) return; MVertexBuffer *normalStream = sourceStreams.getBuffer( "Normal" ); if(normalStream == NULL || normalStream->descriptor().dataType() != MGeometry::kFloat) return; int normalDimension = normalStream->descriptor().dimension(); if(normalDimension != 3 && normalDimension != 4) return; float* positionBuffer = (float*)positionStream->map(); if(positionBuffer) { float* normalBuffer = (float*)normalStream->map(); if(normalBuffer) { void* compositeBuffer = vertexBuffer.acquire(vertexCount, true /*writeOnly - we don't need the current buffer values*/); if(compositeBuffer) { void* compositeBufferStart = compositeBuffer; float* compositeBufferAsFloat = (float*)compositeBuffer; int* compositeBufferAsInt = (int*)compositeBuffer; for(unsigned int i = 0; i < vertexCount; ++i) { if(dataType == MGeometry::kFloat) { *(compositeBufferAsFloat++) = *(positionBuffer + 1); // store position.y *(compositeBufferAsFloat++) = *(positionBuffer + 2); // store position.z *(compositeBufferAsFloat++) = *(normalBuffer); // store normal.x if(dimension == 4) *(compositeBufferAsFloat++) = *(normalBuffer + 2); // store normal.z } else if(dataType == MGeometry::kInt32) { *(compositeBufferAsInt++) = (int)(*(positionBuffer + 1) * 255); // store position.y *(compositeBufferAsInt++) = (int)(*(positionBuffer + 2) * 255); // store position.z *(compositeBufferAsInt++) = (int)(*(normalBuffer) * 255); // store normal.x if(dimension == 4) *(compositeBufferAsInt++) = (int)(*(normalBuffer + 2) * 255); // store normal.z } positionBuffer += positionDimension; normalBuffer += normalDimension; } vertexBuffer.commit(compositeBufferStart); } normalStream->unmap(); } positionStream->unmap(); } }