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