//------------------------------------------------------------------------------ int main(int, char **) { int maxlevel = 3; typedef Far::TopologyRefinerFactoryBase::TopologyDescriptor Descriptor; Sdc::SchemeType type = OpenSubdiv::Sdc::SCHEME_CATMARK; Sdc::Options options; options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY); options.SetFVarLinearInterpolation(Sdc::Options::FVAR_LINEAR_NONE); // Populate a topology descriptor with our raw data Descriptor desc; desc.numVertices = g_nverts; desc.numFaces = g_nfaces; desc.numVertsPerFace = g_vertsperface; desc.vertIndicesPerFace = g_vertIndices; // Create a face-varying channel descriptor Descriptor::FVarChannel uvs; uvs.numValues = g_nuvs; uvs.valueIndices = g_uvIndices; // Add the channel topology to the main descriptor desc.numFVarChannels = 1; desc.fvarChannels = & uvs; // Instantiate a FarTopologyRefiner from the descriptor Far::TopologyRefiner * refiner = Far::TopologyRefinerFactory<Descriptor>::Create(desc, Far::TopologyRefinerFactory<Descriptor>::Options(type, options)); // Uniformly refine the topolgy up to 'maxlevel' // note: fullTopologyInLastLevel must be true to work with face-varying data { Far::TopologyRefiner::UniformOptions options(maxlevel); options.fullTopologyInLastLevel = true; refiner->RefineUniform(options); } // Allocate & interpolate the 'vertex' primvar data (see tutorial 2 for // more details). std::vector<Vertex> vbuffer(refiner->GetNumVerticesTotal()); Vertex * verts = &vbuffer[0]; int nCoarseVerts = g_nverts; for (int i=0; i<nCoarseVerts; ++i) { verts[i].SetPosition(g_verts[i][0], g_verts[i][1], g_verts[i][2]); } refiner->Interpolate(verts, verts + nCoarseVerts); // Allocate & interpolate the 'face-varying' primvar data int channel = 0, nCoarseFVVerts = refiner->GetNumFVarValues(0, channel); std::vector<FVarVertex> fvBuffer(refiner->GetNumFVarValuesTotal(channel)); FVarVertex * fvVerts = &fvBuffer[0]; for (int i=0; i<g_nuvs; ++i) { fvVerts[i].u = g_uvs[i][0]; fvVerts[i].v = g_uvs[i][1]; } refiner->InterpolateFaceVarying(fvVerts, fvVerts + nCoarseFVVerts, channel); { // Output OBJ of the highest level refined ----------- // Print vertex positions for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { for (int vert=0; vert<refiner->GetNumVertices(level); ++vert) { float const * pos = verts[firstVert+vert].GetPosition(); printf("v %f %f %f\n", pos[0], pos[1], pos[2]); } } else { firstVert += refiner->GetNumVertices(level); } } // Print uvs for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { for (int vert=0; vert<refiner->GetNumFVarValues(level, channel); ++vert) { FVarVertex const & uv = fvVerts[firstVert+vert]; printf("vt %f %f\n", uv.u, uv.v); } } else { firstVert += refiner->GetNumFVarValues(level, channel); } } // Print faces for (int face=0; face<refiner->GetNumFaces(maxlevel); ++face) { Far::ConstIndexArray fverts = refiner->GetFaceVertices(maxlevel, face), fvverts = refiner->GetFVarFaceValues(maxlevel, face, channel); // all refined Catmark faces should be quads assert(fverts.size()==4 and fvverts.size()==4); printf("f "); for (int vert=0; vert<fverts.size(); ++vert) { // OBJ uses 1-based arrays... printf("%d/%d ", fverts[vert]+1, fvverts[vert]+1); } printf("\n"); } } }
//------------------------------------------------------------------------------ int main(int, char **) { int maxlevel = 5; Far::TopologyRefiner * refiner = createFarTopologyRefiner(); // Uniformly refine the topolgy up to 'maxlevel' refiner->RefineUniform( maxlevel ); // Allocate a buffer for vertex primvar data. The buffer length is set to // be the sum of all children vertices up to the highest level of refinement. std::vector<Vertex> vbuffer(refiner->GetNumVerticesTotal()); Vertex * verts = &vbuffer[0]; // Initialize coarse mesh primvar data int nCoarseVerts = g_nverts; for (int i=0; i<nCoarseVerts; ++i) { verts[i].SetPosition(g_verts[i][0], g_verts[i][1], g_verts[i][2]); verts[i].SetColor(g_colors[i][0], g_colors[i][1], g_colors[i][2]); } // Interpolate all primvar data - not that this will perform both 'vertex' and // 'varying' interpolation at once by calling each specialized method in our // Vertex class with the appropriate weights. refiner->Interpolate(verts, verts + nCoarseVerts); { // Visualization with Maya : print a MEL script that generates colored // particles at the location of the refined vertices (don't forget to // turn shading on in the viewport to see the colors) int nverts = refiner->GetNumVertices(maxlevel); // Position the 'verts' pointer to the first vertex of our 'maxlevel' level for (int level=0; level<maxlevel; ++level) { verts += refiner->GetNumVertices(level); } // Output particle positions printf("particle "); for (int vert=0; vert<nverts; ++vert) { float const * pos = verts[vert].GetPosition(); printf("-p %f %f %f\n", pos[0], pos[1], pos[2]); } printf(";\n"); // Set particle point size (20 -- very large) printf("addAttr -is true -ln \"pointSize\" -at long -dv 20 particleShape1;\n"); // Add per-particle color attribute ('rgbPP') printf("addAttr -ln \"rgbPP\" -dt vectorArray particleShape1;\n"); // Set per-particle color values from our 'varying' primvar data printf("setAttr \"particleShape1.rgbPP\" -type \"vectorArray\" %d ", nverts); for (int vert=0; vert<nverts; ++vert) { float const * color = verts[vert].GetColor(); printf("%f %f %f\n", color[0], color[1], color[2]); } printf(";\n"); } }