From b781c6efd3c0ebedbb8c1e0139f2490e8a1dbc39 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Tue, 19 May 2015 19:17:50 -0700 Subject: [PATCH] Removed Hbr code from farViewer. The code in farViewer that was used to draw the Hbr representation of meshes is now gone. This code was mostly used as a way to compare against the Vtr implementation. However, we don't want this to serve as an example for others as the Hbr code is not meant to be instructive otherwise. --- examples/farViewer/CMakeLists.txt | 1 - examples/farViewer/farViewer.cpp | 309 ++----- examples/farViewer/hbr_refine.cpp | 1323 ----------------------------- examples/farViewer/hbr_refine.h | 116 --- 4 files changed, 52 insertions(+), 1697 deletions(-) delete mode 100644 examples/farViewer/hbr_refine.cpp delete mode 100644 examples/farViewer/hbr_refine.h diff --git a/examples/farViewer/CMakeLists.txt b/examples/farViewer/CMakeLists.txt index 0860c63d..785d4022 100644 --- a/examples/farViewer/CMakeLists.txt +++ b/examples/farViewer/CMakeLists.txt @@ -60,7 +60,6 @@ _add_glfw_executable(farViewer gl_fontutils.cpp gl_mesh.cpp face_texture.cpp - hbr_refine.cpp "${SHADER_FILES}" "${INC_FILES}" $ diff --git a/examples/farViewer/farViewer.cpp b/examples/farViewer/farViewer.cpp index 637c8c60..31208cbe 100644 --- a/examples/farViewer/farViewer.cpp +++ b/examples/farViewer/farViewer.cpp @@ -55,9 +55,6 @@ GLFWmonitor* g_primary=0; #include #include -#include - -#include "hbr_refine.h" #include "../common/stopwatch.h" #include "../common/simple_math.h" @@ -84,8 +81,7 @@ enum HudCheckBox { kHUD_CB_DISPLAY_CAGE_EDGES, kHUD_CB_ANIMATE_VERTICES, kHUD_CB_DISPLAY_PATCH_COLOR }; -enum DrawMode { kDRAW_NONE = 0, - kDRAW_VERTICES, +enum DrawMode { kDRAW_VERTICES, kDRAW_WIREFRAME, kDRAW_FACES }; @@ -101,12 +97,7 @@ int g_fullscreen = 0, int g_displayPatchColor = 1, g_drawCageEdges = 1, g_drawCageVertices = 0, - g_HbrDrawMode = kDRAW_WIREFRAME, - g_HbrDrawVertIDs = false, - g_HbrDrawEdgeSharpness = false, - g_HbrDrawFaceIDs = false, - g_HbrDrawPtexIDs = false, - g_FarDrawMode = kDRAW_NONE, + g_FarDrawMode = kDRAW_FACES, g_FarDrawVertIDs = false, g_FarDrawEdgeIDs = false, g_FarDrawFaceIDs = false, @@ -163,7 +154,6 @@ struct Transform { } g_transformData; static GLMesh g_base_glmesh, - g_hbr_glmesh, g_far_glmesh; @@ -172,200 +162,44 @@ static GLMesh g_base_glmesh, typedef OpenSubdiv::Far::TopologyRefiner FTopologyRefiner; typedef OpenSubdiv::Far::TopologyRefinerFactory FTopologyRefinerFactory; -//------------------------------------------------------------------------------ -// generate display IDs for Hbr faces -static void -createFaceNumbers(std::vector faces, bool doPtex=false) { - - static char buf[16]; - - for (int i=0; i<(int)faces.size(); ++i) { - - Hface const * f = faces[i]; - - Vertex center(0.0f, 0.0f, 0.0f); - - int nv = f->GetNumVertices(); - float weight = 1.0f / nv; - - for (int j=0; jGetVertex(j)->GetData(), weight); - } - - if (doPtex) { - snprintf(buf, 16, "%d", f->GetPtexIndex()); - } else { - snprintf(buf, 16, "%d", f->GetID()); - } - g_font->Print3D(center.GetPos(), buf, 2); - } -} //------------------------------------------------------------------------------ -// generate display IDs for Hbr edges -static void -createEdgeNumbers(std::vector faces) { +// Vertex class implementation +struct Vertex { - typedef std::map EdgeMap; - EdgeMap edgeMap; + Vertex() { /* _pos[0]=_pos[1]=_pos[2]=0.0f; */ } - typedef std::vector EdgeVec; - EdgeVec edgeVec; + Vertex( int /*i*/ ) { } - { // map half-edges into unique edge id's + Vertex( float x, float y, float z ) { _pos[0]=x; _pos[1]=y; _pos[2]=z; } - for (int i=0; i<(int)faces.size(); ++i) { - Hface const * f = faces[i]; - for (int j=0; jGetNumVertices(); ++j) { - Hhalfedge const * e = f->GetEdge(j); - if (e->IsBoundary() or (e->GetRightFace()->GetID()>f->GetID())) { - int id = (int)edgeMap.size(); - edgeMap[e] = id; - } - } - } - edgeVec.resize(edgeMap.size()); - for (EdgeMap::const_iterator it=edgeMap.begin(); it!=edgeMap.end(); ++it) { - edgeVec[it->second] = it->first; - } + Vertex( const Vertex & src ) { _pos[0]=src._pos[0]; _pos[1]=src._pos[1]; _pos[2]=src._pos[2]; } + + ~Vertex( ) { } + + void AddWithWeight(Vertex const & src, float weight) { + _pos[0]+=weight*src._pos[0]; + _pos[1]+=weight*src._pos[1]; + _pos[2]+=weight*src._pos[2]; } - static char buf[16]; - for (int i=0; i<(int)edgeVec.size(); ++i) { - - Hhalfedge const * e = edgeVec[i]; - - float sharpness = e->GetSharpness(); - if (sharpness>0.0f) { - - Vertex center(0.0f, 0.0f, 0.0f); - center.AddWithWeight(e->GetOrgVertex()->GetData(), 0.5f); - center.AddWithWeight(e->GetDestVertex()->GetData(), 0.5f); - - snprintf(buf, 16, "%g", sharpness); - g_font->Print3D(center.GetPos(), buf, std::min(8,(int)sharpness+4)); - } - } -} - -//------------------------------------------------------------------------------ -// generate display IDs for Hbr verts -static void -createVertNumbers(std::vector faces) { - - assert(not faces.empty()); - - static char buf[16]; - - std::vector verts(faces.size()*4, 0); - - for (int i=0; i<(int)faces.size(); ++i) { - - Hface const * f = faces[i]; - - int nv = f->GetNumVertices(); - for (int j=0; jGetVertex(j); - verts[v->GetID()] = v; - } + void AddWithWeight(Vertex const & src, float weight, float /* ds */, float /* dt */) { + _pos[0]+=weight*src._pos[0]; + _pos[1]+=weight*src._pos[1]; + _pos[2]+=weight*src._pos[2]; } - for (int i=0; i<(int)verts.size(); ++i) { + void AddVaryingWithWeight(Vertex const & , float) { } - if (verts[i]) { - snprintf(buf, 16, "%d", verts[i]->GetID()); - g_font->Print3D(verts[i]->GetData().GetPos(), buf, 1); - } - } -} + void Clear( void * =0 ) { _pos[0]=_pos[1]=_pos[2]=0.0f; } -//------------------------------------------------------------------------------ -static void -createHbrGLMesh(Shape * shape, int maxlevel) { + void SetPosition(float x, float y, float z) { _pos[0]=x; _pos[1]=y; _pos[2]=z; } - Stopwatch s; - s.Start(); + float const * GetPos() const { return _pos; } - // create Hbr mesh using functions from hbr_utils - Hmesh * hmesh = createMesh(shape->scheme, /*fvarwidth*/ 0); - - createVerticesWithPositions(shape, hmesh); - - createTopology(shape, hmesh, shape->scheme); - s.Stop(); - - std::vector 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; iGetFace(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->GetNumPatchesTotal(); - - 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; -} +private: + float _pos[3]; +}; //------------------------------------------------------------------------------ // generate display IDs for Far verts @@ -939,8 +773,6 @@ createMeshes(ShapeDesc const & desc, int maxlevel) { Shape * shape = Shape::parseObj(desc.data.c_str(), desc.scheme); - createHbrGLMesh(shape, maxlevel); - createFarGLMesh(shape, maxlevel); delete shape; } @@ -1046,33 +878,16 @@ display() { g_base_glmesh.Draw(GLMesh::COMP_EDGE, g_transformUB, g_lightingUB); } - // Hbr mesh - if (g_HbrDrawMode!=kDRAW_NONE) { - - GLMesh::Component comp=GLMesh::COMP_VERT; - switch (g_HbrDrawMode) { - case kDRAW_VERTICES : comp=GLMesh::COMP_VERT; break; - case kDRAW_WIREFRAME : comp=GLMesh::COMP_EDGE; break; - case kDRAW_FACES : comp=GLMesh::COMP_FACE; break; - default: - assert(0); - } - g_hbr_glmesh.Draw(comp, g_transformUB, g_lightingUB); - } - // Far mesh - if (g_FarDrawMode!=kDRAW_NONE) { - - GLMesh::Component comp=GLMesh::COMP_VERT; - switch (g_FarDrawMode) { - case kDRAW_VERTICES : comp=GLMesh::COMP_VERT; break; - case kDRAW_WIREFRAME : comp=GLMesh::COMP_EDGE; break; - case kDRAW_FACES : comp=GLMesh::COMP_FACE; break; - default: - assert(0); - } - g_far_glmesh.Draw(comp, g_transformUB, g_lightingUB); + GLMesh::Component comp=GLMesh::COMP_VERT; + switch (g_FarDrawMode) { + case kDRAW_VERTICES : comp=GLMesh::COMP_VERT; break; + case kDRAW_WIREFRAME : comp=GLMesh::COMP_EDGE; break; + case kDRAW_FACES : comp=GLMesh::COMP_FACE; break; + default: + assert(0); } + g_far_glmesh.Draw(comp, g_transformUB, g_lightingUB); if (g_Adaptive and g_FarDrawGregogyBasis) { gregoryWire.Draw(GLMesh::COMP_VERT, g_transformUB, g_lightingUB); @@ -1297,11 +1112,6 @@ callbackCheckBox(bool checked, int button) { } } -static void -callbackHbrDrawMode(int m) { - - g_HbrDrawMode = m; -} static void callbackFarDrawMode(int m) { @@ -1313,20 +1123,16 @@ static void callbackDrawIDs(bool checked, int button) { switch (button) { - case 0: g_HbrDrawVertIDs = checked; break; - case 1: g_HbrDrawFaceIDs = checked; break; - case 2: g_HbrDrawPtexIDs = checked; break; - case 3: g_HbrDrawEdgeSharpness = checked; break; - case 4: g_FarDrawVertIDs = checked; break; - case 5: g_FarDrawEdgeIDs = checked; break; - case 6: g_FarDrawFaceIDs = checked; break; - case 7: g_FarDrawPtexIDs = checked; break; - case 8: g_FarDrawEdgeSharpness = checked; break; - case 9: g_FarDrawGregogyBasis = checked; break; + case 0: g_FarDrawVertIDs = checked; break; + case 1: g_FarDrawEdgeIDs = checked; break; + case 2: g_FarDrawFaceIDs = checked; break; + case 3: g_FarDrawPtexIDs = checked; break; + case 4: g_FarDrawEdgeSharpness = checked; break; + case 5: g_FarDrawGregogyBasis = checked; break; - case 10: g_FarDrawFVarVerts = checked; break; - case 11: g_FarDrawFVarPatches = checked; break; + case 6: g_FarDrawFVarVerts = checked; break; + case 7: g_FarDrawFVarPatches = checked; break; default: break; } @@ -1393,29 +1199,18 @@ initHUD() { g_hud.AddCheckBox("Cage Verts (r)", g_drawCageVertices != 0, 10, 30, callbackCheckBox, kHUD_CB_DISPLAY_CAGE_VERTS, 'r'); - int pulldown = g_hud.AddPullDown("Hbr Draw Mode (h)", 10, 75, 250, callbackHbrDrawMode, 'h'); - g_hud.AddPullDownButton(pulldown, "None", 0, g_HbrDrawMode==kDRAW_NONE); - g_hud.AddPullDownButton(pulldown, "Vertices", 1, g_HbrDrawMode==kDRAW_VERTICES); - g_hud.AddPullDownButton(pulldown, "Wireframe", 2, g_HbrDrawMode==kDRAW_WIREFRAME); - g_hud.AddPullDownButton(pulldown, "Faces", 3, g_HbrDrawMode==kDRAW_FACES); - g_hud.AddCheckBox("Vert IDs", g_HbrDrawVertIDs!=0, 10, 95, callbackDrawIDs, 0); - g_hud.AddCheckBox("Face IDs", g_HbrDrawFaceIDs!=0, 10, 115, callbackDrawIDs, 1); - g_hud.AddCheckBox("Ptex IDs", g_HbrDrawPtexIDs!=0, 10, 135, callbackDrawIDs, 2); - g_hud.AddCheckBox("Edge Sharp", g_HbrDrawEdgeSharpness!=0, 10, 155, callbackDrawIDs, 3); + int pulldown = g_hud.AddPullDown("Far Draw Mode (f)", 10, 195, 250, callbackFarDrawMode, 'f'); + g_hud.AddPullDownButton(pulldown, "Vertices", 0, g_FarDrawMode==kDRAW_VERTICES); + g_hud.AddPullDownButton(pulldown, "Wireframe", 1, g_FarDrawMode==kDRAW_WIREFRAME); + g_hud.AddPullDownButton(pulldown, "Faces", 2, g_FarDrawMode==kDRAW_FACES); - pulldown = g_hud.AddPullDown("Far Draw Mode (f)", 10, 195, 250, callbackFarDrawMode, 'f'); - g_hud.AddPullDownButton(pulldown, "None", 0, g_FarDrawMode==kDRAW_NONE); - g_hud.AddPullDownButton(pulldown, "Vertices", 1, g_FarDrawMode==kDRAW_VERTICES); - g_hud.AddPullDownButton(pulldown, "Wireframe", 2, g_FarDrawMode==kDRAW_WIREFRAME); - g_hud.AddPullDownButton(pulldown, "Faces", 3, g_FarDrawMode==kDRAW_FACES); - - g_hud.AddCheckBox("Vert IDs", g_FarDrawVertIDs!=0, 10, 215, callbackDrawIDs, 4); - g_hud.AddCheckBox("Edge IDs", g_FarDrawEdgeIDs!=0, 10, 235, callbackDrawIDs, 5); - g_hud.AddCheckBox("Face IDs", g_FarDrawFaceIDs!=0, 10, 255, callbackDrawIDs, 6); - g_hud.AddCheckBox("Ptex IDs", g_FarDrawPtexIDs!=0, 10, 275, callbackDrawIDs, 7); - g_hud.AddCheckBox("Edge Sharp", g_FarDrawEdgeSharpness!=0, 10, 295, callbackDrawIDs, 8); - g_hud.AddCheckBox("Gregory Basis", g_FarDrawGregogyBasis!=0, 10, 315, callbackDrawIDs, 9); + g_hud.AddCheckBox("Vert IDs", g_FarDrawVertIDs!=0, 10, 215, callbackDrawIDs, 0); + g_hud.AddCheckBox("Edge IDs", g_FarDrawEdgeIDs!=0, 10, 235, callbackDrawIDs, 1); + g_hud.AddCheckBox("Face IDs", g_FarDrawFaceIDs!=0, 10, 255, callbackDrawIDs, 2); + g_hud.AddCheckBox("Ptex IDs", g_FarDrawPtexIDs!=0, 10, 275, callbackDrawIDs, 3); + g_hud.AddCheckBox("Edge Sharp", g_FarDrawEdgeSharpness!=0, 10, 295, callbackDrawIDs, 4); + g_hud.AddCheckBox("Gregory Basis", g_FarDrawGregogyBasis!=0, 10, 315, callbackDrawIDs, 5); g_hud.AddCheckBox("Use Stencils (s)", g_useStencils!=0, 10, 350, callbackUseStencils, 0, 's'); g_hud.AddCheckBox("Adaptive (`)", g_Adaptive!=0, 10, 370, callbackAdaptive, 0, '`'); diff --git a/examples/farViewer/hbr_refine.cpp b/examples/farViewer/hbr_refine.cpp deleted file mode 100644 index c6168386..00000000 --- a/examples/farViewer/hbr_refine.cpp +++ /dev/null @@ -1,1323 +0,0 @@ -// -// Copyright 2013 Pixar -// -// Licensed under the Apache License, Version 2.0 (the "Apache License") -// with the following modification; you may not use this file except in -// compliance with the Apache License and the following modification to it: -// Section 6. Trademarks. is deleted and replaced with: -// -// 6. Trademarks. This License does not grant permission to use the trade -// names, trademarks, service marks, or product names of the Licensor -// and its affiliates, except as required to comply with Section 4(c) of -// the License and to reproduce the content of the NOTICE file. -// -// You may obtain a copy of the Apache License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the Apache License with the above modification is -// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the Apache License for the specific -// language governing permissions and limitations under the Apache License. -// - -#include "hbr_refine.h" - -#include -#include - -// !!! WARNING !!! -// -// The Far::PatchTablesFactory code duplicated in this file is for debugging -// puproses only ! -// -// Do *NOT* use, duplicate or rely on this code. - -//------------------------------------------------------------------------------ -// -// refine the Hbr mesh uniformly -// -void -RefineUniform(Hmesh & mesh, int maxlevel, - std::vector & refinedFaces) { - - int nfaces = mesh.GetNumFaces(); - - for (int level=0, firstface=0; level<=maxlevel; ++level ) { - - if (level==maxlevel) { - - refinedFaces.resize(nfaces-firstface); - for (int i=firstface, ofs=0; iGetDepth()==level); - if (not f->IsHole()) { - f->Refine(); - } - } - } - - // Hbr allocates faces sequentially, skip faces that have - // already been refined. - firstface = nfaces; - nfaces = mesh.GetNumFaces(); - } -} - - -//------------------------------------------------------------------------------ - -struct VertCompare { - bool operator() (Hvertex const * v1, Hvertex const * v2 ) const { - //return v1->GetID() < v2->GetID(); - return (void*)(v1) < (void*)(v2); - } -}; - -//------------------------------------------------------------------------------ -// True if the vertex can be incorporated into a B-spline patch -bool -vertexIsBSpline(Hvertex * v, bool next) { - - int valence = v->GetValence(); - - // Boundary & corner vertices - if (v->OnBoundary()) { - if (valence==2) { - // corner vertex - - Hface * f = v->GetFace(); - - // the vertex may not need isolation depending on boundary - // interpolation rule (sharp vs. rounded corner) - Hmesh::InterpolateBoundaryMethod method = - f->GetMesh()->GetInterpolateBoundaryMethod(); - - if (method==Hmesh::k_InterpolateBoundaryEdgeAndCorner) { - if (not next) { - // if we are checking coarse vertices (next==false), - // count the number of corners in the face, because we - // can only have 1 corner vertex in a corner patch. - int nsharpboundaries=0; - for (int i=0; iGetNumVertices(); ++i) { - Hhalfedge * e = f->GetEdge(i); - if (e->IsBoundary() and - e->GetSharpness()==Hhalfedge::k_InfinitelySharp) { - ++nsharpboundaries; - } - } - return nsharpboundaries < 3 ? true: false; - } else - return true; - } else - return false; - } else if (valence>3) { - // extraordinary boundary vertex (high valence) - return false; - } - // regular boundary vertices have valence 3 - return true; - } - - // Extraordinary or creased vertices that aren't corner / boundaries - if (v->IsExtraordinary() or v->IsSharp(next)) - return false; - - return true; -} - -//------------------------------------------------------------------------------ -void -refineVertexNeighbors(Hvertex * v) { - - assert(v); - - Hhalfedge * start = v->GetIncidentEdge(), - * next=start; - do { - - Hface * lft = next->GetLeftFace(), - * rgt = next->GetRightFace(); - - if (not ((lft and lft->IsHole()) and - (rgt and rgt->IsHole()) ) ) { - - if (rgt) - rgt->_adaptiveFlags.isTagged=true; - - if (lft) - lft->_adaptiveFlags.isTagged=true; - - Hhalfedge * istart = next, - * inext = istart; - do { - if (not inext->IsInsideHole() ) - inext->GetOrgVertex()->Refine(); - inext = inext->GetNext(); - } while (istart != inext); - } - next = v->GetNextEdge( next ); - } while (next and next!=start); -} - - -//------------------------------------------------------------------------------ -// -// refine the Hbr mesh adaptively -// -int -RefineAdaptive(Hmesh & mesh, int maxlevel, - std::vector & refinedFaces) { - - int ncoarsefaces = mesh.GetNumCoarseFaces(), - ncoarseverts = mesh.GetNumVertices(), - maxValence=0; - - // First pass : tag coarse vertices & faces that need refinement - - typedef std::set VertSet; - VertSet verts, nextverts; - - for (int i=0; iIsConnected()) { - continue; - } - - // Tag non-BSpline vertices for refinement - if (not vertexIsBSpline(v, false)) { - v->_adaptiveFlags.isTagged=true; - nextverts.insert(v); - } - } - - for (int i=0; iIsHole()) - continue; - - bool extraordinary = mesh.GetSubdivision()->FaceIsExtraordinary(&mesh,f); - - int nv = f->GetNumVertices(); - for (int j=0; jGetEdge(j); - assert(e); - - // Tag sharp edges for refinement - if (e->IsSharp(true) and (not e->IsBoundary())) { - nextverts.insert(e->GetOrgVertex()); - nextverts.insert(e->GetDestVertex()); - - e->GetOrgVertex()->_adaptiveFlags.isTagged=true; - e->GetDestVertex()->_adaptiveFlags.isTagged=true; - } - - // Tag extraordinary (non-quad) faces for refinement - if (extraordinary or f->HasVertexEdits()) { - Hvertex * v = f->GetVertex(j); - v->_adaptiveFlags.isTagged=true; - nextverts.insert(v); - } - - // Quad-faces with 2 non-consecutive boundaries need to be flagged - // for refinement as boundary patches. - // - // o ........ o ........ o ........ o - // . | | . ... boundary edge - // . | needs | . - // . | flag | . --- regular edge - // . | | . - // o ........ o ........ o ........ o - // - if ( e->IsBoundary() and (not f->_adaptiveFlags.isTagged) and nv==4 ) { - - if (e->GetPrev() and (not e->GetPrev()->IsBoundary()) and - e->GetNext() and (not e->GetNext()->IsBoundary()) and - e->GetNext() and e->GetNext()->GetNext() and e->GetNext()->GetNext()->IsBoundary()) { - - // Tag the face so that we don't check for this again - f->_adaptiveFlags.isTagged=true; - - // Tag all 4 vertices of the face to make sure 4 boundary - // sub-patches are generated - for (int k=0; k<4; ++k) { - Hvertex * v = f->GetVertex(k); - v->_adaptiveFlags.isTagged=true; - nextverts.insert(v); - } - } - } - } - maxValence = std::max(maxValence, nv); - } - - - // Second pass : refine adaptively around singularities - for (int level=0; level0) - v->_adaptiveFlags.isTagged=true; - else - v->_adaptiveFlags.wasTagged=true; - - refineVertexNeighbors(v); - - // Tag non-BSpline vertices for refinement - if (not vertexIsBSpline(v, true)) - nextverts.insert(v->Subdivide()); - - // Refine edges with creases or edits - int valence = v->GetValence(); - maxValence = std::max(maxValence, valence); - - Hhalfedge * e = v->GetIncidentEdge(); - for (int j=0; jHasChild()) and e->IsSharp(false) and (not e->IsBoundary())) { - - if (not e->IsInsideHole()) { - nextverts.insert( e->Subdivide() ); - nextverts.insert( e->GetOrgVertex()->Subdivide() ); - nextverts.insert( e->GetDestVertex()->Subdivide() ); - } - } - Hhalfedge * next = v->GetNextEdge(e); - e = next ? next : e->GetPrev(); - } - - // Flag verts with hierarchical edits for neighbor refinement at the next level - Hvertex * childvert = v->Subdivide(); - Hhalfedge * childedge = childvert->GetIncidentEdge(); - assert( childvert->GetValence()==valence); - for (int j=0; jGetFace(); - if (f->HasVertexEdits()) { - int nv = f->GetNumVertices(); - for (int k=0; kGetVertex(k) ); - } - if ((childedge = childvert->GetNextEdge(childedge)) == NULL) - break; - } - } - - // Add coarse verts from extraordinary faces - if (level==0) { - for (int i=0; iIsCoarse()); - - if (mesh.GetSubdivision()->FaceIsExtraordinary(&mesh,f)) - nextverts.insert( f->Subdivide() ); - } - } - } - - int nfaces = mesh.GetNumFaces(); - - // First pass : identify transition / watertight-critical - for (int i=0; i_adaptiveFlags.isTagged and (not f->IsHole())) { - Hvertex * v = f->Subdivide(); - assert(v); - v->_adaptiveFlags.wasTagged=true; - } - - int nv = f->GetNumVertices(); - for (int j=0; jIsCoarse()) - f->GetVertex(j)->_adaptiveFlags.wasTagged=true; - - Hhalfedge * e = f->GetEdge(j); - - // Flag transition edge that require a triangulated transition - if (f->_adaptiveFlags.isTagged) { - e->_adaptiveFlags.isTriangleHead=true; - - // Both half-edges need to be tagged if an opposite exists - if (e->GetOpposite()) - e->GetOpposite()->_adaptiveFlags.isTriangleHead=true; - } - - Hface * left = e->GetLeftFace(), - * right = e->GetRightFace(); - - if (not (left and right)) - continue; - - // a tagged edge w/ no children is inside a hole - if (e->HasChild() and (left->_adaptiveFlags.isTagged ^ right->_adaptiveFlags.isTagged)) { - - e->_adaptiveFlags.isTransition = true; - - Hvertex * child = e->Subdivide(); - assert(child); - - // These edges will require extra rows of CVs to maintain water-tightness - // Note : vertices inside holes have no children - if (e->GetOrgVertex()->HasChild()) { - Hhalfedge * org = child->GetEdge(e->GetOrgVertex()->Subdivide()); - if (org) - org->_adaptiveFlags.isWatertightCritical=true; - } - - if (e->GetDestVertex()->HasChild()) { - Hhalfedge * dst = child->GetEdge(e->GetDestVertex()->Subdivide()); - if (dst) - dst->_adaptiveFlags.isWatertightCritical=true; - } - } - } - } - - refinedFaces.reserve(nfaces - ncoarsefaces); - for (int i=ncoarsefaces; i_adaptiveFlags.isTagged) { - continue; - } - - refinedFaces.push_back(mesh.GetFace(i)); - } - - return maxValence; -} - -namespace OpenSubdiv { -namespace OPENSUBDIV_VERSION { -namespace Far { - -// FIXME: -// XXX: we need this class named PatchTablesFactory because of friend access. -class PatchTablesFactory { - -public: - - static Far::PatchTables const * Create(Hmesh & mesh, int maxvalence); - -private: - - typedef Far::PatchDescriptor Descriptor; - - // Returns true if one of v's neighboring faces has vertices carrying the tag "wasTagged" - static bool vertexHasTaggedNeighbors(Hvertex * v); - - // Returns the rotation for a boundary patch - static unsigned char computeBoundaryPatchRotation( Hface * f ); - - // Returns the rotation for a corner patch - static unsigned char computeCornerPatchRotation( Hface * f ); - - // Populates the patch parametrization descriptor 'coord' for the given face - // returns a pointer to the next descriptor - static OpenSubdiv::Far::PatchParam * computePatchParam(Hface const *f, OpenSubdiv::Far::PatchParam *coord); - - // Populates an array of indices with the "one-ring" vertices for the given face - static Far::Index * getOneRing( Hface const * f, int ringsize, Far::Index const * remap, Far::Index * result ); - - // Populates the Gregory patch quad offsets table - static void getQuadOffsets( Hface const * f, unsigned int * result ); - - // The number of patches in the mesh - static int getNumPatches( Far::PatchTables::PatchArrayVector const & parrays ); - - // Reserves tables based on the contents of the PatchArrayVector - static void allocateTables( Far::PatchTables * tables, int nlevels, int fvarwidth ); - - // A convenience container for the different types of feature adaptive patches - template struct PatchTypes { - - TYPE R, // regular patch - G, // gregory patch - GB, // gregory boundary patch - GP; // gregory basis - - PatchTypes() { memset(this, 0, sizeof(PatchTypes)); } - - // Returns the number of patches based on the patch type in the descriptor - TYPE & getValue( Descriptor desc ); - - // Counts the number of arrays required to store each type of patch used - // in the primitive - int getNumPatchArrays() const; - }; - - typedef PatchTypes ParamPointers; - typedef PatchTypes CVPointers; - typedef PatchTypes FVarPointers; - typedef PatchTypes Counter; - -}; - -//------------------------------------------------------------------------------ -template TYPE & -Far::PatchTablesFactory::PatchTypes::getValue( Far::PatchDescriptor desc ) { - - switch (desc.GetType()) { - case Far::PatchDescriptor::REGULAR : return R; - case Far::PatchDescriptor::GREGORY : return G; - case Far::PatchDescriptor::GREGORY_BOUNDARY : return GB; - case Far::PatchDescriptor::GREGORY_BASIS : return GP; - default : assert(0); - } - // can't be reached (suppress compiler warning) - return R; -} - -template int -Far::PatchTablesFactory::PatchTypes::getNumPatchArrays() const { - - int result=0; - if (R) ++result; - if (G) ++result; - if (GB) ++result; - if (GP) ++result; - - return result; -} - -//------------------------------------------------------------------------------ -// True if the surrounding faces are "tagged" (unsupported feature : watertight -// critical patches) -bool -Far::PatchTablesFactory::vertexHasTaggedNeighbors(Hvertex * v) { - - assert(v); - - Hhalfedge * start = v->GetIncidentEdge(), - * next=start; - do { - Hface * right = next->GetRightFace(), - * left = next->GetLeftFace(); - - if (right and (not right->hasTaggedVertices())) - return true; - - if (left and (not left->hasTaggedVertices())) - return true; - - next = v->GetNextEdge(next); - - } while (next and next!=start); - return false; -} - -// Returns a rotation index for boundary patches (range [0-3]) -unsigned char -Far::PatchTablesFactory::computeBoundaryPatchRotation( Hface * f ) { - unsigned char rot=0; - for (unsigned char i=0; i<4;++i) { - if (f->GetVertex(i)->OnBoundary() and - f->GetVertex((i+1)%4)->OnBoundary()) - break; - ++rot; - } - return rot; -} - -// Returns a rotation index for corner patches (range [0-3]) -unsigned char -Far::PatchTablesFactory::computeCornerPatchRotation( Hface * f ) { - unsigned char rot=0; - for (unsigned char i=0; i<4; ++i) { - if (not f->GetVertex((i+3)%4)->OnBoundary()) - break; - ++rot; - } - return rot; -} -/* -int -Far::PatchTablesFactory::getNumPatches( Far::PatchTables::PatchArrayVector const & parrays ) { - - int result=0; - for (int i=0; i<(int)parrays.size(); ++i) { - result += parrays[i].GetNumPatches(); - } - - return result; -} -*/ -//------------------------------------------------------------------------------ -void -Far::PatchTablesFactory::allocateTables( Far::PatchTables * tables, int /* nlevels */, int fvarwidth ) { - - int nverts = 0, npatches = 0; - for (int i=0; iGetNumPatchArrays(); ++i) { - npatches += tables->GetNumPatches(i); - nverts += tables->GetNumControlVertices(i); - } - - if (nverts==0 or npatches==0) - return; - - tables->_patchVerts.resize( nverts ); - - tables->_paramTable.resize( npatches ); - - if (fvarwidth>0) { - //Far::PatchTables::PatchArrayVector const & parrays = tables->GetPatchArrayVector(); - //int nfvarverts = 0; - //for (int i=0; i<(int)parrays.size(); ++i) { - // nfvarverts += parrays[i].GetNumPatches() * - // (parrays[i].GetDescriptor().GetType() == Far::PatchTables::TRIANGLES ? 3 : 4); - //} - - //tables->_fvarData._data.resize( nfvarverts * fvarwidth ); - - //if (nlevels >1) { - // tables->_fvarData._offsets.resize( nlevels ); - //} - } -} - -//------------------------------------------------------------------------------ -Far::PatchTables const * -Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) { - - int nfaces = mesh.GetNumFaces(); - - Counter patchCtr; // counters for full and transition patches - - // Second pass : count boundaries / identify transition constellation - for (int i=0; iFaceIsExtraordinary(&mesh,f)) - continue; - - if (f->IsHole()) - continue; - - bool isTagged=0, wasTagged=0, isConnected=0, isWatertightCritical=0, isExtraordinary=0; - int triangleHeads=0, boundaryVerts=0; - - int nv = f->GetNumVertices(); - for (int j=0; jGetVertex(j); - - if (v->OnBoundary()) { - boundaryVerts++; - - // Boundary vertices with valence higher than 3 aren't Full Boundary - // patches, they are Gregory Boundary patches. - if (v->IsSingular() or v->GetValence()>3) - isExtraordinary=true; - - } else if (v->IsExtraordinary()) - isExtraordinary=true; - - if (f->GetParent() and (not isWatertightCritical)) - isWatertightCritical = vertexHasTaggedNeighbors(v); - - if (v->_adaptiveFlags.isTagged) - isTagged=1; - - if (v->_adaptiveFlags.wasTagged) - wasTagged=1; - - // Count the number of triangle heads to find which transition - // pattern to use. - Hhalfedge * e = f->GetEdge(j); - if (e->_adaptiveFlags.isTriangleHead) { - - ++triangleHeads; - if (f->GetEdge((j+1)%4)->_adaptiveFlags.isTriangleHead) - isConnected=true; - } - } - - f->_adaptiveFlags.bverts=boundaryVerts; - f->_adaptiveFlags.isCritical=isWatertightCritical; - - // Regular Boundary Patch - if (wasTagged) - // XXXX manuelk - need to implement end patches - f->_adaptiveFlags.patchType = Hface::kEnd; - - if (f->_adaptiveFlags.isTagged) - continue; - - assert(f->_adaptiveFlags.rots==0 and nv==4); - - if (not isTagged and wasTagged) { - - if (triangleHeads==0) { - - if (not isExtraordinary and boundaryVerts!=1) { - - // Full Patches - f->_adaptiveFlags.patchType = Hface::kFull; - - switch (boundaryVerts) { - - case 0 : { // Regular patch - patchCtr.R++; - } break; - - case 2 : { // Boundary patch - f->_adaptiveFlags.rots=computeBoundaryPatchRotation(f); - patchCtr.R++; - } break; - - case 3 : { // Corner patch - f->_adaptiveFlags.rots=computeCornerPatchRotation(f); - patchCtr.R++; - } break; - - default : break; - } - } else { - - // Default to Gregory Patch - f->_adaptiveFlags.patchType = Hface::kGregory; - - switch (boundaryVerts) { - - case 0 : { // Regular Gregory patch - patchCtr.G++; - } break; - - - default : { // Boundary Gregory patch - patchCtr.GB++; - } break; - } - } - - } else { - - // Transition Patch - - // Resolve transition constellation : 5 types (see p.5 fig. 7) - switch (triangleHeads) { - - case 1 : { for (unsigned char j=0; j<4; ++j) { - if (f->GetEdge(j)->IsTriangleHead()) - break; - f->_adaptiveFlags.rots++; - } - f->_adaptiveFlags.transitionType = Hface::kTransition0; - } break; - - case 2 : { for (unsigned char j=0; j<4; ++j) { - if (isConnected) { - if (f->GetEdge(j)->IsTriangleHead() and - f->GetEdge((j+3)%4)->IsTriangleHead()) - break; - } else { - if (f->GetEdge(j)->IsTriangleHead()) - break; - } - f->_adaptiveFlags.rots++; - } - - if (isConnected) - f->_adaptiveFlags.transitionType = Hface::kTransition1; - else - f->_adaptiveFlags.transitionType = Hface::kTransition4; - } break; - - case 3 : { for (unsigned char j=0; j<4; ++j) { - if (not f->GetEdge(j)->IsTriangleHead()) - break; - f->_adaptiveFlags.rots++; - } - f->_adaptiveFlags.transitionType = Hface::kTransition2; - } break; - - case 4 : f->_adaptiveFlags.transitionType = Hface::kTransition3; - break; - - default: break; - } - - int pattern = f->_adaptiveFlags.transitionType; - assert(pattern>=0); - - // Correct rotations for corners & boundaries - if (not isExtraordinary and boundaryVerts!=1) { - - switch (boundaryVerts) { - - case 0 : { // regular patch - patchCtr.R++; - } break; - - case 2 : { // boundary patch - unsigned char rot=computeBoundaryPatchRotation(f); - - f->_adaptiveFlags.brots=(4-f->_adaptiveFlags.rots+rot)%4; - - f->_adaptiveFlags.rots=rot; // override the transition rotation - - patchCtr.R++; - } break; - - case 3 : { // corner patch - unsigned char rot=computeCornerPatchRotation(f); - - f->_adaptiveFlags.brots=(4-f->_adaptiveFlags.rots+rot)%4; - - f->_adaptiveFlags.rots=rot; // override the transition rotation - - patchCtr.R++; - } break; - - default : assert(0); break; - } - } else { - // Use Gregory Patch transition ? - } - } - } - } - - - static const Far::Index remapRegular [16] = {5,6,10,9,4,0,1,2,3,7,11,15,14,13,12,8}; - static const Far::Index remapRegularBoundary[16] = {5,6,10,9,4,7,11,15,14,13,12,8,0,1,2,3}; - static const Far::Index remapRegularCorner [16] = {5,6,10,9,7,11,15,14,13,12,8,4,0,1,2,3}; - - int fvarwidth=0; - - Far::PatchTables * result = new Far::PatchTables(maxvalence); - - // Populate the patch array descriptors - result->reservePatchArrays(patchCtr.getNumPatchArrays()); - - typedef Far::ConstPatchDescriptorArray DescArray; - - DescArray const & catmarkDescs = Far::PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::SCHEME_CATMARK); - - int voffset=0, poffset=0, qoffset=0; - for (DescArray::const_iterator it=catmarkDescs.begin(); it!=catmarkDescs.end(); ++it) { - result->pushPatchArray(*it, patchCtr.getValue(*it), &voffset, &poffset, &qoffset ); - } - - //result->_fvarData._fvarWidth = fvarwidth; - result->_numPtexFaces = 0; - - // Allocate various tables - allocateTables( result, 0, fvarwidth ); - - if ((patchCtr.G > 0) or (patchCtr.GB > 0)) { // Quad-offsets tables (for Gregory patches) - result->_quadOffsetsTable.resize( patchCtr.G*4 + patchCtr.GB*4 ); - } - - // Setup convenience pointers at the beginning of each patch array for each - // table (patches, ptex, fvar) - CVPointers iptrs; - ParamPointers pptrs; - FVarPointers fptrs; - - for (DescArray::const_iterator it=catmarkDescs.begin(); it!=catmarkDescs.end(); ++it) { - - Index arrayIndex = result->findPatchArray(*it); - if (arrayIndex==Vtr::INDEX_INVALID) { - continue; - } - - iptrs.getValue( *it ) = result->getPatchArrayVertices(arrayIndex).begin(); - pptrs.getValue( *it ) = result->getPatchParams(arrayIndex).begin(); - } - - unsigned int * quad_G_C0_P = patchCtr.G>0 ? &result->_quadOffsetsTable[0] : 0, - * quad_G_C1_P = patchCtr.GB>0 ? &result->_quadOffsetsTable[patchCtr.G*4] : 0; - - // Populate patch index tables with vertex indices - for (int i=0; iisTransitionPatch() ) { - - // Full / End patches - - if (f->_adaptiveFlags.patchType==Hface::kFull) { - if (not f->_adaptiveFlags.isExtraordinary and f->_adaptiveFlags.bverts!=1) { - - switch (f->_adaptiveFlags.bverts) { - case 0 : { // Regular Patch (16 CVs) - iptrs.R = getOneRing(f, 16, remapRegular, iptrs.R); - pptrs.R = computePatchParam(f, pptrs.R); - //fptrs.R[pattern] = computeFVarData(f, fvarwidth, fptrs.R[0], /*isAdaptive=*/true); - } break; - - case 2 : { // Boundary Patch (12 CVs) - f->_adaptiveFlags.brots = (f->_adaptiveFlags.rots+1)%4; - iptrs.R = getOneRing(f, 12, remapRegularBoundary, iptrs.R); - pptrs.R = computePatchParam(f, pptrs.R); - //fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[0][0], /*isAdaptive=*/true); - } break; - - case 3 : { // Corner Patch (9 CVs) - f->_adaptiveFlags.brots = (f->_adaptiveFlags.rots+1)%4; - iptrs.R = getOneRing(f, 9, remapRegularCorner, iptrs.R); - pptrs.R = computePatchParam(f, pptrs.R); - //fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[0][0], /*isAdaptive=*/true); - } break; - - default : assert(0); - } - } - } else if (f->_adaptiveFlags.patchType==Hface::kGregory) { - - if (f->_adaptiveFlags.bverts==0) { - - // Gregory Regular Patch (4 CVs + quad-offsets / valence tables) - for (int j=0; j<4; ++j) - iptrs.G[j] = f->GetVertex(j)->GetID(); - iptrs.G+=4; - getQuadOffsets(f, quad_G_C0_P); - quad_G_C0_P += 4; - pptrs.G = computePatchParam(f, pptrs.G); - //fptrs.G = computeFVarData(f, fvarwidth, fptrs.G, /*isAdaptive=*/true); - } else { - - // Gregory Boundary Patch (4 CVs + quad-offsets / valence tables) - for (int j=0; j<4; ++j) - iptrs.GB[j] = f->GetVertex(j)->GetID(); - iptrs.GB+=4; - getQuadOffsets(f, quad_G_C1_P); - quad_G_C1_P += 4; - pptrs.GB = computePatchParam(f, pptrs.GB); - //fptrs.GB = computeFVarData(f, fvarwidth, fptrs.GB, /*isAdaptive=*/true); - } - } else { - // XXXX manuelk - end patches here - } - } else { - - // Transition patches - - int pattern = f->_adaptiveFlags.transitionType; - assert( pattern>=Hface::kTransition0 and pattern<=Hface::kTransition4 ); - ++pattern; // TransitionPattern begin with NON_TRANSITION - - if (not f->_adaptiveFlags.isExtraordinary and f->_adaptiveFlags.bverts!=1) { - - switch (f->_adaptiveFlags.bverts) { - case 0 : { // Regular Transition Patch (16 CVs) - iptrs.R = getOneRing(f, 16, remapRegular, iptrs.R); - pptrs.R = computePatchParam(f, pptrs.R); - //fptrs.R[pattern] = computeFVarData(f, fvarwidth, fptrs.R[pattern], /*isAdaptive=*/true); - } break; - - case 2 : { // Boundary Transition Patch (12 CVs) - //unsigned rot = f->_adaptiveFlags.brots; - iptrs.R = getOneRing(f, 12, remapRegularBoundary, iptrs.R); - pptrs.R = computePatchParam(f, pptrs.R); - //fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[pattern][rot], /*isAdaptive=*/true); - } break; - - case 3 : { // Corner Transition Patch (9 CVs) - //unsigned rot = f->_adaptiveFlags.brots; - iptrs.R = getOneRing(f, 9, remapRegularCorner, iptrs.R); - pptrs.R = computePatchParam(f, pptrs.R); - //fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[pattern][rot], /*isAdaptive=*/true); - } break; - } - } else - // No transition Gregory patches - assert(false); - } - } - - // Build Gregory patches vertex valence indices table - if ((patchCtr.G > 0) or (patchCtr.GB > 0)) { - - // MAX_VALENCE is a property of hardware shaders and needs to be matched in OSD - const int perVertexValenceSize = 2*maxvalence + 1; - - const int nverts = mesh.GetNumVertices(); - - Far::PatchTables::VertexValenceTable & table = result->_vertexValenceTable; - table.resize(nverts * perVertexValenceSize); - - class GatherNeighborsOperator : public OpenSubdiv::HbrVertexOperator { - public: - Hvertex * center; - Far::PatchTables::VertexValenceTable & table; - int offset, valence; - - GatherNeighborsOperator(Far::PatchTables::VertexValenceTable & itable, int ioffset, Hvertex * v) : - center(v), table(itable), offset(ioffset), valence(0) { } - - ~GatherNeighborsOperator() { } - - // Operator iterates over neighbor vertices of v and accumulates - // pairs of indices the neighbor and diagonal vertices - // - // Regular case - // Boundary case - // o ------- o D3 o - // D0 N0 | | - // | | o ------- o D2 o - // | | D0 N0 | | - // | | | | - // o ------- o ------- o | | - // N1 | V | N3 | | - // | | o ------- o ------- o - // | | N1 V N2 - // | | - // o o ------- o - // D1 N2 D2 - // - virtual void operator() (Hvertex &v) { - - table[offset++] = v.GetID(); - - Hvertex * diagonal=&v; - - Hhalfedge * e = center->GetEdge(&v); - if ( e ) { - // If v is on a boundary, there may not be a diagonal vertex - diagonal = e->GetNext()->GetDestVertex(); - } - //else { - // diagonal = v.GetQEONext( center ); - //} - - table[offset++] = diagonal->GetID(); - - ++valence; - } - }; - - for (int i=0; iGetID(); - int offset = outputVertexID * perVertexValenceSize; - - // feature adaptive refinement can generate un-connected face-vertices - // that have a valence of 0 - if (not v->IsConnected()) { - //assert( v->GetParentFace() ); - table[offset] = 0; - continue; - } - - // "offset+1" : the first table entry is the vertex valence, which - // is gathered by the operator (see note below) - GatherNeighborsOperator op( table, offset+1, v ); - v->ApplyOperatorSurroundingVertices( op ); - - // Valence sign bit used to mark boundary vertices - table[offset] = v->OnBoundary() ? -op.valence : op.valence; - - // Note : some topologies can cause v to be singular at certain - // levels of adaptive refinement, which prevents us from using - // the GetValence() function. Fortunately, the GatherNeighbors - // operator above just performed a similar traversal, so it is - // very convenient to use it to accumulate the actionable valence. - } - } else { - result->_vertexValenceTable.clear(); - } - - return result; -} - -//------------------------------------------------------------------------------ -// The One Ring vertices to rule them all ! -Far::Index * -Far::PatchTablesFactory::getOneRing(Hface const * f, - int ringsize, Far::Index const * remap, Far::Index * result) { - - assert( f and f->GetNumVertices()==4 and ringsize >=4 ); - - int idx=0; - - for (unsigned char i=0; i<4; ++i) { - result[remap[idx++ % ringsize]] = - f->GetVertex( (i+f->_adaptiveFlags.rots)%4 )->GetID(); - } - - if (ringsize==16) { - - // Regular case - // - // | | | | - // | 4 | 15 | 14 | 13 - // ---- o ---- o ---- o ---- o ---- - // | | | | - // | 5 | 0 | 3 | 12 - // ---- o ---- o ---- o ---- o ---- - // | | | | - // | 6 | 1 | 2 | 11 - // ---- o ---- o ---- o ---- o ---- - // | | | | - // | 7 | 8 | 9 | 10 - // ---- o ---- o ---- o ---- o ---- - // | | | | - // | | | | - - for (int i=0; i<4; ++i) { - int rot = i+f->_adaptiveFlags.rots; - Hvertex * v0 = f->GetVertex( rot % 4 ), - * v1 = f->GetVertex( (rot+1) % 4 ); - - Hhalfedge * e = - v0->GetNextEdge( v0->GetNextEdge( v0->GetEdge(v1) ) ); - - for (int j=0; j<3; ++j) { - e = e->GetNext(); - result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID(); - } - } - - result += 16; - - } else if (ringsize==12) { - - // Boundary case - // - // 4 0 1 5 - // ---- o ---- o ---- o ---- o ---- - // | | | | - // | 11 | 3 | 2 | 6 - // ---- o ---- o ---- o ---- o ---- - // | | | | - // | 10 | 9 | 8 | 7 - // ---- o ---- o ---- o ---- o ---- - // | | | | - // | | | | - - Hvertex * v[4]; - for (int i=0; i<4; ++i) - v[i] = f->GetVertex( (i+f->_adaptiveFlags.rots)%4 ); - - Hhalfedge * e; - - e = v[0]->GetIncidentEdge()->GetPrev()->GetOpposite()->GetPrev(); - result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID(); - - e = v[1]->GetIncidentEdge(); - result[remap[idx++ % ringsize]] = e->GetDestVertex()->GetID(); - - e = v[2]->GetNextEdge( v[2]->GetEdge(v[1]) ); - for (int i=0; i<3; ++i) { - e = e->GetNext(); - result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID(); - } - - e = v[3]->GetNextEdge( v[3]->GetEdge(v[2]) ); - for (int i=0; i<3; ++i) { - e = e->GetNext(); - result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID(); - } - - for (int i=12; i<16; ++i) { - result[remap[idx++]] = result[0]; - } - result += 16; - - } else if (ringsize==9) { - - // Corner case - // - // 0 1 4 - // o ---- o ---- o ---- - // | | | - // | 3 | 2 | 5 - // o ---- o ---- o ---- - // | | | - // | 8 | 7 | 6 - // o ---- o ---- o ---- - // | | | - // | | | - - Hvertex * v0 = f->GetVertex( (0+f->_adaptiveFlags.rots)%4 ), - * v2 = f->GetVertex( (2+f->_adaptiveFlags.rots)%4 ), - * v3 = f->GetVertex( (3+f->_adaptiveFlags.rots)%4 ); - - Hhalfedge * e; - - e = v0->GetIncidentEdge()->GetPrev()->GetOpposite()->GetPrev(); - result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID(); - - e = v2->GetIncidentEdge(); - result[remap[idx++ % ringsize]] = e->GetDestVertex()->GetID(); - - e = v3->GetNextEdge( v3->GetEdge(v2) ); - for (int i=0; i<3; ++i) { - e = e->GetNext(); - result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID(); - } - - for (int i=9; i<16; ++i) { - result[remap[idx++]] = result[0]; - } - result += 16; - - } - assert(idx==16); - return result; -} - -//------------------------------------------------------------------------------ -// Populate the quad-offsets table used by Gregory patches -void -Far::PatchTablesFactory::getQuadOffsets(Hface const * f, unsigned int * result) { - - assert(result and f and f->GetNumVertices()==4); - - // Builds a table of value pairs for each vertex of the patch. - // - // o - // N0 | - // | - // | - // o ------ o ------ o - // N1 V | .... M3 - // | ....... - // | ....... - // o ....... - // N2 - // - // [...] [N2 - N3] [...] - // - // Each value pair is composed of 2 index values in range [0-4[ pointing - // to the 2 neighbor vertices to the vertex that belong to the Gregory patch. - // Neighbor ordering is valence counter-clockwise and must match the winding - // used to build the vertexValenceTable. - // - - class GatherOffsetsOperator : public OpenSubdiv::HbrVertexOperator { - public: - Hvertex ** verts; int offsets[2]; int index; int count; - - GatherOffsetsOperator(Hvertex ** iverts) : verts(iverts) { } - - ~GatherOffsetsOperator() { } - - void reset() { - index=count=offsets[0]=offsets[1]=0; - } - - virtual void operator() (Hvertex &v) { - // Resolve which 2 neighbor vertices of v belong to the Gregory patch - for (unsigned char i=0; i<4; ++i) - if (&v==verts[i]) { - assert(count<3); - offsets[count++]=index; - break; - } - ++index; - } - }; - - // 4 central CVs of the Gregory patch - Hvertex * fvs[4] = { f->GetVertex(0), - f->GetVertex(1), - f->GetVertex(2), - f->GetVertex(3) }; - - - // Hbr vertex operator that iterates over neighbor vertices - GatherOffsetsOperator op( fvs ); - - for (unsigned char i=0; i<4; ++i) { - - op.reset(); - - fvs[i]->ApplyOperatorSurroundingVertices( op ); - - if (op.offsets[1] - op.offsets[0] != 1) - std::swap(op.offsets[0], op.offsets[1]); - - // Pack the 2 indices in 16 bits - result[i] = (op.offsets[0] | (op.offsets[1] << 8)); - } -} - -//------------------------------------------------------------------------------ -// Computes per-face or per-patch local ptex texture coordinates. -OpenSubdiv::Far::PatchParam * -Far::PatchTablesFactory::computePatchParam(Hface const * f, OpenSubdiv::Far::PatchParam *coord) { - - unsigned short u, v, ofs = 1; - unsigned char depth; - bool nonquad = false; - - if (coord == NULL) return NULL; - - // save the rotation state of the coarse face - //unsigned char rots = (unsigned char)f->_adaptiveFlags.rots; - - // track upwards towards coarse parent face, accumulating u,v indices - Hface const * p = f->GetParent(); - for ( u=v=depth=0; p!=NULL; depth++ ) { - - int nverts = p->GetNumVertices(); - if ( nverts != 4 ) { // non-quad coarse face : stop accumulating offsets - nonquad = true; // set non-quad bit - break; - } - - for (unsigned char i=0; iGetChild( i )==f ) { - switch ( i ) { - case 0 : break; - case 1 : { u+=ofs; } break; - case 2 : { u+=ofs; v+=ofs; } break; - case 3 : { v+=ofs; } break; - } - break; - } - } - ofs = (unsigned short)(ofs << 1); - f = p; - p = f->GetParent(); - } - - unsigned short boundaryMask = 0; - unsigned short transitionMask = 0; - coord->Set( f->GetPtexIndex(), u, v, depth, nonquad, boundaryMask, transitionMask ); - - return ++coord; -} -} - -} // end namespace OPENSUBDIV_VERSION -using namespace OPENSUBDIV_VERSION; - -} // end namespace OpenSubdiv - - -OpenSubdiv::Far::PatchTables const * -CreatePatchTables(Hmesh & mesh, int maxvalence) { - - return OpenSubdiv::Far::PatchTablesFactory::Create(mesh, maxvalence); -} - -//------------------------------------------------------------------------------ diff --git a/examples/farViewer/hbr_refine.h b/examples/farViewer/hbr_refine.h deleted file mode 100644 index 706c4782..00000000 --- a/examples/farViewer/hbr_refine.h +++ /dev/null @@ -1,116 +0,0 @@ -// -// Copyright 2013 Pixar -// -// Licensed under the Apache License, Version 2.0 (the "Apache License") -// with the following modification; you may not use this file except in -// compliance with the Apache License and the following modification to it: -// Section 6. Trademarks. is deleted and replaced with: -// -// 6. Trademarks. This License does not grant permission to use the trade -// names, trademarks, service marks, or product names of the Licensor -// and its affiliates, except as required to comply with Section 4(c) of -// the License and to reproduce the content of the NOTICE file. -// -// You may obtain a copy of the Apache License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the Apache License with the above modification is -// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the Apache License for the specific -// language governing permissions and limitations under the Apache License. -// - -#ifndef HBR_REFINE_H -#define HBR_REFINE_H - -#ifndef HBR_ADAPTIVE -#define HBR_ADAPTIVE -#endif - -#include - -#include - -//------------------------------------------------------------------------------ -// Vertex class implementation -struct Vertex { - - Vertex() { /* _pos[0]=_pos[1]=_pos[2]=0.0f; */ } - - Vertex( int /*i*/ ) { } - - Vertex( float x, float y, float z ) { _pos[0]=x; _pos[1]=y; _pos[2]=z; } - - Vertex( const Vertex & src ) { _pos[0]=src._pos[0]; _pos[1]=src._pos[1]; _pos[2]=src._pos[2]; } - - ~Vertex( ) { } - - void AddWithWeight(Vertex const & src, float weight) { - _pos[0]+=weight*src._pos[0]; - _pos[1]+=weight*src._pos[1]; - _pos[2]+=weight*src._pos[2]; - } - - void AddWithWeight(Vertex const & src, float weight, float /* ds */, float /* dt */) { - _pos[0]+=weight*src._pos[0]; - _pos[1]+=weight*src._pos[1]; - _pos[2]+=weight*src._pos[2]; - } - - void AddVaryingWithWeight(Vertex const & , float) { } - - void Clear( void * =0 ) { _pos[0]=_pos[1]=_pos[2]=0.0f; } - - void SetPosition(float x, float y, float z) { _pos[0]=x; _pos[1]=y; _pos[2]=z; } - - void ApplyVertexEdit(const OpenSubdiv::HbrVertexEdit & edit) { - const float *src = edit.GetEdit(); - switch(edit.GetOperation()) { - case OpenSubdiv::HbrHierarchicalEdit::Set: - _pos[0] = src[0]; - _pos[1] = src[1]; - _pos[2] = src[2]; - break; - case OpenSubdiv::HbrHierarchicalEdit::Add: - _pos[0] += src[0]; - _pos[1] += src[1]; - _pos[2] += src[2]; - break; - case OpenSubdiv::HbrHierarchicalEdit::Subtract: - _pos[0] -= src[0]; - _pos[1] -= src[1]; - _pos[2] -= src[2]; - break; - } - } - - void ApplyMovingVertexEdit(const OpenSubdiv::HbrMovingVertexEdit &) { } - - float const * GetPos() const { return _pos; } - -private: - float _pos[3]; -}; - -//------------------------------------------------------------------------------ - -typedef OpenSubdiv::HbrMesh Hmesh; -typedef OpenSubdiv::HbrFace Hface; -typedef OpenSubdiv::HbrVertex Hvertex; -typedef OpenSubdiv::HbrHalfedge Hhalfedge; - -//------------------------------------------------------------------------------ - -// refine the Hbr mesh uniformly -void RefineUniform(Hmesh & mesh, int maxlevel, std::vector & refinedFaces); - -// refine the Hbr mesh adaptively -int RefineAdaptive(Hmesh & mesh, int maxlevel, std::vector & refinedFaces); - -OpenSubdiv::Far::PatchTables const * CreatePatchTables(Hmesh & mesh, int maxvalence); - -//------------------------------------------------------------------------------ - -#endif // HBR_REFINE_H