//------------------------------------------------------------------------------ int main(int, char **) { Hmesh * hmesh = createMesh(); int maxlevel=2, // 2 levels of subdivision firstface=0, // marker to the first face index of level 2 firstvertex=0; // marker to the first vertex index of level 2 // Refine the mesh to 'maxlevel' for (int level=0; level<maxlevel; ++level) { // Total number of faces in the mesh, across all levels // // Mote: this function iterates over the list of faces and can be slow int nfaces = hmesh->GetNumFaces(); if (level==(maxlevel-1)) { // Save our vertex marker firstvertex = hmesh->GetNumVertices(); } // Iterate over the faces of the current level of subdivision for (int face=firstface; face<nfaces; ++face) { Hface * f = hmesh->GetFace(face); // Mote : hole tags would have to be dealt with here. f->Refine(); } // Save our face index marker for the next level firstface = nfaces; } { // Output OBJ of the highest level refined ----------- // Print vertex positions int nverts = hmesh->GetNumVertices(); for (int vert=firstvertex; vert<nverts; ++vert) { float const * pos = hmesh->GetVertex(vert)->GetData().GetPosition(); printf("v %f %f %f\n", pos[0], pos[1], pos[2]); } // Print faces for (int face=firstface; face<hmesh->GetNumFaces(); ++face) { Hface * f = hmesh->GetFace(face); assert(f->GetNumVertices()==4 ); printf("f "); for (int vert=0; vert<4; ++vert) { // OBJ uses 1-based arrays printf("%d ", f->GetVertex(vert)->GetID() - firstvertex + 1); } printf("\n"); } } }
//------------------------------------------------------------------------------ // Creates an Hbr mesh // // see hbr_tutorial_0 and hbr_tutorial_1 for more details // Hmesh * createMesh() { // Pyramid geometry from catmark_pyramid.h static float verts[5][3] = {{ 0.0f, 0.0f, 2.0f}, { 0.0f, -2.0f, 0.0f}, { 2.0f, 0.0f, 0.0f}, { 0.0f, 2.0f, 0.0f}, {-2.0f, 0.0f, 0.0f}}; static int nverts = 5, nfaces = 5; static int facenverts[5] = { 3, 3, 3, 3, 4 }; static int faceverts[16] = { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1, 4, 3, 2, 1 }; OpenSubdiv::HbrCatmarkSubdivision<Vertex> * catmark = new OpenSubdiv::HbrCatmarkSubdivision<Vertex>(); Hmesh * hmesh = new Hmesh(catmark); // Populate the vertices Vertex v; for (int i=0; i<nverts; ++i) { v.SetPosition(verts[i][0], verts[i][1], verts[i][2]); hmesh->NewVertex(i, v); } // Create the topology int * fv = faceverts; for (int i=0; i<nfaces; ++i) { int nv = facenverts[i]; bool valid = true; for(int j=0;j<nv;j++) { Hvertex const * origin = hmesh->GetVertex(fv[j]), * destination = hmesh->GetVertex(fv[(j+1)%nv]); Hhalfedge const * opposite = destination->GetEdge(origin); // Make sure that the vertices exist in the mesh if (origin==NULL or destination==NULL) { printf(" An edge was specified that connected a nonexistent vertex\n"); valid=false; break; } // Check for a degenerate edge if (origin == destination) { printf(" An edge was specified that connected a vertex to itself\n"); valid=false; break; } // Check that no more than 2 faces are adjacent to the edge if (opposite and opposite->GetOpposite() ) { printf(" A non-manifold edge incident to more than 2 faces was found\n"); valid=false; break; } // Check that the edge is unique and oriented properly if (origin->GetEdge(destination)) { printf(" An edge connecting two vertices was specified more than once." " It's likely that an incident face was flipped\n"); valid=false; break; } } if (valid) { hmesh->NewFace(nv, fv, 0); } else { printf(" Skipped face %d\n", i); } fv+=nv; } hmesh->SetInterpolateBoundaryMethod(Hmesh::k_InterpolateBoundaryEdgeOnly); hmesh->Finish(); return hmesh; }
//------------------------------------------------------------------------------ static void createHbrMesh(Shape * shape, int maxlevel) { Stopwatch s; s.Start(); // create Hbr mesh using functions from hbr_utils Hmesh * hmesh = createMesh<Vertex>(shape->scheme, /*fvarwidth*/ 0); createVerticesWithPositions<Vertex>(shape, hmesh); createTopology<Vertex>(shape, hmesh, shape->scheme); s.Stop(); std::vector<Hface const *> coarseFaces, // list of Hbr coarse faces refinedFaces; // list of Hbr faces refined at maxlevel int nfaces = hmesh->GetNumFaces(); { // create control cage GL mesh coarseFaces.resize(nfaces); for (int i=0; i<nfaces; ++i) { coarseFaces[i] = hmesh->GetFace(i); } GLMesh::Options coarseOptions; coarseOptions.vertColorMode=GLMesh::VERTCOLOR_BY_SHARPNESS; coarseOptions.edgeColorMode=GLMesh::EDGECOLOR_BY_SHARPNESS; coarseOptions.faceColorMode=GLMesh::FACECOLOR_SOLID; g_base_glmesh.Initialize(coarseOptions, coarseFaces); g_base_glmesh.InitializeDeviceBuffers(); } { // create maxlevel refined GL mesh s.Start(); OpenSubdiv::Far::PatchTables const * patchTables = 0; if (g_Adaptive) { int maxvalence = RefineAdaptive(*hmesh, maxlevel, refinedFaces); patchTables = CreatePatchTables(*hmesh, maxvalence); patchTables->GetNumPatches(); delete patchTables; } else { RefineUniform(*hmesh, maxlevel, refinedFaces); } s.Stop(); //printf("Hbr time: %f ms\n", float(s.GetElapsed())*1000.0f); if (g_HbrDrawVertIDs) { createVertNumbers(refinedFaces); } // Hbr is a half-edge rep, so edges do not have unique IDs that // can be displayed if (g_HbrDrawEdgeSharpness) { createEdgeNumbers(refinedFaces); } if (g_HbrDrawFaceIDs) { createFaceNumbers(refinedFaces, /*ptex*/ false); } if (g_HbrDrawPtexIDs) { createFaceNumbers(refinedFaces, /*ptex*/ true); } GLMesh::Options refinedOptions; refinedOptions.vertColorMode=GLMesh::VERTCOLOR_BY_SHARPNESS; refinedOptions.edgeColorMode=GLMesh::EDGECOLOR_BY_SHARPNESS; refinedOptions.faceColorMode=GLMesh::FACECOLOR_SOLID; g_hbr_glmesh.Initialize(refinedOptions, refinedFaces); g_hbr_glmesh.SetDiffuseColor(1.0f,0.75f,0.9f, 1.0f); } g_hbr_glmesh.InitializeDeviceBuffers(); delete hmesh; }