//------------------------------------------------------------------------------ // generate display IDs for Vtr verts static void createVertNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & vertexBuffer) { int maxlevel = refiner.GetMaxLevel(), firstvert = 0; if (refiner.IsUniform()) { for (int i=0; i<maxlevel; ++i) { firstvert += refiner.GetNumVertices(i); } } static char buf[16]; if (refiner.IsUniform()) { for (int i=firstvert; i<(int)vertexBuffer.size(); ++i) { snprintf(buf, 16, "%d", i); g_font->Print3D(vertexBuffer[i].GetPos(), buf, 1); } } else { for (int level=0, vert=0; level<=refiner.GetMaxLevel(); ++level) { for (int i=0; i<refiner.GetNumVertices(level); ++i, ++vert) { snprintf(buf, 16, "%d", i); g_font->Print3D(vertexBuffer[vert].GetPos(), buf, 1); } } } }
//------------------------------------------------------------------------------ // generate display IDs for Far faces static void createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & vertexBuffer) { static char buf[16]; if (refiner.IsUniform()) { int maxlevel = refiner.GetMaxLevel(), firstvert = 0; for (int i=0; i<maxlevel; ++i) { firstvert += refiner.GetLevel(i).GetNumVertices(); } OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); for (int face=0; face<refLastLevel.GetNumFaces(); ++face) { Vertex center(0.0f, 0.0f, 0.0f); OpenSubdiv::Far::ConstIndexArray const verts = refLastLevel.GetFaceVertices(face); float weight = 1.0f / (float)verts.size(); for (int vert=0; vert<verts.size(); ++vert) { center.AddWithWeight(vertexBuffer[firstvert+verts[vert]], weight); } snprintf(buf, 16, "%d", face); g_font->Print3D(center.GetPos(), buf, 2); } } else { int maxlevel = refiner.GetMaxLevel(), // patch = refiner.GetLevel(0).GetNumFaces(), firstvert = refiner.GetLevel(0).GetNumVertices(); for (int level=1; level<=maxlevel; ++level) { OpenSubdiv::Far::TopologyLevel const & refLevel = refiner.GetLevel(level); int nfaces = refLevel.GetNumFaces(); for (int face=0; face<nfaces; ++face /*, ++patch */) { Vertex center(0.0f, 0.0f, 0.0f); OpenSubdiv::Far::ConstIndexArray const verts = refLevel.GetFaceVertices(face); float weight = 1.0f / (float)verts.size(); for (int vert=0; vert<verts.size(); ++vert) { center.AddWithWeight(vertexBuffer[firstvert+verts[vert]], weight); } snprintf(buf, 16, "%d", face); g_font->Print3D(center.GetPos(), buf, 2); } firstvert+=refLevel.GetNumVertices(); } } }
void InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner, Shape const & shape, std::vector<float> & fvarData) { int channel = 0, // shapes only have 1 UV channel fvarWidth = 2; int maxlevel = refiner.GetMaxLevel(), numValuesM = refiner.GetLevel(maxlevel).GetNumFVarValues(channel), numValuesTotal = refiner.GetNumFVarValuesTotal(channel); if (shape.uvs.empty() || numValuesTotal<=0) { return; } OpenSubdiv::Far::PrimvarRefiner primvarRefiner(refiner); if (refiner.IsUniform()) { // For uniform we only keep the highest level of refinement: fvarData.resize(numValuesM * fvarWidth); std::vector<FVarVertex> buffer(numValuesTotal - numValuesM); FVarVertex * src = &buffer[0]; memcpy(src, &shape.uvs[0], shape.uvs.size()*sizeof(float)); // Defer the last level to treat separately with its alternate destination: for (int level = 1; level < maxlevel; ++level) { FVarVertex * dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel); primvarRefiner.InterpolateFaceVarying(level, src, dst, channel); src = dst; } FVarVertex * dst = reinterpret_cast<FVarVertex *>(&fvarData[0]); primvarRefiner.InterpolateFaceVarying(maxlevel, src, dst, channel); } else { // For adaptive we keep all levels: fvarData.resize(numValuesTotal * fvarWidth); FVarVertex * src = reinterpret_cast<FVarVertex *>(&fvarData[0]); memcpy(src, &shape.uvs[0], shape.uvs.size()*sizeof(float)); for (int level = 1; level <= maxlevel; ++level) { FVarVertex * dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel); primvarRefiner.InterpolateFaceVarying(level, src, dst, channel); src = dst; } } }
//------------------------------------------------------------------------------ // generate display IDs for Far edges static void createEdgeNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector<Vertex> const & vertexBuffer, bool ids=false, bool sharpness=false) { if (ids or sharpness) { int maxlevel = refiner.GetMaxLevel(), firstvert = 0; for (int i=0; i<maxlevel; ++i) { firstvert += refiner.GetLevel(i).GetNumVertices(); } OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); static char buf[16]; for (int i=0; i<refLastLevel.GetNumEdges(); ++i) { Vertex center(0.0f, 0.0f, 0.0f); OpenSubdiv::Far::ConstIndexArray const verts = refLastLevel.GetEdgeVertices(i); assert(verts.size()==2); center.AddWithWeight(vertexBuffer[firstvert+verts[0]], 0.5f); center.AddWithWeight(vertexBuffer[firstvert+verts[1]], 0.5f); if (ids) { snprintf(buf, 16, "%d", i); g_font->Print3D(center.GetPos(), buf, 3); } if (sharpness) { float sharpness = refLastLevel.GetEdgeSharpness(i); if (sharpness>0.0f) { snprintf(buf, 16, "%g", sharpness); g_font->Print3D(center.GetPos(), buf, std::min(8,(int)sharpness+4)); } } } } }
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; }
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; }