MObject animCube::createMesh(const MTime& time, MObject& outData, MStatus& stat) { int numVertices, frame; float cubeSize; MFloatPointArray points; MFnMesh meshFS; // Scale the cube on the frame number, wrap every 10 frames. frame = (int)time.as( MTime::kFilm ); if (frame == 0) frame = 1; cubeSize = 0.5f * (float)( frame % 10); const int numFaces = 6; numVertices = 8; const int numFaceConnects = 24; MFloatPoint vtx_1( -cubeSize, -cubeSize, -cubeSize ); MFloatPoint vtx_2( cubeSize, -cubeSize, -cubeSize ); MFloatPoint vtx_3( cubeSize, -cubeSize, cubeSize ); MFloatPoint vtx_4( -cubeSize, -cubeSize, cubeSize ); MFloatPoint vtx_5( -cubeSize, cubeSize, -cubeSize ); MFloatPoint vtx_6( -cubeSize, cubeSize, cubeSize ); MFloatPoint vtx_7( cubeSize, cubeSize, cubeSize ); MFloatPoint vtx_8( cubeSize, cubeSize, -cubeSize ); points.append( vtx_1 ); points.append( vtx_2 ); points.append( vtx_3 ); points.append( vtx_4 ); points.append( vtx_5 ); points.append( vtx_6 ); points.append( vtx_7 ); points.append( vtx_8 ); // Set up an array containing the number of vertices // for each of the 6 cube faces (4 verticies per face) // int face_counts[numFaces] = { 4, 4, 4, 4, 4, 4 }; MIntArray faceCounts( face_counts, numFaces ); // Set up and array to assign vertices from points to each face // int face_connects[ numFaceConnects ] = { 0, 1, 2, 3, 4, 5, 6, 7, 3, 2, 6, 5, 0, 3, 5, 4, 0, 4, 7, 1, 1, 7, 6, 2 }; MIntArray faceConnects( face_connects, numFaceConnects ); MObject newMesh = meshFS.create(numVertices, numFaces, points, faceCounts, faceConnects, outData, &stat); return newMesh; }
MStatus LSSolverNode::buildOutputMesh(MFnMesh& inputMesh, float* vertices, MObject &outputMesh) { MStatus stat; MPointArray points; unsigned vIndex = 0; int numVertices = inputMesh.numVertices(); for(int i=0; i<numVertices;i++) { double x = vertices[vIndex++]; double y = vertices[vIndex++]; double z = vertices[vIndex++]; //std::cout<<"("<<x<<","<<y<<","<<z<<")"<<endl; MPoint point(x,y,z); points.append(point); } const int numFaces = inputMesh.numPolygons(); int *face_counts = new int[numFaces]; for(int i = 0 ; i < numFaces ; i++) { face_counts[i] = 3; } MIntArray faceCounts( face_counts, numFaces ); // Set up and array to assign vertices from points to each face int numFaceConnects = numFaces * 3; int *face_connects = new int[numFaceConnects]; int faceConnectsIdx = 0; for ( int i=0; i<numFaces; i++ ) { MIntArray polyVerts; inputMesh.getPolygonVertices( i, polyVerts ); int pvc = polyVerts.length(); face_connects[faceConnectsIdx++] = polyVerts[0]; face_connects[faceConnectsIdx++]= polyVerts[1]; face_connects[faceConnectsIdx++] = polyVerts[2]; } MIntArray faceConnects( face_connects, numFaceConnects ); MFnMesh meshFS; MObject newMesh = meshFS.create(numVertices, numFaces, points, faceCounts, faceConnects, outputMesh, &stat); return stat; }
static MStatus convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & refinedVerts, bool hasUVs, std::vector<FVarVertexUV> const & refinedUVs, bool hasColors, std::vector<FVarVertexColor> const & refinedColors, MFnMesh & inMeshFn, MObject newMeshDataObj) { MStatus status; typedef OpenSubdiv::Far::ConstIndexArray IndexArray; int maxlevel = refiner.GetMaxLevel(); OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); int nfaces = refLastLevel.GetNumFaces(); // Init Maya Data // Face Counts MIntArray faceCounts(nfaces); for (int face=0; face < nfaces; ++face) { faceCounts[face] = 4; } // Face Connects MIntArray faceConnects(nfaces*4); for (int face=0, idx=0; face < nfaces; ++face) { IndexArray fverts = refLastLevel.GetFaceVertices(face); for (int vert=0; vert < fverts.size(); ++vert) { faceConnects[idx++] = fverts[vert]; } } // Points int nverts = refLastLevel.GetNumVertices(); int firstOfLastVert = refiner.GetNumVerticesTotal() - nverts - refiner.GetLevel(0).GetNumVertices(); MFloatPointArray points(nverts); for (int vIt = 0; vIt < nverts; ++vIt) { Vertex const & v = refinedVerts[firstOfLastVert + vIt]; points.set(vIt, v.position[0], v.position[1], v.position[2]); } // Create New Mesh from MFnMesh MFnMesh newMeshFn; MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newMeshDataObj, &status); MCHECKERR(status, "Cannot create new mesh"); // Get face-varying set names and other info from the inMesh MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); // Add new UVs back to the mesh if needed if (hasUVs) { MIntArray fvarConnects(faceConnects.length()); int count = 0; for (int f = 0; f < refLastLevel.GetNumFaces(); ++f) { IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELUV); for (int index = 0 ; index < faceIndices.size() ; ++index) { fvarConnects[count++] = faceIndices[index]; } } int nuvs = refLastLevel.GetNumFVarValues(CHANNELUV); int firstOfLastUvs = refiner.GetNumFVarValuesTotal(CHANNELUV) - nuvs - refiner.GetLevel(0).GetNumFVarValues(CHANNELUV); MFloatArray uCoord(nuvs), vCoord(nuvs); for (int uvIt = 0; uvIt < nuvs; ++uvIt) { FVarVertexUV const & uv = refinedUVs[firstOfLastUvs + uvIt]; uCoord[uvIt] = uv.u; vCoord[uvIt] = uv.v; } // Currently, the plugin only supports one UV set int uvSetIndex = 0; if (uvSetIndex > 0) { status = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] ); MCHECKERR(status, "Cannot create UVSet"); } static MString defaultUVName("map1"); MString const * uvname = uvSetIndex==0 ? &defaultUVName : &uvSetNames[uvSetIndex]; status = newMeshFn.setUVs(uCoord, vCoord, uvname); MCHECKERR(status, "Cannot set UVs for set : "+*uvname); status = newMeshFn.assignUVs(faceCounts, fvarConnects, uvname); MCHECKERR(status, "Cannot assign UVs"); } // Add new colors back to the mesh if needed if (hasColors) { int count = 0; MIntArray fvarConnects2(faceConnects.length()); for (int f = 0 ; f < refLastLevel.GetNumFaces(); ++f) { IndexArray faceIndices = refLastLevel.GetFaceFVarValues(f, CHANNELCOLOR); for (int index = 0 ; index < faceIndices.size() ; ++index) { fvarConnects2[count++] = faceIndices[index]; } } int ncols = refLastLevel.GetNumFVarValues(CHANNELCOLOR); int firstOfLastCols = refiner.GetNumFVarValuesTotal(CHANNELCOLOR) - ncols - refiner.GetLevel(0).GetNumFVarValues(CHANNELCOLOR); MColorArray colorArray(ncols); for (int colIt = 0; colIt < ncols; ++colIt) { FVarVertexColor const & c = refinedColors[firstOfLastCols + colIt]; colorArray.set(colIt, c.r, c.g, c.b, c.a); } // Currently, the plugin only supports one color sets int colorSetIndex = 0; // Assign color buffer and map the ids for each face-vertex // API Limitation: Cannot set MColorRepresentation here status = newMeshFn.createColorSetDataMesh( colorSetNames[colorSetIndex]); MCHECKERR(status, "Cannot create ColorSet"); bool isColorClamped = inMeshFn.isColorClamped( colorSetNames[colorSetIndex], &status); MCHECKERR(status, "Can not get Color Clamped "); status = newMeshFn.setIsColorClamped( colorSetNames[colorSetIndex], isColorClamped); MCHECKERR(status, "Can not set Color Clamped : " + isColorClamped); status = newMeshFn.setColors( colorArray, &colorSetNames[colorSetIndex], colorSetReps[colorSetIndex]); MCHECKERR(status, "Can not set Colors"); status = newMeshFn.assignColors( fvarConnects2, &colorSetNames[colorSetIndex]); MCHECKERR(status, "Can not assign Colors"); } return MS::kSuccess; }
MStatus convertOsdFarToMayaMeshData( FMesh const * farMesh, OpenSubdiv::OsdCpuVertexBuffer * vertexBuffer, int subdivisionLevel, MFnMesh const & inMeshFn, MObject newMeshDataObj ) { MStatus returnStatus; // Get sizing data from OSD const OpenSubdiv::FarPatchTables *farPatchTables = farMesh->GetPatchTables(); int numPolygons = farPatchTables->GetNumFaces(); // use the highest level stored in the patch tables const unsigned int *polygonConnects_orig = farPatchTables->GetFaceVertices(); // use the highest level stored in the patch tables const OpenSubdiv::FarSubdivisionTables<OpenSubdiv::OsdVertex> *farSubdivTables = farMesh->GetSubdivisionTables(); unsigned int numVertices = farSubdivTables->GetNumVertices(subdivisionLevel); unsigned int vertexOffset = farSubdivTables->GetFirstVertexOffset(subdivisionLevel); // Init Maya Data MFloatPointArray points(numVertices); MIntArray faceCounts(numPolygons); // number of edges for each polygon. Assume quads (4-edges per face) MIntArray faceConnects(numPolygons*4); // array of vertex ids for all edges. assuming quads // -- Face Counts for (int i=0; i < numPolygons; ++i) { faceCounts[i] = 4; } // -- Face Connects for (unsigned int i=0; i < faceConnects.length(); i++) { faceConnects[i] = polygonConnects_orig[i] - vertexOffset; // adjust vertex indices so that v0 is at index 0 } // -- Points // Number of floats in each vertex. (positions, normals, etc) int numFloatsPerVertex = vertexBuffer->GetNumElements(); assert(numFloatsPerVertex == 3); // assuming only xyz stored for each vertex const float *vertexData = vertexBuffer->BindCpuBuffer(); float *ptrVertexData; for (unsigned int i=0; i < numVertices; i++) { // make sure to offset to the first osd vertex for that subd level unsigned int osdRawVertexIndex = i + vertexOffset; // Lookup the data in the vertexData ptrVertexData = (float *) vertexData + ((osdRawVertexIndex) * numFloatsPerVertex); points.set(i, ptrVertexData[0], ptrVertexData[1], ptrVertexData[2]); } // Create New Mesh from MFnMesh MFnMesh newMeshFn; MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newMeshDataObj, &returnStatus); MCHECKERR(returnStatus, "Cannot create new mesh"); // Attach UVs (if present) // ASSUMPTION: Only tracking UVs as FVar data. Will need to change this // ASSUMPTION: OSD has a unique UV for each face-vertex int fvarTotalWidth = farMesh->GetTotalFVarWidth(); if (fvarTotalWidth > 0) { // Get face-varying set names and other info from the inMesh MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; returnStatus = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); int numUVSets = uvSetNames.length(); int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels; assert(fvarTotalWidth == expectedFvarTotalWidth); const OpenSubdiv::FarPatchTables::FVarDataTable &fvarDataTable = farPatchTables->GetFVarDataTable(); assert(fvarDataTable.size() == expectedFvarTotalWidth*faceConnects.length()); // Create an array of indices to map each face-vert to the UV and ColorSet Data MIntArray fvarConnects(faceConnects.length()); for (unsigned int i=0; i < faceConnects.length(); i++) { fvarConnects[i] = i; } MFloatArray uCoord(faceConnects.length()); MFloatArray vCoord(faceConnects.length()); for (int uvSetIndex=0; uvSetIndex < numUVSets; uvSetIndex++) { for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) { int fvarItem = vertid*fvarTotalWidth + uvSetIndex*2; // stride per vertex is the fvarTotalWidth uCoord[vertid] = fvarDataTable[fvarItem]; vCoord[vertid] = fvarDataTable[fvarItem+1]; } // Assign UV buffer and map the uvids for each face-vertex if (uvSetIndex != 0) { // assume uvset index 0 is the default UVset, so do not create returnStatus = newMeshFn.createUVSetDataMesh( uvSetNames[uvSetIndex] ); } MCHECKERR(returnStatus, "Cannot create UVSet"); newMeshFn.setUVs(uCoord,vCoord, &uvSetNames[uvSetIndex]); newMeshFn.assignUVs(faceCounts, fvarConnects, &uvSetNames[uvSetIndex]); } MColorArray colorArray(faceConnects.length()); int colorSetRelativeStartIndex = numUVSets*2; for (unsigned int colorSetIndex=0; colorSetIndex < colorSetNames.length(); colorSetIndex++) { for(unsigned int vertid=0; vertid < faceConnects.length(); vertid++) { int fvarItem = vertid*fvarTotalWidth + colorSetRelativeStartIndex; if (colorSetChannels[colorSetIndex] == 1) { colorArray[vertid].r = fvarDataTable[fvarItem]; colorArray[vertid].g = fvarDataTable[fvarItem]; colorArray[vertid].b = fvarDataTable[fvarItem]; colorArray[vertid].a = 1.0f; } else if (colorSetChannels[colorSetIndex] == 3) { colorArray[vertid].r = fvarDataTable[fvarItem]; colorArray[vertid].g = fvarDataTable[fvarItem+1]; colorArray[vertid].b = fvarDataTable[fvarItem+2]; colorArray[vertid].a = 1.0f; } else { colorArray[vertid].r = fvarDataTable[fvarItem]; colorArray[vertid].g = fvarDataTable[fvarItem+1]; colorArray[vertid].b = fvarDataTable[fvarItem+2]; colorArray[vertid].a = fvarDataTable[fvarItem+3]; } } // Assign UV buffer and map the uvids for each face-vertex // API Limitation: Cannot set MColorRepresentation here returnStatus = newMeshFn.createColorSetDataMesh(colorSetNames[colorSetIndex]); MCHECKERR(returnStatus, "Cannot create ColorSet"); bool isColorClamped = inMeshFn.isColorClamped(colorSetNames[colorSetIndex], &returnStatus); newMeshFn.setIsColorClamped(colorSetNames[colorSetIndex], isColorClamped); newMeshFn.setColors(colorArray, &colorSetNames[colorSetIndex], colorSetReps[colorSetIndex]); newMeshFn.assignColors(fvarConnects, &colorSetNames[colorSetIndex]); // Increment colorSet start location in fvar buffer colorSetRelativeStartIndex += colorSetChannels[colorSetIndex]; } } return MS::kSuccess; }
static MStatus convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & vertexBuffer, MFnMesh const & inMeshFn, MObject newMeshDataObj) { MStatus status; typedef OpenSubdiv::Far::ConstIndexArray IndexArray; int maxlevel = refiner.GetMaxLevel(); OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); int nfaces = refLastLevel.GetNumFaces(); // Init Maya Data // -- Face Counts MIntArray faceCounts(nfaces); for (int face=0; face < nfaces; ++face) { faceCounts[face] = 4; } // -- Face Connects MIntArray faceConnects(nfaces*4); for (int face=0, idx=0; face < nfaces; ++face) { IndexArray fverts = refLastLevel.GetFaceVertices(face); for (int vert=0; vert < fverts.size(); ++vert) { faceConnects[idx++] = fverts[vert]; } } // -- Points MFloatPointArray points(refLastLevel.GetNumVertices()); Vertex const * v = &vertexBuffer.at(0); for (int level=1; level<=maxlevel; ++level) { int nverts = refiner.GetLevel(level).GetNumVertices(); if (level==maxlevel) { for (int vert=0; vert < nverts; ++vert, ++v) { points.set(vert, v->position[0], v->position[1], v->position[2]); } } else { v += nverts; } } // Create New Mesh from MFnMesh MFnMesh newMeshFn; MObject newMeshObj = newMeshFn.create(points.length(), faceCounts.length(), points, faceCounts, faceConnects, newMeshDataObj, &status); MCHECKERR(status, "Cannot create new mesh"); int fvarTotalWidth = 0; if (fvarTotalWidth > 0) { // Get face-varying set names and other info from the inMesh MStringArray uvSetNames; MStringArray colorSetNames; std::vector<int> colorSetChannels; std::vector<MFnMesh::MColorRepresentation> colorSetReps; int totalColorSetChannels = 0; status = getMayaFvarFieldParams(inMeshFn, uvSetNames, colorSetNames, colorSetChannels, colorSetReps, totalColorSetChannels); #if defined(DEBUG) or defined(_DEBUG) int numUVSets = uvSetNames.length(); int expectedFvarTotalWidth = numUVSets*2 + totalColorSetChannels; assert(fvarTotalWidth == expectedFvarTotalWidth); #endif // XXXX fvar stuff here } return MS::kSuccess; }