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