diff --git a/documentation/far_overview.rst b/documentation/far_overview.rst index 114e7611..ba214668 100644 --- a/documentation/far_overview.rst +++ b/documentation/far_overview.rst @@ -45,11 +45,11 @@ First, *Far* provides the tools to refine subdivision topology either uniform or sparse, where extraordinary features are automatically isolated (see `feature adaptive subdivision `__). -As a geometry representation, *Far* also provides a set of *"Tables"* classes. +As a geometry representation, *Far* also provides a set of *"Table"* classes. These tables are designed to be static containers for the refined topology data, after it has been serialized and factorized. This representation is -embodied in the `Far::PatchTables <#far-patchtables>`__ and the -`Far::StencilTables <#far-patchtables>`__ classes. +embodied in the `Far::PatchTable <#far-patchtable>`__ and the +`Far::StencilTable <#far-patchtable>`__ classes. *Far* is also a fully featured API. Typically *Far* tabular data is targeted at *Osd*, where it can be processed by an implementation optimized for a specific @@ -87,8 +87,8 @@ Far::TopologyRefiner TopologyRefiner is the building block for many other useful classes in OpenSubdiv, but its purpose is more specific. It is intended to store the topology of an arbitrarily refined subdivision hierarchy to support the -construction of `stencil tables <#patch-tables>`__, `patch tables -<#patch-tables>`__, etc. +construction of `stencil table <#patch-table>`__, `patch table +<#patch-table>`__, etc. Aside from public access to topology, TopologyRefiner has public refinement methods (currently *RefineUniform()* and *RefineAdapative()*) where simple @@ -185,14 +185,14 @@ A common base class has been created for the factory class, i.e.: both to provide common code independent of and also potentially to protect core code from unwanted specialization. -Far::PatchTables +Far::PatchTable ================ -The patch tables are a serialized topology representation. This container is -generated using *Far::PatchTablesFactory* from an instance +The patch table is a serialized topology representation. This container is +generated using *Far::PatchTableFactory* from an instance *Far::TopologyRefiner* after a refinement has been applied. The -FarPatchTablesFactory traverses the data-structures of the TopologyRefiner and +FarPatchTableFactory traverses the data-structures of the TopologyRefiner and serializes the sub-faces into collections of bi-linear and bi-cubic patches, as dictated by the refinement mode (uniform or adaptive). The patches are then sorted into arrays based on their types. @@ -216,13 +216,13 @@ description of the patches in the array. This includes the patches *type*, *pattern* and *rotation*. The PatchArray *ArrayRange* provides the indices necessary to track the records -of individual patches in the tables. +of individual patches in the table. Patch Types *********** The following are the different patch types that can be represented in the -PatchTables: +PatchTable: +-------------------------------------------------------------------------+ | | @@ -285,11 +285,11 @@ Patch Transitions .. include:: under_development.rst -Far::StencilTables +Far::StencilTable ================== -The base container for stencil data is the StencilTables class. As with most -other Far entities, it has an associated StencilTablesFactory that requires a +The base container for stencil data is the StencilTable class. As with most +other Far entities, it has an associated StencilTableFactory that requires a TopologyRefiner: Advantages @@ -321,7 +321,7 @@ iteration interpolates the new vertices by applying polynomial weights to a The interpolation calculations for any given vertex can be broken down into sequences of multiply-add operations applied to the supporting vertices. -Stencil tables encode a factorization of these weighted sums : each stencils is +Stencil table encodes a factorization of these weighted sums : each stencils is created by combining the list of control vertices from the 1-ring. With iterative subdivision, each refinement step is dependent upon the previous @@ -377,7 +377,7 @@ derivatives, so limit stencils carry a set of weights for tangent vectors. .. image:: images/far_stencil0.png :align: center -Once the stencil tables have been generated, limit stencils are the most direct +Once the stencil table has been generated, limit stencils are the most direct and efficient method of evaluation of specific locations on the limit of a subdivision surface, starting from the coarse vertices of the control cage. diff --git a/documentation/nav_template.txt b/documentation/nav_template.txt index 64b4d35f..ac6c2d80 100644 --- a/documentation/nav_template.txt +++ b/documentation/nav_template.txt @@ -63,8 +63,8 @@
  • Far
  • Vtr
  • Sdc
  • diff --git a/documentation/osd_overview.rst b/documentation/osd_overview.rst index de200718..980349e6 100644 --- a/documentation/osd_overview.rst +++ b/documentation/osd_overview.rst @@ -119,7 +119,7 @@ a series of regression tests that compare the methods to each other. * **Beta Issues** Face-varying smooth data interpolation is currently only supported in - **Osd** through refinement and limit points but not in the PatchTables. + **Osd** through refinement and limit points but not in the PatchTable. ---- diff --git a/documentation/tutorials.rst b/documentation/tutorials.rst index 5898d4ce..03fce0c3 100644 --- a/documentation/tutorials.rst +++ b/documentation/tutorials.rst @@ -89,17 +89,17 @@ or in your local ``/turorials``. | |far_tut_3| | - | **Tutorial 4** - | This tutorial shows how to create and manipulate FarStencilTables. We use the + | This tutorial shows how to create and manipulate FarStencilTable. We use the factorized stencils to interpolate vertex primvar data buffers. `[code] `__ | | **Tutorial 5** | This tutorial shows how to create and manipulate both 'vertex' and 'varying' - FarStencilTables to interpolate 2 primvar data buffers: vertex positions and + FarStencilTable to interpolate 2 primvar data buffers: vertex positions and vertex colors. `[code] `__ | | **Tutorial 6** | This tutorial shows how to interpolate surface limits at arbitrary - parametric locations using feature adaptive Far::PatchTables. `[code] `__ + parametric locations using feature adaptive Far::PatchTable. `[code] `__ | |far_tut_6| | | **Tutorial 7** diff --git a/examples/common/patchColors.h b/examples/common/patchColors.h index c9a07edb..8d9a48e2 100644 --- a/examples/common/patchColors.h +++ b/examples/common/patchColors.h @@ -25,7 +25,7 @@ #ifndef OPENSUBDIV_EXAMPLES_COMMON_PATCH_COLORS_H #define OPENSUBDIV_EXAMPLES_COMMON_PATCH_COLORS_H -#include +#include // returns a unique color for each type of feature-adaptive patches float const * getAdaptivePatchColor(OpenSubdiv::Far::PatchDescriptor const & desc); diff --git a/examples/dxPtexViewer/dxPtexViewer.cpp b/examples/dxPtexViewer/dxPtexViewer.cpp index dc4ca77b..448d6e69 100755 --- a/examples/dxPtexViewer/dxPtexViewer.cpp +++ b/examples/dxPtexViewer/dxPtexViewer.cpp @@ -236,12 +236,14 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner * refiner, typedef OpenSubdiv::Far::ConstIndexArray IndexArray; // calc normal vectors - int nverts = refiner->GetNumVertices(0), - nfaces = refiner->GetNumFaces(0); + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + + int nverts = refBaseLevel.GetNumVertices(), + nfaces = refBaseLevel.GetNumFaces(); for (int face = 0; face < nfaces; ++face) { - IndexArray fverts = refiner->GetFaceVertices(0, face); + IndexArray fverts = refBaseLevel.GetFaceVertices(face); float const * p0 = &pos[fverts[0]*3], * p1 = &pos[fverts[1]*3], @@ -704,12 +706,13 @@ createOsdMesh(int level, int kernel) { OpenSubdiv::Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); // create cage edge index - int nedges = refiner->GetNumEdges(0); + int nedges = refBaseLevel.GetNumEdges(); std::vector edgeIndices(nedges*2); for(int i=0; iGetEdgeVertices(0, i); + IndexArray verts = refBaseLevel.GetEdgeVertices(i); edgeIndices[i*2 ]=verts[0]; edgeIndices[i*2+1]=verts[1]; } @@ -734,7 +737,7 @@ createOsdMesh(int level, int kernel) { if (g_kernel == kCPU) { g_mesh = new Osd::Mesh( @@ -746,7 +749,7 @@ createOsdMesh(int level, int kernel) { #ifdef OPENSUBDIV_HAS_OPENMP } else if (kernel == kOPENMP) { g_mesh = new Osd::Mesh( @@ -758,7 +761,7 @@ createOsdMesh(int level, int kernel) { #ifdef OPENSUBDIV_HAS_TBB } else if (kernel == kTBB) { g_mesh = new Osd::Mesh( @@ -771,7 +774,7 @@ createOsdMesh(int level, int kernel) { } else if(kernel == kCL) { static Osd::EvaluatorCacheT clEvaluatorCache; g_mesh = new Osd::Mesh( @@ -785,7 +788,7 @@ createOsdMesh(int level, int kernel) { #ifdef OPENSUBDIV_HAS_CUDA } else if (g_kernel == kCUDA) { g_mesh = new Osd::Mesh( @@ -797,7 +800,7 @@ createOsdMesh(int level, int kernel) { } else if (g_kernel == kDirectCompute) { static Osd::EvaluatorCacheT d3d11ComputeEvaluatorCache; g_mesh = new Osd::Mesh( diff --git a/examples/dxViewer/dxviewer.cpp b/examples/dxViewer/dxviewer.cpp index 55b4309e..d3189e5d 100644 --- a/examples/dxViewer/dxviewer.cpp +++ b/examples/dxViewer/dxviewer.cpp @@ -277,22 +277,24 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) - int nedges = refiner->GetNumEdges(0), - nverts = refiner->GetNumVertices(0); + Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + + int nedges = refBaseLevel.GetNumEdges(), + nverts = refBaseLevel.GetNumVertices(); g_coarseEdges.resize(nedges*2); g_coarseEdgeSharpness.resize(nedges); g_coarseVertexSharpness.resize(nverts); for(int i=0; iGetEdgeVertices(0, i); + IndexArray verts = refBaseLevel.GetEdgeVertices(i); g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2+1]=verts[1]; - g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); + g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i); } for(int i=0; iGetVertexSharpness(0, i); + g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i); } g_orgPositions=shape->verts; @@ -320,7 +322,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= if (g_kernel == kCPU) { g_mesh = new Osd::Mesh( @@ -332,7 +334,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= #ifdef OPENSUBDIV_HAS_OPENMP } else if (kernel == kOPENMP) { g_mesh = new Osd::Mesh( @@ -344,7 +346,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= #ifdef OPENSUBDIV_HAS_TBB } else if (kernel == kTBB) { g_mesh = new Osd::Mesh( @@ -357,7 +359,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= } else if(kernel == kCL) { static Osd::EvaluatorCacheT clEvaluatorCache; g_mesh = new Osd::Mesh( @@ -371,7 +373,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= #ifdef OPENSUBDIV_HAS_CUDA } else if (g_kernel == kCUDA) { g_mesh = new Osd::Mesh( @@ -383,7 +385,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= } else if (g_kernel == kDirectCompute) { static Osd::EvaluatorCacheT d3d11ComputeEvaluatorCache; g_mesh = new Osd::Mesh( @@ -403,7 +405,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= if (g_endCap == kEndCapLegacyGregory) { g_legacyGregoryPatchTable = Osd::D3D11LegacyGregoryPatchTable::Create( - g_mesh->GetFarPatchTables(), g_pd3dDeviceContext); + g_mesh->GetFarPatchTable(), g_pd3dDeviceContext); } // compute model bounding @@ -827,7 +829,7 @@ display() { g_mesh->GetPatchTable()->GetPatchIndexBuffer(), DXGI_FORMAT_R32_UINT, 0); // patch drawing - int patchCount[12]; // [Type] (see far/patchTables.h) + int patchCount[12]; // [Type] (see far/patchTable.h) int numTotalPatches = 0; int numDrawCalls = 0; diff --git a/examples/farViewer/farViewer.cpp b/examples/farViewer/farViewer.cpp index 5debf28b..2459187d 100644 --- a/examples/farViewer/farViewer.cpp +++ b/examples/farViewer/farViewer.cpp @@ -50,9 +50,9 @@ GLFWmonitor* g_primary=0; #include #include -#include -#include -#include +#include +#include +#include #include @@ -212,7 +212,7 @@ createVertNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner, if (refiner.IsUniform()) { for (int i=0; iPrint3D(vertexBuffer[vert].GetPos(), buf, 1); } @@ -245,16 +245,17 @@ createEdgeNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner, firstvert = 0; for (int i=0; i0.0f) { snprintf(buf, 16, "%g", sharpness); g_font->Print3D(center.GetPos(), buf, std::min(8,(int)sharpness+4)); @@ -289,15 +290,16 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner, firstvert = 0; for (int i=0; iPrint3D(center.GetPos(), buf, 2); } - firstvert+=refiner.GetNumVertices(level); + firstvert+=refLevel.GetNumVertices(); } } } @@ -340,7 +343,7 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner, //------------------------------------------------------------------------------ // generate display vert IDs for the selected Far patch static void -createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables, +createPatchNumbers(OpenSubdiv::Far::PatchTable const & patchTable, std::vector const & vertexBuffer) { if (not g_currentPatch) @@ -350,8 +353,8 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables, patchArray = -1; // Find PatchArray containing our patch - for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { - int npatches = patchTables.GetNumPatches(array); + for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) { + int npatches = patchTable.GetNumPatches(array); if (patchID >= npatches) { patchID -= npatches; } else { @@ -363,10 +366,10 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables, return; } - g_currentPatchDesc = patchTables.GetPatchArrayDescriptor(patchArray); + g_currentPatchDesc = patchTable.GetPatchArrayDescriptor(patchArray); OpenSubdiv::Far::ConstIndexArray const cvs = - patchTables.GetPatchVertices(patchArray, patchID); + patchTable.GetPatchVertices(patchArray, patchID); static char buf[16]; for (int i=0; i const & fvarBuffer) { static int channel = 0; @@ -386,20 +389,20 @@ createFVarPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables, int patch = g_currentPatch-1; static char buf[16]; - if (patch>=0 and patch=0 and patchPrint3D(fvarBuffer[cvs[i]].GetPos(), buf, 2); } - g_currentFVarPatchType = patchTables.GetFVarPatchType(channel, handle); + g_currentFVarPatchType = patchTable.GetFVarPatchType(channel, handle); } } @@ -410,7 +413,7 @@ static GLMesh fvarVerts, static void createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner, - OpenSubdiv::Far::PatchTables const & patchTables, + OpenSubdiv::Far::PatchTable const & patchTable, std::vector const & fvarBuffer) { assert(not fvarBuffer.empty()); @@ -420,14 +423,14 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner, if (g_FarDrawFVarVerts) { GLMesh::Options options; options.vertColorMode = GLMesh::VERTCOLOR_BY_LEVEL; - fvarVerts.InitializeFVar(options, refiner, &patchTables, channel, 0, (float *)(&fvarBuffer[0])); + fvarVerts.InitializeFVar(options, refiner, &patchTable, channel, 0, (float *)(&fvarBuffer[0])); } if (g_FarDrawFVarPatches) { // generate uniform tessellation for patches int tessFactor = g_FarDrawFVarPatchTess, - npatches = patchTables.GetNumPatchesTotal(), + npatches = patchTable.GetNumPatchesTotal(), nvertsperpatch = (tessFactor) * (tessFactor), nverts = npatches * nvertsperpatch; @@ -439,7 +442,7 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner, std::vector verts(nverts); memset(&verts[0], 0, verts.size()*sizeof(Vertex)); - OpenSubdiv::Far::PatchTables::PatchHandle handle; + OpenSubdiv::Far::PatchTable::PatchHandle handle; Vertex * vert = &verts[0]; for (int patch=0; patch const & vertexBuffer) { typedef OpenSubdiv::Far::PatchDescriptor PatchDescriptor; int npatches = 0; int patchArray = 0; - for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { - if (patchTables.GetPatchArrayDescriptor(array).GetType()== + for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) { + if (patchTable.GetPatchArrayDescriptor(array).GetType()== PatchDescriptor::GREGORY_BASIS) { - npatches = patchTables.GetNumPatches(array); + npatches = patchTable.GetNumPatches(array); patchArray = array; break; } @@ -496,7 +499,7 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables, * indices = &edgeindices[patch * 40]; OpenSubdiv::Far::ConstIndexArray const cvs = - patchTables.GetPatchVertices(patchArray, patch); + patchTable.GetPatchVertices(patchArray, patch); for (int i=0; i<20; ++i) { vpe[i] = 2; @@ -536,7 +539,7 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables, //------------------------------------------------------------------------------ // generate display IDs for Far faces static void -createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables, +createPtexNumbers(OpenSubdiv::Far::PatchTable const & patchTable, std::vector const & vertexBuffer) { typedef OpenSubdiv::Far::PatchDescriptor Descriptor; @@ -546,15 +549,15 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables, static int regular[4] = {5, 6, 9, 10}, gregory[4] = {0, 1, 2, 3}; - for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { + for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) { - for (int patch=0; patch<(int)patchTables.GetNumPatches(array); ++patch) { + for (int patch=0; patch<(int)patchTable.GetNumPatches(array); ++patch) { OpenSubdiv::Far::ConstIndexArray const cvs = - patchTables.GetPatchVertices(array, patch); + patchTable.GetPatchVertices(array, patch); int * remap = 0; - switch (patchTables.GetPatchArrayDescriptor(array).GetType()) { + switch (patchTable.GetPatchArrayDescriptor(array).GetType()) { case Descriptor::REGULAR: remap = regular; break; case Descriptor::GREGORY: case Descriptor::GREGORY_BOUNDARY: @@ -568,7 +571,7 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables, center.AddWithWeight(vertexBuffer[cvs[remap[k]]], 0.25f); } - snprintf(buf, 16, "%d", patchTables.GetPatchParam(array, patch).faceIndex); + snprintf(buf, 16, "%d", patchTable.GetPatchParam(array, patch).faceIndex); g_font->Print3D(center.GetPos(), buf, 1); } } @@ -606,35 +609,35 @@ createFarGLMesh(Shape * shape, int maxlevel) { int numTotalVerts = refiner->GetNumVerticesTotal(); // - // Patch tables + // Patch table // std::vector fvarBuffer; - Far::PatchTables * patchTables = 0; + Far::PatchTable * patchTable = 0; bool createFVarWire = g_FarDrawFVarPatches or g_FarDrawFVarVerts; if (g_Adaptive) { - Far::PatchTablesFactory::Options options; + Far::PatchTableFactory::Options options; options.generateFVarTables = createFVarWire; options.shareEndCapPatchPoints = false; - patchTables = - Far::PatchTablesFactory::Create(*refiner, options); + patchTable = + Far::PatchTableFactory::Create(*refiner, options); // increase vertex buffer for the additional endcap verts - if (patchTables->GetEndCapVertexStencilTables()) { - numTotalVerts += patchTables->GetEndCapVertexStencilTables()->GetNumStencils(); + if (patchTable->GetEndCapVertexStencilTable()) { + numTotalVerts += patchTable->GetEndCapVertexStencilTable()->GetNumStencils(); } - g_numPatches = patchTables->GetNumPatchesTotal(); - g_maxValence = patchTables->GetMaxValence(); + g_numPatches = patchTable->GetNumPatchesTotal(); + g_maxValence = patchTable->GetMaxValence(); if (createFVarWire) { // interpolate fvar values - //Far::FVarPatchTables const * fvarTables = - // patchTables->GetFVarPatchTables(); - //assert(fvarTables); + //Far::FVarPatchTable const * fvarTable = + // patchTable->GetFVarPatchTable(); + //assert(fvarTable); int channel = 0; @@ -642,7 +645,7 @@ createFarGLMesh(Shape * shape, int maxlevel) { fvarBuffer.resize(refiner->GetNumFVarValuesTotal(channel), 0); Vertex * values = &fvarBuffer[0]; - int nCoarseValues = refiner->GetNumFVarValues(0); + int nCoarseValues = refiner->GetLevel(0).GetNumFVarValues(channel); for (int i=0; iuvs[i*2]; @@ -672,29 +675,29 @@ createFarGLMesh(Shape * shape, int maxlevel) { // // Stencil interpolation // - Far::StencilTables const * stencilTables = 0; - Far::StencilTablesFactory::Options options; + Far::StencilTable const * stencilTable = 0; + Far::StencilTableFactory::Options options; options.generateOffsets=true; options.generateIntermediateLevels=true; - stencilTables = Far::StencilTablesFactory::Create(*refiner, options); + stencilTable = Far::StencilTableFactory::Create(*refiner, options); // append endpatch stencils if needed - if (patchTables and patchTables->GetEndCapVertexStencilTables()) { - if (Far::StencilTables const * stencilTablesWithEndCap = - Far::StencilTablesFactory::AppendEndCapStencilTables( - *refiner, stencilTables, - patchTables->GetEndCapVertexStencilTables())) { - delete stencilTables; - stencilTables = stencilTablesWithEndCap; + if (patchTable and patchTable->GetEndCapVertexStencilTable()) { + if (Far::StencilTable const * stencilTableWithEndCap = + Far::StencilTableFactory::AppendEndCapStencilTable( + *refiner, stencilTable, + patchTable->GetEndCapVertexStencilTable())) { + delete stencilTable; + stencilTable = stencilTableWithEndCap; } } // // apply stencils // - stencilTables->UpdateValues(verts, verts + ncoarseverts); + stencilTable->UpdateValues(verts, verts + ncoarseverts); - delete stencilTables; + delete stencilTable; } else { // // TopologyRefiner interpolation @@ -722,21 +725,21 @@ createFarGLMesh(Shape * shape, int maxlevel) { createFaceNumbers(*refiner, vertexBuffer); } - if (g_FarDrawPtexIDs and patchTables) { - createPtexNumbers(*patchTables, vertexBuffer); + if (g_FarDrawPtexIDs and patchTable) { + createPtexNumbers(*patchTable, vertexBuffer); } if (g_Adaptive) { - createPatchNumbers(*patchTables, vertexBuffer); + createPatchNumbers(*patchTable, vertexBuffer); } if (g_Adaptive and g_FarDrawGregogyBasis) { - createGregoryBasis(*patchTables, vertexBuffer); + createGregoryBasis(*patchTable, vertexBuffer); } if (g_Adaptive and createFVarWire) { - createFVarPatches(*refiner, *patchTables, fvarBuffer); - createFVarPatchNumbers(*patchTables, fvarBuffer); + createFVarPatches(*refiner, *patchTable, fvarBuffer); + createFVarPatchNumbers(*patchTable, fvarBuffer); } createEdgeNumbers(*refiner, vertexBuffer, g_FarDrawEdgeIDs!=0, g_FarDrawEdgeSharpness!=0); @@ -746,7 +749,7 @@ createFarGLMesh(Shape * shape, int maxlevel) { options.edgeColorMode=g_Adaptive ? GLMesh::EDGECOLOR_BY_PATCHTYPE : GLMesh::EDGECOLOR_BY_SHARPNESS; options.faceColorMode=g_Adaptive ? GLMesh::FACECOLOR_BY_PATCHTYPE :GLMesh::FACECOLOR_SOLID; - g_far_glmesh.Initialize(options, *refiner, patchTables, (float *)&verts[0]); + g_far_glmesh.Initialize(options, *refiner, patchTable, (float *)&verts[0]); if (g_Adaptive) { g_far_glmesh.SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); } else { @@ -759,7 +762,7 @@ createFarGLMesh(Shape * shape, int maxlevel) { g_far_glmesh.InitializeDeviceBuffers(); delete refiner; - delete patchTables; + delete patchTable; } //------------------------------------------------------------------------------ diff --git a/examples/farViewer/gl_mesh.cpp b/examples/farViewer/gl_mesh.cpp index 5ce7006c..685887e1 100644 --- a/examples/farViewer/gl_mesh.cpp +++ b/examples/farViewer/gl_mesh.cpp @@ -243,10 +243,10 @@ GLMesh::Initialize(Options /* options */, //------------------------------------------------------------------------------ void GLMesh::Initialize(Options options, TopologyRefiner const & refiner, - PatchTables const * patchTables, float const * vertexData) { + PatchTable const * patchTable, float const * vertexData) { - if (patchTables) { - initializeBuffers(options, refiner, *patchTables, vertexData); + if (patchTable) { + initializeBuffers(options, refiner, *patchTable, vertexData); } else { initializeBuffers(options, refiner, vertexData); } @@ -265,15 +265,18 @@ GLMesh::initializeBuffers(Options options, typedef OpenSubdiv::Far::ConstIndexArray IndexArray; - int maxlevel = refiner.GetMaxLevel(), - nverts = refiner.GetNumVertices(maxlevel), - nedges = refiner.GetNumEdges(maxlevel), - nfaces = refiner.GetNumFaces(maxlevel), + int maxlevel = refiner.GetMaxLevel(); + + OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel); + + int nverts = refLastLevel.GetNumVertices(), + nedges = refLastLevel.GetNumEdges(), + nfaces = refLastLevel.GetNumFaces(), firstvert = 0; for (int i=0; i0) { - for (int vert=0; vert & eao = _eao[COMP_FACE]; eao.resize(nfaceverts); @@ -381,7 +386,7 @@ GLMesh::initializeBuffers(Options options, for (int face=0, ofs=0; face & vbo, int edge, float const * vertData, int v0, int //------------------------------------------------------------------------------ void GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner, - PatchTables const * patchTables, int channel, int tessFactor, float const * fvarData) { + PatchTable const * patchTable, int channel, int tessFactor, float const * fvarData) { int nverts = refiner.GetNumFVarValuesTotal(channel); @@ -421,7 +426,7 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner, if (options.vertColorMode==VERTCOLOR_BY_LEVEL) { for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) { - for (int vert=0; vert0) { // edge color component ------------------------------ - int npatches = patchTables->GetNumPatchesTotal(), + int npatches = patchTable->GetNumPatchesTotal(), nvertsperpatch = (tessFactor) * (tessFactor), nedgesperpatch = (tessFactor-1) * (tessFactor*2+tessFactor-1), //nverts = npatches * nvertsperpatch, @@ -475,14 +480,14 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner, *ptr++ = tessFactor * (tessFactor-1) + i+1; } - OpenSubdiv::Far::PatchTables::PatchHandle handle; + OpenSubdiv::Far::PatchTable::PatchHandle handle; for (int patch=0, offset=0; patchGetFVarPatchType(channel, handle); + patchTable->GetFVarPatchType(channel, handle); if (OpenSubdiv::Far::PatchDescriptor::IsAdaptive(type)) { color = getAdaptivePatchColor( @@ -591,7 +596,7 @@ getRingSize(OpenSubdiv::Far::PatchDescriptor desc) { //------------------------------------------------------------------------------ void GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, - PatchTables const & patchTables, float const * vertexData) { + PatchTable const & patchTable, float const * vertexData) { int nverts = refiner.GetNumVerticesTotal(); @@ -604,7 +609,7 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, if (options.vertColorMode==VERTCOLOR_BY_LEVEL) { for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) { - for (int vert=0; vert & vbo = _vbo[COMP_EDGE]; vbo.resize(nedges * 2 * 6); @@ -641,10 +646,10 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, float const * color=solidColor; - for (int array=0, edge=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { + for (int array=0, edge=0; array<(int)patchTable.GetNumPatchArrays(); ++array) { OpenSubdiv::Far::PatchDescriptor desc = - patchTables.GetPatchArrayDescriptor(array); + patchTable.GetPatchArrayDescriptor(array); if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) { color = getAdaptivePatchColor(desc); @@ -652,10 +657,10 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, int ncvs = getRingSize(desc); - for (int patch=0; patch & vbo = _vbo[COMP_FACE]; vbo.resize(nverts*3); @@ -686,17 +691,17 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, _faceColors.resize(nfaces*4, 1.0f); // default to solid color - for (int array=0, face=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { + for (int array=0, face=0; array<(int)patchTable.GetNumPatchArrays(); ++array) { OpenSubdiv::Far::PatchDescriptor desc = - patchTables.GetPatchArrayDescriptor(array); + patchTable.GetPatchArrayDescriptor(array); //int ncvs = getRingSize(desc); - for (int patch=0; patch #include -#include +#include #include "../common/glUtils.h" @@ -193,13 +193,13 @@ public: // Far initialization typedef OpenSubdiv::Far::TopologyRefiner TopologyRefiner; - typedef OpenSubdiv::Far::PatchTables PatchTables; + typedef OpenSubdiv::Far::PatchTable PatchTable; void Initialize(Options options, TopologyRefiner const & refiner, - PatchTables const * patchTables, float const * vertexData); + PatchTable const * patchTable, float const * vertexData); void InitializeFVar(Options options, TopologyRefiner const & refiner, - PatchTables const * patchTables, int channel, int tessFactor, float const * fvarData); + PatchTable const * patchTable, int channel, int tessFactor, float const * fvarData); void InitializeDeviceBuffers(); @@ -229,7 +229,7 @@ private: float const * vertexData); void initializeBuffers(Options options, TopologyRefiner const & refiner, - PatchTables const & patchTables, float const * vertexData); + PatchTable const & patchTable, float const * vertexData); void clearBuffers(); diff --git a/examples/glEvalLimit/glEvalLimit.cpp b/examples/glEvalLimit/glEvalLimit.cpp index 0e9beb31..ad6df89d 100755 --- a/examples/glEvalLimit/glEvalLimit.cpp +++ b/examples/glEvalLimit/glEvalLimit.cpp @@ -50,8 +50,8 @@ GLFWmonitor* g_primary=0; #include #include #include -#include -#include +#include +#include #include #include @@ -60,6 +60,7 @@ GLFWmonitor* g_primary=0; #include "../common/stopwatch.h" #include "../common/simple_math.h" #include "../common/glHud.h" +#include "../common/glUtils.h" #include "init_shapes.h" #include "particles.h" @@ -71,10 +72,6 @@ GLFWmonitor* g_primary=0; #include #include -#ifdef OPENSUBDIV_HAS_OPENMP - #include -#endif - using namespace OpenSubdiv; //------------------------------------------------------------------------------ @@ -91,9 +88,11 @@ std::vector g_coarseEdgeSharpness; std::vector g_coarseVertexSharpness; enum DrawMode { kRANDOM=0, - kUV=1, - kVARYING=2, - kFACEVARYING=3 }; + kUV, + kVARYING, + kNORMAL, + kSHADE, + kFACEVARYING }; int g_running = 1, g_width = 1024, @@ -146,6 +145,18 @@ GLuint g_cageEdgeVAO = 0, GLhud g_hud; +//------------------------------------------------------------------------------ +struct Program { + GLuint program; + GLuint uniformModelViewMatrix; + GLuint uniformProjectionMatrix; + GLuint uniformDrawMode; + GLuint attrPosition; + GLuint attrColor; + GLuint attrTangentU; + GLuint attrTangentV; +} g_defaultProgram; + //------------------------------------------------------------------------------ static void createRandomColors(int nverts, int stride, float * colors) { @@ -167,22 +178,24 @@ createCoarseMesh(OpenSubdiv::Far::TopologyRefiner const & refiner) { typedef OpenSubdiv::Far::ConstIndexArray IndexArray; // save coarse topology (used for coarse mesh drawing) - int nedges = refiner.GetNumEdges(0), - nverts = refiner.GetNumVertices(0); + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0); + + int nedges = refBaseLevel.GetNumEdges(), + nverts = refBaseLevel.GetNumVertices(); g_coarseEdges.resize(nedges*2); g_coarseEdgeSharpness.resize(nedges); g_coarseVertexSharpness.resize(nverts); for(int i=0; i g_patchCoords; -Osd::VertexBufferDescriptor g_idesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 3 ), - g_odesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 6 ), - g_vdesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 6 ), - g_fvidesc( /*offset*/ 0, /*legnth*/ 2, /*stride*/ 2 ), - g_fvodesc( /*offset*/ 3, /*legnth*/ 2, /*stride*/ 6 ); +Osd::VertexBufferDescriptor g_idesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 3), + g_odesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 6), + g_vdesc(/*offset*/ 3, /*legnth*/ 3, /*stride*/ 6), + g_duDesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 6), + g_dvDesc(/*offset*/ 3, /*legnth*/ 3, /*stride*/ 6), + g_fvidesc(/*offset*/ 0, /*legnth*/ 2, /*stride*/ 2), + g_fvodesc(/*offset*/ 3, /*legnth*/ 2, /*stride*/ 6); +// input vertex data (coarse + refined) +Osd::CpuVertexBuffer * g_vertexData = 0; +Osd::CpuVertexBuffer * g_varyingData = 0; -Osd::CpuGLVertexBuffer * g_Q=0, - * g_dQs=0, - * g_dQt=0; +// output vertex data (limit locations) +Osd::CpuGLVertexBuffer * g_outVertexData = NULL; +Osd::CpuGLVertexBuffer * g_outDerivatives = NULL; STParticles * g_particles=0; @@ -245,7 +260,7 @@ updateGeom() { if (! g_topologyRefiner) return; // note that for patch eval we need coarse+refined combined buffer. - int nCoarseVertices = g_topologyRefiner->GetNumVertices(0); + int nCoarseVertices = g_topologyRefiner->GetLevel(0).GetNumVertices(); Osd::CpuEvaluator::EvalStencils(g_vertexData, Osd::VertexBufferDescriptor(0, 3, 3), g_vertexData, @@ -280,7 +295,7 @@ updateGeom() { g_patchCoords.clear(); for (int i = 0; i < g_particles->GetNumParticles(); ++i) { STParticles::Position const &position = g_particles->GetPositions()[i]; - Far::PatchTables::PatchHandle const *handle = + Far::PatchTable::PatchHandle const *handle = g_patchMap->FindPatch(position.ptexIndex, position.s, position.t); if (handle) { g_patchCoords.push_back(Osd::PatchCoord( @@ -289,20 +304,44 @@ updateGeom() { } // Evaluate the positions of the samples on the limit surface - g_nsamplesFound = Osd::CpuEvaluator::EvalPatches(g_vertexData, g_idesc, - g_Q, g_odesc, - g_patchCoords, - g_patchTables, NULL); - - // varying - if (g_drawMode == kVARYING) { - Osd::CpuEvaluator::EvalPatches(g_varyingData, g_idesc, - g_Q, g_vdesc, - g_patchCoords, - g_patchTables, NULL); + if (g_drawMode == kNORMAL || g_drawMode == kSHADE) { + // evaluate positions and derivatives + g_nsamplesFound = Osd::CpuEvaluator::EvalPatches( + g_vertexData, g_idesc, + g_outVertexData, g_odesc, + g_outDerivatives, g_duDesc, + g_outDerivatives, g_dvDesc, + (int)g_patchCoords.size(), + &g_patchCoords[0], + g_patchTable, NULL); + } else { + // evaluate positions + g_nsamplesFound = Osd::CpuEvaluator::EvalPatches( + g_vertexData, g_idesc, + g_outVertexData, g_odesc, + (int)g_patchCoords.size(), + &g_patchCoords[0], + g_patchTable, NULL); } - g_Q->BindVBO(); + // color + if (g_drawMode == kUV) { + // store patchCoords as colors + float *p = g_outVertexData->BindCpuBuffer() + g_vdesc.offset; + for (int i = 0; i < (int)g_patchCoords.size(); ++i) { + p[0] = g_patchCoords[i].s; + p[1] = g_patchCoords[i].t; + p[2] = 0; + p += g_vdesc.stride; + } + } else if (g_drawMode == kVARYING) { + // XXX: is this really varying? + Osd::CpuEvaluator::EvalPatches(g_varyingData, g_idesc, + g_outVertexData, g_vdesc, + (int)g_patchCoords.size(), + &g_patchCoords[0], + g_patchTable, NULL); + } s.Stop(); @@ -349,46 +388,46 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) { Far::TopologyRefiner::AdaptiveOptions options(level); g_topologyRefiner->RefineAdaptive(options); - // Generate stencil tables to update the bi-cubic patches control + // Generate stencil table to update the bi-cubic patches control // vertices after they have been re-posed (both for vertex & varying // interpolation) - Far::StencilTablesFactory::Options soptions; + Far::StencilTableFactory::Options soptions; soptions.generateOffsets=true; soptions.generateIntermediateLevels=true; - Far::StencilTables const * vertexStencils = - Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions); + Far::StencilTable const * vertexStencils = + Far::StencilTableFactory::Create(*g_topologyRefiner, soptions); - soptions.interpolationMode = Far::StencilTablesFactory::INTERPOLATE_VARYING; - Far::StencilTables const * varyingStencils = - Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions); + soptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_VARYING; + Far::StencilTable const * varyingStencils = + Far::StencilTableFactory::Create(*g_topologyRefiner, soptions); - // Generate bi-cubic patch tables for the limit surface - Far::PatchTablesFactory::Options poptions; + // Generate bi-cubic patch table for the limit surface + Far::PatchTableFactory::Options poptions; poptions.SetEndCapType( - Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS); + Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS); - Far::PatchTables const * patchTables = - Far::PatchTablesFactory::Create(*g_topologyRefiner, poptions); + Far::PatchTable const * patchTable = + Far::PatchTableFactory::Create(*g_topologyRefiner, poptions); // append endcap stencils - if (Far::StencilTables const *endCapVertexStencilTables = - patchTables->GetEndCapVertexStencilTables()) { - Far::StencilTables const *tables = - Far::StencilTablesFactory::AppendEndCapStencilTables( + if (Far::StencilTable const *endCapVertexStencilTable = + patchTable->GetEndCapVertexStencilTable()) { + Far::StencilTable const *table = + Far::StencilTableFactory::AppendEndCapStencilTable( *g_topologyRefiner, - vertexStencils, endCapVertexStencilTables); + vertexStencils, endCapVertexStencilTable); delete vertexStencils; - vertexStencils = tables; + vertexStencils = table; } - if (Far::StencilTables const *endCapVaryingStencilTables = - patchTables->GetEndCapVaryingStencilTables()) { - Far::StencilTables const *tables = - Far::StencilTablesFactory::AppendEndCapStencilTables( + if (Far::StencilTable const *endCapVaryingStencilTable = + patchTable->GetEndCapVaryingStencilTable()) { + Far::StencilTable const *table = + Far::StencilTableFactory::AppendEndCapStencilTable( *g_topologyRefiner, - varyingStencils, endCapVaryingStencilTables); + varyingStencils, endCapVaryingStencilTable); delete varyingStencils; - varyingStencils = tables; + varyingStencils = table; } // total number of vertices = coarse verts + refined verts + gregory basis verts @@ -400,12 +439,12 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) { if (g_varyingStencils) delete g_varyingStencils; g_varyingStencils = varyingStencils; - if (g_patchTables) delete g_patchTables; - g_patchTables = patchTables; + if (g_patchTable) delete g_patchTable; + g_patchTable = patchTable; // Create a far patch map if (g_patchMap) delete g_patchMap; - g_patchMap = new Far::PatchMap(*g_patchTables); + g_patchMap = new Far::PatchMap(*g_patchTable); } { // Create vertex primvar buffer for the CVs @@ -422,45 +461,22 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) { } // Create output buffers for the limit samples (position & tangents) - delete g_Q; - g_Q = Osd::CpuGLVertexBuffer::Create(6, g_nparticles); - memset( g_Q->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float)); + delete g_outVertexData; + g_outVertexData = Osd::CpuGLVertexBuffer::Create(6, g_nparticles); + memset(g_outVertexData->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float)); if (g_drawMode==kRANDOM) { - createRandomColors(g_nparticles, 6, g_Q->BindCpuBuffer()+3); + createRandomColors(g_nparticles, 6, g_outVertexData->BindCpuBuffer()+3); } - delete g_dQs; - g_dQs = Osd::CpuGLVertexBuffer::Create(3,g_nparticles); - memset( g_dQs->BindCpuBuffer(), 0, g_nparticles*3*sizeof(float)); - - delete g_dQt; - g_dQt = Osd::CpuGLVertexBuffer::Create(3,g_nparticles); - memset( g_dQt->BindCpuBuffer(), 0, g_nparticles*3*sizeof(float)); + delete g_outDerivatives; + g_outDerivatives = Osd::CpuGLVertexBuffer::Create(6, g_nparticles); + memset(g_outDerivatives->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float)); } updateGeom(); - // Bind g_Q as a GL_POINTS VBO - glBindVertexArray(g_samplesVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_Q->BindVBO()); - - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12); - - glBindVertexArray(0); } -//------------------------------------------------------------------------------ -struct Program { - GLuint program; - GLuint uniformModelViewProjectionMatrix; - GLuint attrPosition; - GLuint attrColor; -} g_defaultProgram; - //------------------------------------------------------------------------------ static void checkGLErrors(std::string const & where = "") { @@ -473,16 +489,6 @@ checkGLErrors(std::string const & where = "") { } } -//------------------------------------------------------------------------------ -static GLuint -compileShader(GLenum shaderType, const char *source) { - GLuint shader = glCreateShader(shaderType); - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); - checkGLErrors("compileShader"); - return shader; -} - //------------------------------------------------------------------------------ static bool linkDefaultProgram() { @@ -497,31 +503,47 @@ linkDefaultProgram() { GLSL_VERSION_DEFINE "in vec3 position;\n" "in vec3 color;\n" + "in vec3 tangentU;\n" + "in vec3 tangentV;\n" "out vec4 fragColor;\n" - "uniform mat4 ModelViewProjectionMatrix;\n" + "out vec3 normal;\n" + "uniform mat4 ModelViewMatrix;\n" + "uniform mat4 ProjectionMatrix;\n" "void main() {\n" " fragColor = vec4(color, 1);\n" - " gl_Position = ModelViewProjectionMatrix * " + // XXX: fix the normal transform + " normal = (ModelViewMatrix * vec4(normalize(cross(tangentU, tangentV)), 0)).xyz;\n" + " gl_Position = ProjectionMatrix * ModelViewMatrix * " " vec4(position, 1);\n" "}\n"; static const char *fsSrc = GLSL_VERSION_DEFINE "in vec4 fragColor;\n" + "in vec3 normal;\n" + "uniform int DrawMode;\n" "out vec4 color;\n" "void main() {\n" - " color = fragColor;\n" + " if (DrawMode == 3) {\n" + " color = vec4(normal*0.5+vec3(0.5), 1);\n" + " } else if (DrawMode == 4) {\n" + " color = vec4(vec3(1)*dot(normal, vec3(0,0,1)), 1);\n" + " } else {\n" + " color = fragColor;\n" + " }\n" "}\n"; GLuint program = glCreateProgram(); - GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vsSrc); - GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fsSrc); + GLuint vertexShader = GLUtils::CompileShader(GL_VERTEX_SHADER, vsSrc); + GLuint fragmentShader = GLUtils::CompileShader(GL_FRAGMENT_SHADER, fsSrc); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glBindAttribLocation(program, 0, "position"); glBindAttribLocation(program, 1, "color"); + glBindAttribLocation(program, 2, "tangentU"); + glBindAttribLocation(program, 3, "tangentV"); glBindFragDataLocation(program, 0, "color"); glLinkProgram(program); @@ -539,10 +561,16 @@ linkDefaultProgram() { } g_defaultProgram.program = program; - g_defaultProgram.uniformModelViewProjectionMatrix = - glGetUniformLocation(program, "ModelViewProjectionMatrix"); + g_defaultProgram.uniformModelViewMatrix = + glGetUniformLocation(program, "ModelViewMatrix"); + g_defaultProgram.uniformProjectionMatrix = + glGetUniformLocation(program, "ProjectionMatrix"); + g_defaultProgram.uniformDrawMode = + glGetUniformLocation(program, "DrawMode"); g_defaultProgram.attrPosition = glGetAttribLocation(program, "position"); g_defaultProgram.attrColor = glGetAttribLocation(program, "color"); + g_defaultProgram.attrTangentU = glGetAttribLocation(program, "tangentU"); + g_defaultProgram.attrTangentV = glGetAttribLocation(program, "tangentV"); return true; } @@ -562,8 +590,11 @@ static void drawCageEdges() { glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, - 1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); + glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix, + 1, GL_FALSE, g_transformData.ModelViewMatrix); + glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix, + 1, GL_FALSE, g_transformData.ProjectionMatrix); + glUniform1i(g_defaultProgram.uniformDrawMode, 0); std::vector vbo; vbo.reserve(g_coarseEdges.size() * 6); @@ -588,6 +619,8 @@ drawCageEdges() { glEnableVertexAttribArray(g_defaultProgram.attrPosition); glEnableVertexAttribArray(g_defaultProgram.attrColor); + glDisableVertexAttribArray(g_defaultProgram.attrTangentU); + glDisableVertexAttribArray(g_defaultProgram.attrTangentV); glVertexAttribPointer(g_defaultProgram.attrPosition, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); glVertexAttribPointer(g_defaultProgram.attrColor, @@ -604,8 +637,11 @@ static void drawCageVertices() { glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, - 1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); + glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix, + 1, GL_FALSE, g_transformData.ModelViewMatrix); + glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix, + 1, GL_FALSE, g_transformData.ProjectionMatrix); + glUniform1i(g_defaultProgram.uniformDrawMode, 0); int numPoints = (int)g_positions.size()/3; std::vector vbo; @@ -642,6 +678,8 @@ drawCageVertices() { glEnableVertexAttribArray(g_defaultProgram.attrPosition); glEnableVertexAttribArray(g_defaultProgram.attrColor); + glDisableVertexAttribArray(g_defaultProgram.attrTangentU); + glDisableVertexAttribArray(g_defaultProgram.attrTangentV); glVertexAttribPointer(g_defaultProgram.attrPosition, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); glVertexAttribPointer(g_defaultProgram.attrColor, @@ -658,19 +696,43 @@ drawCageVertices() { //------------------------------------------------------------------------------ static void drawSamples() { - glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, - 1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); - + glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix, + 1, GL_FALSE, g_transformData.ModelViewMatrix); + glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix, + 1, GL_FALSE, g_transformData.ProjectionMatrix); + glUniform1i(g_defaultProgram.uniformDrawMode, g_drawMode); glBindVertexArray(g_samplesVAO); + glEnableVertexAttribArray(g_defaultProgram.attrPosition); + glEnableVertexAttribArray(g_defaultProgram.attrColor); + glEnableVertexAttribArray(g_defaultProgram.attrTangentU); + glEnableVertexAttribArray(g_defaultProgram.attrTangentV); + + glBindBuffer(GL_ARRAY_BUFFER, g_outVertexData->BindVBO()); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12); + + glBindBuffer(GL_ARRAY_BUFFER, g_outDerivatives->BindVBO()); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12); + + glEnableVertexAttribArray(g_defaultProgram.attrPosition); + glEnableVertexAttribArray(g_defaultProgram.attrColor); + glEnableVertexAttribArray(g_defaultProgram.attrTangentU); + glEnableVertexAttribArray(g_defaultProgram.attrTangentV); + glPointSize(2.0f); glDrawArrays(GL_POINTS, 0, g_nparticles); glPointSize(1.0f); + glDisableVertexAttribArray(g_defaultProgram.attrPosition); + glDisableVertexAttribArray(g_defaultProgram.attrColor); + glDisableVertexAttribArray(g_defaultProgram.attrTangentU); + glDisableVertexAttribArray(g_defaultProgram.attrTangentV); + glBindVertexArray(0); glUseProgram(0); @@ -728,7 +790,8 @@ display() { g_fpsTimer.Start(); g_hud.DrawString(10, -150, "Particle Speed ([) (]): %.1f", g_particles->GetSpeed()); - g_hud.DrawString(10, -120, "# Samples : (%d/%d)", g_nsamplesFound, g_Q->GetNumVertices()); + g_hud.DrawString(10, -120, "# Samples : (%d/%d)", + g_nsamplesFound, g_outVertexData->GetNumVertices()); g_hud.DrawString(10, -100, "Compute : %.3f ms", g_computeTime); g_hud.DrawString(10, -80, "Eval : %.3f ms", g_evalTime * 1000.f); g_hud.DrawString(10, -60, "GPU Draw : %.3f ms", drawGpuTime); @@ -944,6 +1007,8 @@ initHUD() { g_hud.AddPullDownButton(shading_pulldown, "Random", kRANDOM, g_drawMode==kRANDOM); g_hud.AddPullDownButton(shading_pulldown, "(u,v)", kUV, g_drawMode==kUV); g_hud.AddPullDownButton(shading_pulldown, "Varying", kVARYING, g_drawMode==kVARYING); + g_hud.AddPullDownButton(shading_pulldown, "Normal", kNORMAL, g_drawMode==kNORMAL); + g_hud.AddPullDownButton(shading_pulldown, "Shade", kSHADE, g_drawMode==kSHADE); g_hud.AddPullDownButton(shading_pulldown, "FaceVarying", kFACEVARYING, g_drawMode==kFACEVARYING); for (int i = 1; i < 11; ++i) { diff --git a/examples/glEvalLimit/particles.cpp b/examples/glEvalLimit/particles.cpp index 2f8904a0..5dee362d 100644 --- a/examples/glEvalLimit/particles.cpp +++ b/examples/glEvalLimit/particles.cpp @@ -70,14 +70,15 @@ STParticles::STParticles(Refiner const & refiner, int nparticles, bool centered) { // initialize topology adjacency _adjacency.resize(nptexfaces); - int nfaces = refiner.GetNumFaces(0), + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0); + + int nfaces = refBaseLevel.GetNumFaces(), adjfaces[4], adjedges[4]; for (int face=0, ptexface=0; face const & fvarSrcData) { Release(); OpenSubdiv::Far::ConstIndexArray indices = - patchTables->GetFVarPatchesValues(0); + patchTable->GetFVarPatchesValues(0); // expand fvardata to per-patch array std::vector data; @@ -280,13 +280,15 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner const & refiner, typedef OpenSubdiv::Far::ConstIndexArray IndexArray; + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0); + // calc normal vectors int nverts = (int)pos.size()/3; - int nfaces = refiner.GetNumFaces(0); + int nfaces = refBaseLevel.GetNumFaces(); for (int face = 0; face < nfaces; ++face) { - IndexArray fverts = refiner.GetFaceVertices(0, face); + IndexArray fverts = refBaseLevel.GetFaceVertices(face); assert(fverts.size()>=2); @@ -366,22 +368,23 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark) OpenSubdiv::Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) - int nedges = refiner->GetNumEdges(0), - nverts = refiner->GetNumVertices(0); + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + int nedges = refBaseLevel.GetNumEdges(), + nverts = refBaseLevel.GetNumVertices(); g_coarseEdges.resize(nedges*2); g_coarseEdgeSharpness.resize(nedges); g_coarseVertexSharpness.resize(nverts); for(int i=0; iGetEdgeVertices(0, i); + IndexArray verts = refBaseLevel.GetEdgeVertices(i); g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2+1]=verts[1]; - g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); + g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i); } for(int i=0; iGetVertexSharpness(0, i); + g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i); } g_orgPositions=shape->verts; @@ -404,7 +407,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark) delete g_mesh; g_mesh = new OpenSubdiv::Osd::Mesh( refiner, @@ -417,7 +420,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark) InterpolateFVarData(*refiner, *shape, fvarData); // set fvardata to texture buffer - g_fvarData.Create(g_mesh->GetFarPatchTables(), + g_fvarData.Create(g_mesh->GetFarPatchTable(), shape->GetFVarWidth(), fvarData); delete shape; diff --git a/examples/glImaging/glImaging.cpp b/examples/glImaging/glImaging.cpp index f145db90..1e0c38fb 100755 --- a/examples/glImaging/glImaging.cpp +++ b/examples/glImaging/glImaging.cpp @@ -232,7 +232,7 @@ createOsdMesh(std::string const &kernel, { if (kernel == "CPU") { return new Osd::Mesh( refiner, @@ -242,7 +242,7 @@ createOsdMesh(std::string const &kernel, #ifdef OPENSUBDIV_HAS_OPENMP } else if (kernel == "OPENMP") { return new Osd::Mesh( refiner, @@ -253,7 +253,7 @@ createOsdMesh(std::string const &kernel, #ifdef OPENSUBDIV_HAS_TBB } else if (kernel == "TBB") { return new Osd::Mesh( refiner, @@ -264,7 +264,7 @@ createOsdMesh(std::string const &kernel, #ifdef OPENSUBDIV_HAS_OPENCL } else if(kernel == "CL") { return new Osd::Mesh( @@ -278,7 +278,7 @@ createOsdMesh(std::string const &kernel, #ifdef OPENSUBDIV_HAS_CUDA } else if(kernel == "CUDA") { return new Osd::Mesh( refiner, @@ -289,7 +289,7 @@ createOsdMesh(std::string const &kernel, #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK } else if(kernel == "XFB") { return new Osd::Mesh( refiner, @@ -300,7 +300,7 @@ createOsdMesh(std::string const &kernel, #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE } else if(kernel == "GLSL") { return new Osd::Mesh( refiner, diff --git a/examples/glPaintTest/glPaintTest.cpp b/examples/glPaintTest/glPaintTest.cpp index 57f41a19..d75f1039 100644 --- a/examples/glPaintTest/glPaintTest.cpp +++ b/examples/glPaintTest/glPaintTest.cpp @@ -238,7 +238,7 @@ createOsdMesh() { bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive); g_mesh = new OpenSubdiv::Osd::Mesh( refiner, 3, 0, g_level, bits); diff --git a/examples/glPtexViewer/glPtexViewer.cpp b/examples/glPtexViewer/glPtexViewer.cpp index 1e572dbc..1a27fd98 100644 --- a/examples/glPtexViewer/glPtexViewer.cpp +++ b/examples/glPtexViewer/glPtexViewer.cpp @@ -322,13 +322,15 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner * refiner, typedef OpenSubdiv::Far::ConstIndexArray IndexArray; + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + // calc normal vectors - int nverts = refiner->GetNumVertices(0), - nfaces = refiner->GetNumFaces(0); + int nverts = refBaseLevel.GetNumVertices(), + nfaces = refBaseLevel.GetNumFaces(); for (int face = 0; face < nfaces; ++face) { - IndexArray fverts = refiner->GetFaceVertices(0, face); + IndexArray fverts = refBaseLevel.GetFaceVertices(face); float const * p0 = &pos[fverts[0]*3], * p1 = &pos[fverts[1]*3], @@ -907,10 +909,12 @@ createOsdMesh(int level, int kernel) { // save coarse topology (used for coarse mesh drawing) // create cage edge index - int nedges = refiner->GetNumEdges(0); + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + + int nedges = refBaseLevel.GetNumEdges(); std::vector edgeIndices(nedges*2); for(int i=0; iGetEdgeVertices(0, i); + IndexArray verts = refBaseLevel.GetEdgeVertices(i); edgeIndices[i*2 ]=verts[0]; edgeIndices[i*2+1]=verts[1]; } @@ -935,7 +939,7 @@ createOsdMesh(int level, int kernel) { if (kernel == kCPU) { g_mesh = new OpenSubdiv::Osd::Mesh( refiner, @@ -945,7 +949,7 @@ createOsdMesh(int level, int kernel) { #ifdef OPENSUBDIV_HAS_OPENMP } else if (kernel == kOPENMP) { g_mesh = new OpenSubdiv::Osd::Mesh( refiner, @@ -956,7 +960,7 @@ createOsdMesh(int level, int kernel) { #ifdef OPENSUBDIV_HAS_TBB } else if (kernel == kTBB) { g_mesh = new OpenSubdiv::Osd::Mesh( refiner, @@ -968,7 +972,7 @@ createOsdMesh(int level, int kernel) { } else if (kernel == kCL) { static OpenSubdiv::Osd::EvaluatorCacheT clEvaluatorCache; g_mesh = new OpenSubdiv::Osd::Mesh( @@ -982,7 +986,7 @@ createOsdMesh(int level, int kernel) { #ifdef OPENSUBDIV_HAS_CUDA } else if (kernel == kCUDA) { g_mesh = new OpenSubdiv::Osd::Mesh( refiner, @@ -994,7 +998,7 @@ createOsdMesh(int level, int kernel) { } else if (kernel == kGLSL) { static OpenSubdiv::Osd::EvaluatorCacheT glXFBEvaluatorCache; g_mesh = new OpenSubdiv::Osd::Mesh( refiner, @@ -1007,7 +1011,7 @@ createOsdMesh(int level, int kernel) { } else if (kernel == kGLSLCompute) { static OpenSubdiv::Osd::EvaluatorCacheT glComputeEvaluatorCache; g_mesh = new OpenSubdiv::Osd::Mesh( refiner, diff --git a/examples/glShareTopology/glShareTopology.cpp b/examples/glShareTopology/glShareTopology.cpp index b8809e00..8e89433e 100644 --- a/examples/glShareTopology/glShareTopology.cpp +++ b/examples/glShareTopology/glShareTopology.cpp @@ -43,7 +43,7 @@ GLFWwindow* g_window=0; GLFWmonitor* g_primary=0; #include -#include +#include #include #include @@ -891,31 +891,31 @@ rebuildTopology() { if (g_kernel == kCPU) { g_scene = new Scene(g_options); + Far::StencilTable>(g_options); #ifdef OPENSUBDIV_HAS_OPENMP } else if (g_kernel == kOPENMP) { g_scene = new Scene(g_options); + Far::StencilTable>(g_options); #endif #ifdef OPENSUBDIV_HAS_TBB } else if (g_kernel == kTBB) { g_scene = new Scene(g_options); + Far::StencilTable>(g_options); #endif #ifdef OPENSUBDIV_HAS_CUDA } else if (g_kernel == kCUDA) { g_scene = new Scene(g_options); + Osd::CudaStencilTable>(g_options); #endif #ifdef OPENSUBDIV_HAS_OPENCL } else if (g_kernel == kCL) { static Osd::EvaluatorCacheT clEvaluatorCache; g_scene = new Scene(g_options, &clEvaluatorCache, &g_clDeviceContext); #endif @@ -924,14 +924,14 @@ rebuildTopology() { static Osd::EvaluatorCacheT glXFBEvaluatorCache; g_scene = new Scene(g_options, &glXFBEvaluatorCache); + Osd::GLStencilTableTBO>(g_options, &glXFBEvaluatorCache); #endif #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE } else if (g_kernel == kGLSLCompute) { static Osd::EvaluatorCacheT glComputeEvaluatorCache; g_scene = new Scene(g_options, &glComputeEvaluatorCache); + Osd::GLStencilTableSSBO>(g_options, &glComputeEvaluatorCache); #endif } diff --git a/examples/glShareTopology/meshRefiner.h b/examples/glShareTopology/meshRefiner.h index a556bdc4..fe81d18b 100644 --- a/examples/glShareTopology/meshRefiner.h +++ b/examples/glShareTopology/meshRefiner.h @@ -29,17 +29,17 @@ template class MeshRefiner { public: typedef EVALUATOR Evaluator; - typedef STENCIL_TABLES StencilTables; + typedef STENCIL_TABLE StencilTable; typedef DEVICE_CONTEXT DeviceContext; typedef OpenSubdiv::Osd::EvaluatorCacheT EvaluatorCache; - MeshRefiner(OpenSubdiv::Far::StencilTables const * vertexStencils, //XXX: takes ownership - OpenSubdiv::Far::StencilTables const * varyingStencils, + MeshRefiner(OpenSubdiv::Far::StencilTable const * vertexStencils, //XXX: takes ownership + OpenSubdiv::Far::StencilTable const * varyingStencils, int numControlVertices, EvaluatorCache * evaluatorCache = NULL, DeviceContext * deviceContext = NULL) @@ -49,9 +49,9 @@ public: _numControlVertices = numControlVertices; _numVertices = numControlVertices + vertexStencils->GetNumStencils(); - _vertexStencils = OpenSubdiv::Osd::convertToCompatibleStencilTables( + _vertexStencils = OpenSubdiv::Osd::convertToCompatibleStencilTable( vertexStencils, deviceContext); - _varyingStencils = OpenSubdiv::Osd::convertToCompatibleStencilTables( + _varyingStencils = OpenSubdiv::Osd::convertToCompatibleStencilTable( varyingStencils, deviceContext); } @@ -137,8 +137,8 @@ private: int _numVertices; int _numControlVertices; - StencilTables const *_vertexStencils; - StencilTables const *_varyingStencils; + StencilTable const *_vertexStencils; + StencilTable const *_varyingStencils; EvaluatorCache * _evaluatorCache; DeviceContext *_deviceContext; }; diff --git a/examples/glShareTopology/scene.h b/examples/glShareTopology/scene.h index c173f759..987d3bb5 100644 --- a/examples/glShareTopology/scene.h +++ b/examples/glShareTopology/scene.h @@ -91,8 +91,8 @@ public: } virtual size_t createMeshRefiner( - OpenSubdiv::Far::StencilTables const * vertexStencils, - OpenSubdiv::Far::StencilTables const * varyingStencils, + OpenSubdiv::Far::StencilTable const * vertexStencils, + OpenSubdiv::Far::StencilTable const * varyingStencils, int numControlVertices) { MeshRefinerType *meshRefiner = diff --git a/examples/glShareTopology/sceneBase.cpp b/examples/glShareTopology/sceneBase.cpp index 147b5df4..3ae832f0 100644 --- a/examples/glShareTopology/sceneBase.cpp +++ b/examples/glShareTopology/sceneBase.cpp @@ -24,8 +24,8 @@ #include #include -#include -#include +#include +#include #include "sceneBase.h" using namespace OpenSubdiv; @@ -47,7 +47,7 @@ SceneBase::~SceneBase() { void SceneBase::AddTopology(Shape const *shape, int level, bool varying) { - Far::PatchTables const * patchTable = NULL; + Far::PatchTable const * patchTable = NULL; int numVerts = createStencilTable(shape, level, varying, &patchTable); // centering rest position @@ -92,7 +92,7 @@ SceneBase::AddTopology(Shape const *shape, int level, bool varying) { int SceneBase::createStencilTable(Shape const *shape, int level, bool varying, - OpenSubdiv::Far::PatchTables const **patchTablesOut) { + OpenSubdiv::Far::PatchTable const **patchTableOut) { Far::TopologyRefiner * refiner = 0; { @@ -115,61 +115,61 @@ SceneBase::createStencilTable(Shape const *shape, int level, bool varying, refiner->RefineUniform(options); } - Far::StencilTables const * vertexStencils=0, * varyingStencils=0; + Far::StencilTable const * vertexStencils=0, * varyingStencils=0; { - Far::StencilTablesFactory::Options options; + Far::StencilTableFactory::Options options; options.generateOffsets = true; options.generateIntermediateLevels = _options.adaptive; - vertexStencils = Far::StencilTablesFactory::Create(*refiner, options); + vertexStencils = Far::StencilTableFactory::Create(*refiner, options); if (varying) { - varyingStencils = Far::StencilTablesFactory::Create(*refiner, options); + varyingStencils = Far::StencilTableFactory::Create(*refiner, options); } assert(vertexStencils); } - Far::PatchTables const * patchTables = NULL; + Far::PatchTable const * patchTable = NULL; { - Far::PatchTablesFactory::Options poptions(level); + Far::PatchTableFactory::Options poptions(level); if (_options.endCap == kEndCapBSplineBasis) { poptions.SetEndCapType( - Far::PatchTablesFactory::Options::ENDCAP_BSPLINE_BASIS); + Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS); } else { poptions.SetEndCapType( - Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS); + Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS); } - patchTables = Far::PatchTablesFactory::Create(*refiner, poptions); + patchTable = Far::PatchTableFactory::Create(*refiner, poptions); } - *patchTablesOut = patchTables; + *patchTableOut = patchTable; // append gregory vertices into stencils { - if (Far::StencilTables const *vertexStencilsWithEndCap = - Far::StencilTablesFactory::AppendEndCapStencilTables( + if (Far::StencilTable const *vertexStencilsWithEndCap = + Far::StencilTableFactory::AppendEndCapStencilTable( *refiner, vertexStencils, - patchTables->GetEndCapVertexStencilTables())) { + patchTable->GetEndCapVertexStencilTable())) { delete vertexStencils; vertexStencils = vertexStencilsWithEndCap; } if (varyingStencils) { - if (Far::StencilTables const *varyingStencilsWithEndCap = - Far::StencilTablesFactory::AppendEndCapStencilTables( + if (Far::StencilTable const *varyingStencilsWithEndCap = + Far::StencilTableFactory::AppendEndCapStencilTable( *refiner, varyingStencils, - patchTables->GetEndCapVaryingStencilTables())) { + patchTable->GetEndCapVaryingStencilTable())) { delete varyingStencils; varyingStencils = varyingStencilsWithEndCap; } } } - int numControlVertices = refiner->GetNumVertices(0); + int numControlVertices = refiner->GetLevel(0).GetNumVertices(); _stencilTableSize = createMeshRefiner(vertexStencils, varyingStencils, numControlVertices); - // note: refiner takes ownerships of vertexStencils/ varyingStencils, patchTables + // note: refiner takes ownerships of vertexStencils/ varyingStencils, patchTable delete refiner; return numControlVertices + vertexStencils->GetNumStencils(); @@ -214,9 +214,9 @@ SceneBase::CreateIndexBuffer() { int numTopologies = (int)_topologies.size(); for (int i = 0; i < numTopologies; ++i) { - Far::PatchTables const *patchTables = _patchTables[i]; + Far::PatchTable const *patchTable = _patchTables[i]; - int nPatchArrays = patchTables->GetNumPatchArrays(); + int nPatchArrays = patchTable->GetNumPatchArrays(); _topologies[i].patchArrays.clear(); @@ -224,21 +224,21 @@ SceneBase::CreateIndexBuffer() { for (int j = 0; j < nPatchArrays; ++j) { SceneBase::PatchArray patchArray; - patchArray.desc = patchTables->GetPatchArrayDescriptor(j); - patchArray.numPatches = patchTables->GetNumPatches(j); + patchArray.desc = patchTable->GetPatchArrayDescriptor(j); + patchArray.numPatches = patchTable->GetNumPatches(j); patchArray.indexOffset = (int)buffer.size(); patchArray.primitiveIDOffset = (int)ppBuffer.size()/3; _topologies[i].patchArrays.push_back(patchArray); // indices - Far::ConstIndexArray indices = patchTables->GetPatchArrayVertices(j); + Far::ConstIndexArray indices = patchTable->GetPatchArrayVertices(j); for (int k = 0; k < indices.size(); ++k) { buffer.push_back(indices[k]); } // patchParams - Far::ConstPatchParamArray patchParams = patchTables->GetPatchParams(j); + Far::ConstPatchParamArray patchParams = patchTable->GetPatchParams(j); // XXX: needs sharpness interface for patcharray or put sharpness into patchParam. for (int k = 0; k < patchParams.size(); ++k) { float sharpness = 0.0; @@ -248,26 +248,26 @@ SceneBase::CreateIndexBuffer() { } } #if 0 - // XXX: we'll remove below APIs from Far::PatchTables. + // XXX: we'll remove below APIs from Far::PatchTable. // use GetPatchParams(patchArray) instead as above. // patch param (all in one) - Far::PatchParamTable const &patchParamTables = - patchTables->GetPatchParamTable(); + Far::PatchParamTable const &patchParamTable = + patchTable->GetPatchParamTable(); std::vector const &sharpnessIndexTable = - patchTables->GetSharpnessIndexTable(); + patchTable->GetSharpnessIndexTable(); std::vector const &sharpnessValues = - patchTables->GetSharpnessValues(); + patchTable->GetSharpnessValues(); - int npatches = (int)patchParamTables.size(); + int npatches = (int)patchParamTable.size(); for (int i = 0; i < npatches; ++i) { float sharpness = 0.0; if (i < (int)sharpnessIndexTable.size()) { sharpness = sharpnessIndexTable[i] >= 0 ? sharpnessValues[sharpnessIndexTable[i]] : 0.0f; } - ppBuffer.push_back(patchParamTables[i].faceIndex); - ppBuffer.push_back(patchParamTables[i].bitField.field); + ppBuffer.push_back(patchParamTable[i].faceIndex); + ppBuffer.push_back(patchParamTable[i].bitField.field); ppBuffer.push_back(*((unsigned int *)&sharpness)); } #endif diff --git a/examples/glShareTopology/sceneBase.h b/examples/glShareTopology/sceneBase.h index 39a4531f..fde7a0d8 100644 --- a/examples/glShareTopology/sceneBase.h +++ b/examples/glShareTopology/sceneBase.h @@ -26,7 +26,7 @@ #define OPENSUBDIV_EXAMPLES_GL_SHARE_TOPOLOGY_SCENE_BASE_H #include -#include +#include #include #include @@ -135,20 +135,20 @@ public: protected: int createStencilTable(Shape const *shape, int level, bool varying, - OpenSubdiv::Far::PatchTables const **patchTableOut); + OpenSubdiv::Far::PatchTable const **patchTableOut); void buildBatches(); virtual size_t createMeshRefiner( - OpenSubdiv::Far::StencilTables const * vertexStencils, - OpenSubdiv::Far::StencilTables const * varyingStencils, + OpenSubdiv::Far::StencilTable const * vertexStencils, + OpenSubdiv::Far::StencilTable const * varyingStencils, int numControlVertices) = 0; Options _options; std::vector _objects; std::vector _topologies; - std::vector _patchTables; + std::vector _patchTables; GLuint _indexBuffer; GLuint _patchParamTexture; BatchVector _batches; diff --git a/examples/glStencilViewer/glStencilViewer.cpp b/examples/glStencilViewer/glStencilViewer.cpp index 25d92836..d7497b2f 100644 --- a/examples/glStencilViewer/glStencilViewer.cpp +++ b/examples/glStencilViewer/glStencilViewer.cpp @@ -48,9 +48,9 @@ GLFWmonitor* g_primary=0; #include "../common/glUtils.h" #include "../common/glHud.h" -#include +#include #include -#include +#include #include #include @@ -136,7 +136,7 @@ GLhud g_hud; int g_currentShape = 0; //------------------------------------------------------------------------------ -Far::LimitStencilTables const * g_controlStencils; +Far::LimitStencilTable const * g_controlStencils; // Control vertex positions (P(xyz)) Osd::CpuVertexBuffer * g_controlValues=0; @@ -271,7 +271,7 @@ static void createMesh(ShapeDesc const & shapeDesc, int level) { typedef Far::ConstIndexArray IndexArray; - typedef Far::LimitStencilTablesFactory::LocationArray LocationArray; + typedef Far::LimitStencilTableFactory::LocationArray LocationArray; Shape const * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme); @@ -284,22 +284,24 @@ createMesh(ShapeDesc const & shapeDesc, int level) { OpenSubdiv::Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) - int nedges = refiner->GetNumEdges(0), - nverts = refiner->GetNumVertices(0); + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + + int nedges = refBaseLevel.GetNumEdges(), + nverts = refBaseLevel.GetNumVertices(); g_coarseEdges.resize(nedges*2); g_coarseEdgeSharpness.resize(nedges); g_coarseVertexSharpness.resize(nverts); for(int i=0; iGetEdgeVertices(0, i); + IndexArray verts = refBaseLevel.GetEdgeVertices(i); g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2+1]=verts[1]; - g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); + g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i); } for(int i=0; iGetVertexSharpness(0, i); + g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i); } g_orgPositions=shape->verts; @@ -338,7 +340,7 @@ createMesh(ShapeDesc const & shapeDesc, int level) { } delete g_controlStencils; - g_controlStencils = Far::LimitStencilTablesFactory::Create(*refiner, locs); + g_controlStencils = Far::LimitStencilTableFactory::Create(*refiner, locs); delete [] u; delete [] v; diff --git a/examples/glViewer/glViewer.cpp b/examples/glViewer/glViewer.cpp index e5f5571c..e39c24d2 100644 --- a/examples/glViewer/glViewer.cpp +++ b/examples/glViewer/glViewer.cpp @@ -283,11 +283,11 @@ struct FVarData glDeleteTextures(1, &textureBuffer); textureBuffer = 0; } - void Create(OpenSubdiv::Far::PatchTables const *patchTables, + void Create(OpenSubdiv::Far::PatchTable const *patchTable, int fvarWidth, std::vector const & fvarSrcData) { Release(); OpenSubdiv::Far::ConstIndexArray indices = - patchTables->GetFVarPatchesValues(0); + patchTable->GetFVarPatchesValues(0); // expand fvardata to per-patch array std::vector data; @@ -555,22 +555,24 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) - int nedges = refiner->GetNumEdges(0), - nverts = refiner->GetNumVertices(0); + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + + int nedges = refBaseLevel.GetNumEdges(), + nverts = refBaseLevel.GetNumVertices(); g_coarseEdges.resize(nedges*2); g_coarseEdgeSharpness.resize(nedges); g_coarseVertexSharpness.resize(nverts); for(int i=0; iGetEdgeVertices(0, i); + IndexArray verts = refBaseLevel.GetEdgeVertices(i); g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2+1]=verts[1]; - g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); + g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i); } for(int i=0; iGetVertexSharpness(0, i); + g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i); } g_orgPositions=shape->verts; @@ -602,7 +604,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= if (kernel == kCPU) { g_mesh = new Osd::Mesh( refiner, @@ -612,7 +614,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= #ifdef OPENSUBDIV_HAS_OPENMP } else if (kernel == kOPENMP) { g_mesh = new Osd::Mesh( refiner, @@ -623,7 +625,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= #ifdef OPENSUBDIV_HAS_TBB } else if (kernel == kTBB) { g_mesh = new Osd::Mesh( refiner, @@ -636,7 +638,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= // CLKernel static Osd::EvaluatorCacheT clEvaluatorCache; g_mesh = new Osd::Mesh( @@ -650,7 +652,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= #ifdef OPENSUBDIV_HAS_CUDA } else if(kernel == kCUDA) { g_mesh = new Osd::Mesh( refiner, @@ -662,7 +664,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= } else if(kernel == kGLSL) { static Osd::EvaluatorCacheT glXFBEvaluatorCache; g_mesh = new Osd::Mesh( refiner, @@ -675,7 +677,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= } else if(kernel == kGLSLCompute) { static Osd::EvaluatorCacheT glComputeEvaluatorCache; g_mesh = new Osd::Mesh( refiner, @@ -697,7 +699,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= InterpolateFVarData(*refiner, *shape, fvarData); // set fvardata to texture buffer - g_fvarData.Create(g_mesh->GetFarPatchTables(), + g_fvarData.Create(g_mesh->GetFarPatchTable(), shape->GetFVarWidth(), fvarData); } @@ -706,7 +708,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= g_legacyGregoryPatchTable = NULL; if (g_endCap == kEndCapLegacyGregory) { g_legacyGregoryPatchTable = - Osd::GLLegacyGregoryPatchTable::Create(g_mesh->GetFarPatchTables()); + Osd::GLLegacyGregoryPatchTable::Create(g_mesh->GetFarPatchTable()); } if (not doAnim) { @@ -1320,7 +1322,7 @@ display() { g_mesh->GetPatchTable()->GetPatchArrays(); // patch drawing - int patchCount[13]; // [Type] (see far/patchTables.h) + int patchCount[13]; // [Type] (see far/patchTable.h) int numTotalPatches = 0; int numDrawCalls = 0; memset(patchCount, 0, sizeof(patchCount)); diff --git a/examples/glViewer/init_shapes.h b/examples/glViewer/init_shapes.h index 4490722f..b3347c5c 100644 --- a/examples/glViewer/init_shapes.h +++ b/examples/glViewer/init_shapes.h @@ -77,6 +77,12 @@ static std::vector g_defaultShapes; #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include @@ -106,6 +112,9 @@ static std::vector g_defaultShapes; #include #include #include +#include +#include +#include //------------------------------------------------------------------------------ static void initShapes() { @@ -145,6 +154,12 @@ static void initShapes() { g_defaultShapes.push_back( ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark ) ); g_defaultShapes.push_back( ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/ ) ); g_defaultShapes.push_back( ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark ) ); + g_defaultShapes.push_back( ShapeDesc("catmark_pole8", catmark_pole8, kCatmark ) ); + g_defaultShapes.push_back( ShapeDesc("catmark_pole64", catmark_pole64, kCatmark ) ); + g_defaultShapes.push_back( ShapeDesc("catmark_pole360", catmark_pole360, kCatmark ) ); + g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark ) ); + g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark ) ); + g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark ) ); g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) ); g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) ); g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) ); @@ -177,5 +192,8 @@ static void initShapes() { g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) ); g_defaultShapes.push_back( ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop ) ); g_defaultShapes.push_back( ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop ) ); + g_defaultShapes.push_back( ShapeDesc("loop_pole8", loop_pole8, kLoop ) ); + g_defaultShapes.push_back( ShapeDesc("loop_pole64", loop_pole64, kLoop ) ); + g_defaultShapes.push_back( ShapeDesc("loop_pole360", loop_pole360, kLoop ) ); } //------------------------------------------------------------------------------ diff --git a/examples/glViewer/shader.glsl b/examples/glViewer/shader.glsl index fb1b27ee..02d9d8c4 100644 --- a/examples/glViewer/shader.glsl +++ b/examples/glViewer/shader.glsl @@ -112,6 +112,9 @@ OSD_USER_VARYING_ATTRIBUTE_DECLARE out block { OutputVertex v; +#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE + float sharpness; +#endif OSD_USER_VARYING_DECLARE } outpt; @@ -119,6 +122,9 @@ void main() { outpt.v.position = ModelViewMatrix * position; outpt.v.patchCoord = vec4(0); +#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE + outpt.sharpness = 0; +#endif OSD_USER_VARYING_PER_VERTEX(); } diff --git a/examples/mayaPolySmooth/mayaPolySmooth.cpp b/examples/mayaPolySmooth/mayaPolySmooth.cpp index 97a2712a..d2ca222b 100644 --- a/examples/mayaPolySmooth/mayaPolySmooth.cpp +++ b/examples/mayaPolySmooth/mayaPolySmooth.cpp @@ -61,7 +61,7 @@ // OpenSubdiv includes #include -#include +#include #include #include @@ -523,8 +523,12 @@ convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner, typedef OpenSubdiv::Far::ConstIndexArray IndexArray; - int maxlevel = refiner.GetMaxLevel(), - nfaces = refiner.GetNumFaces(maxlevel); + int maxlevel = refiner.GetMaxLevel(); + + OpenSubdiv::Far::TopologyLevel const & refLastLevel + = refiner.GetLevel(maxlevel); + + int nfaces = refLastLevel.GetNumFaces(); // Init Maya Data @@ -537,18 +541,18 @@ convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner, // -- Face Connects MIntArray faceConnects(nfaces*4); for (int face=0, idx=0; face < nfaces; ++face) { - IndexArray fverts = refiner.GetFaceVertices(maxlevel, face); + IndexArray fverts = refLastLevel.GetFaceVertices(face); for (int vert=0; vert < fverts.size(); ++vert) { faceConnects[idx++] = fverts[vert]; } } // -- Points - MFloatPointArray points(refiner.GetNumVertices(maxlevel)); + MFloatPointArray points(refLastLevel.GetNumVertices()); Vertex const * v = &vertexBuffer.at(0); for (int level=1; level<=maxlevel; ++level) { - int nverts = refiner.GetNumVertices(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]); @@ -652,7 +656,7 @@ MayaPolySmooth::compute( const MPlug& plug, MDataBlock& data ) { reinterpret_cast(inMeshFn.getRawPoints(&status)); std::vector refinedVerts( - refiner->GetNumVerticesTotal() - refiner->GetNumVertices(0)); + refiner->GetNumVerticesTotal() - refiner->GetLevel(0).GetNumVertices()); refiner->Interpolate(controlVerts, &refinedVerts.at(0)); @@ -669,7 +673,7 @@ MayaPolySmooth::compute( const MPlug& plug, MDataBlock& data ) { // Propagate objectGroups from inMesh to outMesh (for per-facet shading, etc) status = createSmoothMesh_objectGroups(inMeshFn, inMeshDat, - newMeshData, subdivisionLevel, refiner->GetNumFaces(subdivisionLevel)); + newMeshData, subdivisionLevel, refiner->GetLevel(subdivisionLevel).GetNumFaces()); // Write to output plug MDataHandle outMeshH = data.outputValue(a_output, &status); diff --git a/opensubdiv/far/CMakeLists.txt b/opensubdiv/far/CMakeLists.txt index d625e040..da0de874 100644 --- a/opensubdiv/far/CMakeLists.txt +++ b/opensubdiv/far/CMakeLists.txt @@ -33,16 +33,17 @@ set(SOURCE_FILES patchBasis.cpp patchDescriptor.cpp patchMap.cpp - patchTables.cpp - patchTablesFactory.cpp + patchTable.cpp + patchTableFactory.cpp ptexIndices.cpp - stencilTablesFactory.cpp + stencilTableFactory.cpp + stencilBuilder.cpp topologyRefiner.cpp topologyRefinerFactory.cpp ) set(PRIVATE_HEADER_FILES - protoStencil.h + stencilBuilder.h ) set(PUBLIC_HEADER_FILES @@ -55,11 +56,11 @@ set(PUBLIC_HEADER_FILES patchDescriptor.h patchParam.h patchMap.h - patchTables.h - patchTablesFactory.h + patchTable.h + patchTableFactory.h ptexIndices.h - stencilTables.h - stencilTablesFactory.h + stencilTable.h + stencilTableFactory.h topologyLevel.h topologyRefiner.h topologyRefinerFactory.h diff --git a/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp b/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp index d457a621..5c7031a2 100644 --- a/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp +++ b/opensubdiv/far/endCapBSplineBasisPatchFactory.cpp @@ -25,7 +25,7 @@ #include "../far/gregoryBasis.h" #include "../far/endCapBSplineBasisPatchFactory.h" #include "../far/error.h" -#include "../far/stencilTablesFactory.h" +#include "../far/stencilTableFactory.h" #include "../far/topologyRefiner.h" #include diff --git a/opensubdiv/far/endCapBSplineBasisPatchFactory.h b/opensubdiv/far/endCapBSplineBasisPatchFactory.h index 97a60f5c..6354fdef 100644 --- a/opensubdiv/far/endCapBSplineBasisPatchFactory.h +++ b/opensubdiv/far/endCapBSplineBasisPatchFactory.h @@ -25,9 +25,8 @@ #ifndef OPENSUBDIV3_FAR_END_CAP_BSPLINE_BASIS_PATCH_FACTORY_H #define OPENSUBDIV3_FAR_END_CAP_BSPLINE_BASIS_PATCH_FACTORY_H -#include "../far/patchTablesFactory.h" +#include "../far/patchTableFactory.h" #include "../far/gregoryBasis.h" -#include "../far/protoStencil.h" #include "../vtr/level.h" namespace OpenSubdiv { @@ -39,7 +38,7 @@ class TopologyRefiner; /// \brief A BSpline endcap factory /// -/// note: This is an internal use class in PatchTablesFactory, and +/// note: This is an internal use class in PatchTableFactory, and /// will be replaced with SdcSchemeWorker for mask coefficients /// and Vtr::Level for topology traversal. /// @@ -70,19 +69,19 @@ public: ConstIndexArray GetPatchPoints( Vtr::Level const * level, Index faceIndex); - /// \brief Create a StencilTables for end patch points, relative to the max + /// \brief Create a StencilTable for end patch points, relative to the max /// subdivision level. /// - StencilTables* CreateVertexStencilTables() const { - return GregoryBasis::CreateStencilTables(_vertexStencils); + StencilTable* CreateVertexStencilTable() const { + return GregoryBasis::CreateStencilTable(_vertexStencils); } - /// \brief Create a StencilTables for end patch varying primvar. + /// \brief Create a StencilTable for end patch varying primvar. /// This table is used as a convenient way to get varying primvars /// populated on end patch points along with positions. /// - StencilTables* CreateVaryingStencilTables() const { - return GregoryBasis::CreateStencilTables(_varyingStencils); + StencilTable* CreateVaryingStencilTable() const { + return GregoryBasis::CreateStencilTable(_varyingStencils); } private: diff --git a/opensubdiv/far/endCapGregoryBasisPatchFactory.cpp b/opensubdiv/far/endCapGregoryBasisPatchFactory.cpp index e3ddcdbf..5c2e362b 100644 --- a/opensubdiv/far/endCapGregoryBasisPatchFactory.cpp +++ b/opensubdiv/far/endCapGregoryBasisPatchFactory.cpp @@ -25,7 +25,7 @@ #include "../far/gregoryBasis.h" #include "../far/endCapGregoryBasisPatchFactory.h" #include "../far/error.h" -#include "../far/stencilTablesFactory.h" +#include "../far/stencilTableFactory.h" #include "../far/topologyRefiner.h" #include @@ -37,21 +37,8 @@ namespace OPENSUBDIV_VERSION { namespace Far { - -static inline bool -checkMaxValence(Vtr::Level const & level) { - if (level.getMaxValence()>EndCapGregoryBasisPatchFactory::GetMaxValence()) { - // The proto-basis closed-form table limits valence to 'MAX_VALENCE' - Error(FAR_RUNTIME_ERROR, - "Vertex valence %d exceeds maximum %d supported", - level.getMaxValence(), EndCapGregoryBasisPatchFactory::GetMaxValence()); - return false; - } - return true; -} - // -// EndCapGregoryBasisPatchFactory for Vertex StencilTables +// EndCapGregoryBasisPatchFactory for Vertex StencilTable // EndCapGregoryBasisPatchFactory::EndCapGregoryBasisPatchFactory( TopologyRefiner const & refiner, bool shareBoundaryVertices) : @@ -62,12 +49,6 @@ EndCapGregoryBasisPatchFactory::EndCapGregoryBasisPatchFactory( assert(not refiner.IsUniform()); } -int -EndCapGregoryBasisPatchFactory::GetMaxValence() { - - return GregoryBasis::MAX_VALENCE; -} - // // Stateless EndCapGregoryBasisPatchFactory // @@ -78,10 +59,6 @@ EndCapGregoryBasisPatchFactory::Create(TopologyRefiner const & refiner, // Gregory patches are end-caps: they only exist on max-level Vtr::Level const & level = refiner.getLevel(refiner.GetMaxLevel()); - if (not checkMaxValence(level)) { - return 0; - } - GregoryBasis::ProtoBasis basis(level, faceIndex, fvarChannel); GregoryBasis * result = new GregoryBasis; basis.Copy(result); @@ -97,10 +74,6 @@ EndCapGregoryBasisPatchFactory::addPatchBasis(Index faceIndex, // Gregory patches only exist on the hight Vtr::Level const & level = _refiner->getLevel(_refiner->GetMaxLevel()); - if (not checkMaxValence(level)) { - return false; - } - // Gather the CVs that influence the Gregory patch and their relative // weights in a basis GregoryBasis::ProtoBasis basis(level, faceIndex); @@ -139,7 +112,7 @@ EndCapGregoryBasisPatchFactory::addPatchBasis(Index faceIndex, ConstIndexArray EndCapGregoryBasisPatchFactory::GetPatchPoints( Vtr::Level const * level, Index faceIndex, - PatchTablesFactory::PatchFaceTag const * levelPatchTags) + PatchTableFactory::PatchFaceTag const * levelPatchTags) { // allocate indices (awkward) // assert(Vtr::INDEX_INVALID==0xFFFFFFFF); diff --git a/opensubdiv/far/endCapGregoryBasisPatchFactory.h b/opensubdiv/far/endCapGregoryBasisPatchFactory.h index 73156a51..5ef68f34 100644 --- a/opensubdiv/far/endCapGregoryBasisPatchFactory.h +++ b/opensubdiv/far/endCapGregoryBasisPatchFactory.h @@ -25,7 +25,7 @@ #ifndef OPENSUBDIV3_FAR_END_CAP_GREGORY_BASIS_PATCH_FACTORY_H #define OPENSUBDIV3_FAR_END_CAP_GREGORY_BASIS_PATCH_FACTORY_H -#include "../far/patchTablesFactory.h" +#include "../far/patchTableFactory.h" #include "../far/gregoryBasis.h" #include "../vtr/level.h" @@ -38,7 +38,7 @@ class TopologyRefiner; /// \brief A specialized factory to gather Gregory basis control vertices /// -/// note: This is an internal use class in PatchTablesFactory, and +/// note: This is an internal use class in PatchTableFactory, and /// will be replaced with SdcSchemeWorker for mask coefficients /// and Vtr::Level for topology traversal. /// @@ -62,10 +62,6 @@ public: static GregoryBasis const * Create(TopologyRefiner const & refiner, Index faceIndex, int fvarChannel=-1); - /// \brief Returns the maximum valence of a vertex in the mesh that the - /// Gregory patches can handle - static int GetMaxValence(); - public: /// @@ -98,21 +94,21 @@ public: /// ConstIndexArray GetPatchPoints( Vtr::Level const * level, Index faceIndex, - PatchTablesFactory::PatchFaceTag const * levelPatchTags); + PatchTableFactory::PatchFaceTag const * levelPatchTags); - /// \brief Create a StencilTables for end patch points, relative to the max + /// \brief Create a StencilTable for end patch points, relative to the max /// subdivision level. /// - StencilTables* CreateVertexStencilTables() const { - return GregoryBasis::CreateStencilTables(_vertexStencils); + StencilTable* CreateVertexStencilTable() const { + return GregoryBasis::CreateStencilTable(_vertexStencils); } - /// \brief Create a StencilTables for end patch varying primvar. + /// \brief Create a StencilTable for end patch varying primvar. /// This table is used as a convenient way to get varying primvars /// populated on end patch points along with positions. /// - StencilTables* CreateVaryingStencilTables() const { - return GregoryBasis::CreateStencilTables(_varyingStencils); + StencilTable* CreateVaryingStencilTable() const { + return GregoryBasis::CreateStencilTable(_varyingStencils); } private: diff --git a/opensubdiv/far/endCapLegacyGregoryPatchFactory.cpp b/opensubdiv/far/endCapLegacyGregoryPatchFactory.cpp index b0ef21aa..7569bdd6 100644 --- a/opensubdiv/far/endCapLegacyGregoryPatchFactory.cpp +++ b/opensubdiv/far/endCapLegacyGregoryPatchFactory.cpp @@ -24,7 +24,7 @@ #include "../far/error.h" #include "../far/endCapLegacyGregoryPatchFactory.h" -#include "../far/patchTables.h" +#include "../far/patchTable.h" #include "../far/topologyRefiner.h" #include "../vtr/level.h" @@ -41,10 +41,10 @@ EndCapLegacyGregoryPatchFactory::EndCapLegacyGregoryPatchFactory( ConstIndexArray EndCapLegacyGregoryPatchFactory::GetPatchPoints( Vtr::Level const * level, Index faceIndex, - PatchTablesFactory::PatchFaceTag const * levelPatchTags, + PatchTableFactory::PatchFaceTag const * levelPatchTags, int levelVertOffset) { - PatchTablesFactory::PatchFaceTag patchTag = levelPatchTags[faceIndex]; + PatchTableFactory::PatchFaceTag patchTag = levelPatchTags[faceIndex]; // Gregory Regular Patch (4 CVs + quad-offsets / valence tables) Vtr::ConstIndexArray faceVerts = level->getFaceVertices(faceIndex); @@ -102,8 +102,8 @@ static void getQuadOffsets( void EndCapLegacyGregoryPatchFactory::Finalize( int maxValence, - PatchTables::QuadOffsetsTable *quadOffsetsTable, - PatchTables::VertexValenceTable *vertexValenceTable) + PatchTable::QuadOffsetsTable *quadOffsetsTable, + PatchTable::VertexValenceTable *vertexValenceTable) { // populate quad offsets @@ -116,18 +116,18 @@ EndCapLegacyGregoryPatchFactory::Finalize( quadOffsetsTable->resize(numTotalGregoryPatches*4); - if (numTotalGregoryPatches > 0) { - PatchTables::QuadOffsetsTable::value_type *p = + if (numTotalGregoryPatches > 0) { + PatchTable::QuadOffsetsTable::value_type *p = &((*quadOffsetsTable)[0]); - for (size_t i = 0; i < numGregoryPatches; ++i) { - getQuadOffsets(level, _gregoryFaceIndices[i], p); - p += 4; - } - for (size_t i = 0; i < numGregoryBoundaryPatches; ++i) { - getQuadOffsets(level, _gregoryBoundaryFaceIndices[i], p); - p += 4; - } - } + for (size_t i = 0; i < numGregoryPatches; ++i) { + getQuadOffsets(level, _gregoryFaceIndices[i], p); + p += 4; + } + for (size_t i = 0; i < numGregoryBoundaryPatches; ++i) { + getQuadOffsets(level, _gregoryBoundaryFaceIndices[i], p); + p += 4; + } + } // populate vertex valences // @@ -144,7 +144,7 @@ EndCapLegacyGregoryPatchFactory::Finalize( // const int SizePerVertex = 2*maxValence + 1; - PatchTables::VertexValenceTable & vTable = (*vertexValenceTable); + PatchTable::VertexValenceTable & vTable = (*vertexValenceTable); vTable.resize(_refiner.GetNumVerticesTotal() * SizePerVertex); int vOffset = 0; diff --git a/opensubdiv/far/endCapLegacyGregoryPatchFactory.h b/opensubdiv/far/endCapLegacyGregoryPatchFactory.h index 867f2b99..30570b31 100644 --- a/opensubdiv/far/endCapLegacyGregoryPatchFactory.h +++ b/opensubdiv/far/endCapLegacyGregoryPatchFactory.h @@ -25,19 +25,19 @@ #ifndef OPENSUBDIV3_FAR_END_CAP_LEGACY_GREGORY_PATCH_FACTORY_H #define OPENSUBDIV3_FAR_END_CAP_LEGACY_GREGORY_PATCH_FACTORY_H -#include "../far/patchTablesFactory.h" +#include "../far/patchTableFactory.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { -class PatchTables; +class PatchTable; class TopologyRefiner; namespace Far { /// \brief This factory generates legacy (OpenSubdiv 2.x) gregory patches. /// -/// note: This is an internal use class in PatchTablesFactory. +/// note: This is an internal use class in PatchTableFactory. /// will be deprecated at some point. /// class EndCapLegacyGregoryPatchFactory { @@ -58,12 +58,12 @@ public: /// @param levelVertOffset relative offset of patch vertex indices /// ConstIndexArray GetPatchPoints(Vtr::Level const * level, Index faceIndex, - PatchTablesFactory::PatchFaceTag const * levelPatchTags, + PatchTableFactory::PatchFaceTag const * levelPatchTags, int levelVertOffset); void Finalize(int maxValence, - PatchTables::QuadOffsetsTable *quadOffsetsTable, - PatchTables::VertexValenceTable *vertexValenceTable); + PatchTable::QuadOffsetsTable *quadOffsetsTable, + PatchTable::VertexValenceTable *vertexValenceTable); private: diff --git a/opensubdiv/far/gregoryBasis.cpp b/opensubdiv/far/gregoryBasis.cpp index f8b5d143..9917be14 100644 --- a/opensubdiv/far/gregoryBasis.cpp +++ b/opensubdiv/far/gregoryBasis.cpp @@ -24,7 +24,7 @@ #include "../far/gregoryBasis.h" #include "../far/error.h" -#include "../far/stencilTablesFactory.h" +#include "../far/stencilTableFactory.h" #include "../far/topologyRefiner.h" #include "../vtr/stackBuffer.h" @@ -129,10 +129,10 @@ inline float csf(Index n, Index j) { } } -GregoryBasis::ProtoBasis::ProtoBasis( - Vtr::Level const & level, Index faceIndex, int fvarChannel) { - - static float ef[MAX_VALENCE-3] = { +inline float computeCoefficient(int valence) { + // precomputed coefficient table up to valence 29 + static float efTable[] = { + 0, 0, 0, 0.812816f, 0.500000f, 0.363644f, 0.287514f, 0.238688f, 0.204544f, 0.179229f, 0.159657f, 0.144042f, 0.131276f, 0.120632f, 0.111614f, @@ -141,6 +141,16 @@ GregoryBasis::ProtoBasis::ProtoBasis( 0.0669851f, 0.0641504f, 0.0615475f, 0.0591488f, 0.0569311f, 0.0548745f, 0.0529621f }; + assert(valence > 0); + if (valence < 30) return efTable[valence]; + + float t = 2.0f * float(M_PI) / float(valence); + return 1.0f / (valence * (cosf(t) + 5.0f + + sqrtf((cosf(t) + 9) * (cosf(t) + 1)))/16.0f); +} + +GregoryBasis::ProtoBasis::ProtoBasis( + Vtr::Level const & level, Index faceIndex, int fvarChannel) { Vtr::ConstIndexArray facePoints = (fvarChannel<0) ? level.getFaceVertices(faceIndex) : @@ -248,8 +258,9 @@ GregoryBasis::ProtoBasis::ProtoBasis( e1[vid] += e * csf(ivalence-3, 2*i+1); } - e0[vid] *= ef[ivalence-3]; - e1[vid] *= ef[ivalence-3]; + float ef = computeCoefficient(ivalence); + e0[vid] *= ef; + e1[vid] *= ef; if (valence<0) { @@ -381,8 +392,8 @@ GregoryBasis::ProtoBasis::ProtoBasis( } /*static*/ -StencilTables * -GregoryBasis::CreateStencilTables(PointsVector const &stencils) { +StencilTable * +GregoryBasis::CreateStencilTable(PointsVector const &stencils) { int nStencils = (int)stencils.size(); if (nStencils == 0) return NULL; @@ -393,15 +404,15 @@ GregoryBasis::CreateStencilTables(PointsVector const &stencils) { } // allocate destination - StencilTables *stencilTables = new StencilTables(); + StencilTable *stencilTable = new StencilTable(); - // XXX: do we need numControlVertices in stencilTables? - stencilTables->_numControlVertices = 0; - stencilTables->resize(nStencils, nElements); + // XXX: do we need numControlVertices in stencilTable? + stencilTable->_numControlVertices = 0; + stencilTable->resize(nStencils, nElements); - int * sizes = &stencilTables->_sizes[0]; - Index * indices = &stencilTables->_indices[0]; - float * weights = &stencilTables->_weights[0]; + int * sizes = &stencilTable->_sizes[0]; + Index * indices = &stencilTable->_indices[0]; + float * weights = &stencilTable->_weights[0]; for (int i = 0; i < nStencils; ++i) { GregoryBasis::Point const &src = stencils[i]; @@ -415,9 +426,9 @@ GregoryBasis::CreateStencilTables(PointsVector const &stencils) { weights += size; ++sizes; } - stencilTables->generateOffsets(); + stencilTable->generateOffsets(); - return stencilTables; + return stencilTable; } } // end namespace Far diff --git a/opensubdiv/far/gregoryBasis.h b/opensubdiv/far/gregoryBasis.h index fc6ec804..25c6b80c 100644 --- a/opensubdiv/far/gregoryBasis.h +++ b/opensubdiv/far/gregoryBasis.h @@ -25,8 +25,9 @@ #ifndef OPENSUBDIV3_FAR_GREGORY_BASIS_H #define OPENSUBDIV3_FAR_GREGORY_BASIS_H -#include "../far/protoStencil.h" #include "../vtr/level.h" +#include "../far/types.h" +#include "../far/stencilTable.h" #include namespace OpenSubdiv { @@ -59,7 +60,7 @@ public: template void Evaluate(T const & controlValues, U values[20]) const { - Index const * indices = &_indices.at(0); + Vtr::Index const * indices = &_indices.at(0); float const * weights = &_weights.at(0); for (int i=0; i<20; ++i) { @@ -70,16 +71,6 @@ public: } } - static const int MAX_VALENCE = (30*2); - static const int MAX_ELEMS = (16 + MAX_VALENCE); - - // limit valence of 30 because we use a pre-computed closed-form 'ef' table - // XXXtakahito: revisit here to determine appropriate size - // or remove fixed size limit and use Sdc mask - static int getNumMaxElements(int maxValence) { - return (16 + maxValence); - } - // // Basis point // @@ -88,13 +79,19 @@ public: // class Point { public: + static const int RESERVED_ENTRY_SIZE = 64; - Point() : _size(0) { } + Point() : _size(0) { + _indices.reserve(RESERVED_ENTRY_SIZE); + _weights.reserve(RESERVED_ENTRY_SIZE); + } - Point(Index idx, float weight = 1.0f) { + Point(Vtr::Index idx, float weight = 1.0f) { + _indices.reserve(RESERVED_ENTRY_SIZE); + _weights.reserve(RESERVED_ENTRY_SIZE); _size = 1; - _indices[0] = idx; - _weights[0] = weight; + _indices.push_back(idx); + _weights.push_back(weight); } Point(Point const & other) { @@ -105,24 +102,24 @@ public: return _size; } - Index const * GetIndices() const { - return _indices; + Vtr::Index const * GetIndices() const { + return &_indices[0]; } float const * GetWeights() const { - return _weights; + return &_weights[0]; } Point & operator = (Point const & other) { _size = other._size; - memcpy(_indices, other._indices, other._size*sizeof(Index)); - memcpy(_weights, other._weights, other._size*sizeof(float)); + _indices = other._indices; + _weights = other._weights; return *this; } Point & operator += (Point const & other) { for (int i=0; i _indices; + std::vector _weights; }; // @@ -208,11 +202,11 @@ public: // struct ProtoBasis { - ProtoBasis(Vtr::Level const & level, Index faceIndex, int fvarChannel=-1); + ProtoBasis(Vtr::Level const & level, Vtr::Index faceIndex, int fvarChannel=-1); int GetNumElements() const; - void Copy(int * sizes, Index * indices, float * weights) const; + void Copy(int * sizes, Vtr::Index * indices, float * weights) const; void Copy(GregoryBasis* dest) const; // Control Vertices based on : @@ -248,13 +242,13 @@ public: typedef std::vector PointsVector; - static StencilTables *CreateStencilTables(PointsVector const &stencils); + static StencilTable *CreateStencilTable(PointsVector const &stencils); private: int _sizes[20]; - std::vector _indices; + std::vector _indices; std::vector _weights; }; diff --git a/opensubdiv/far/patchMap.cpp b/opensubdiv/far/patchMap.cpp index 22bf50b5..3d5b719f 100644 --- a/opensubdiv/far/patchMap.cpp +++ b/opensubdiv/far/patchMap.cpp @@ -30,8 +30,8 @@ namespace OPENSUBDIV_VERSION { namespace Far { // Constructor -PatchMap::PatchMap( PatchTables const & patchTables ) { - initialize( patchTables ); +PatchMap::PatchMap( PatchTable const & patchTable ) { + initialize( patchTable ); } // sets all the children to point to the patch of index patchIdx @@ -63,11 +63,11 @@ PatchMap::addChild( QuadTree & quadtree, QuadNode * parent, int quadrant ) { } void -PatchMap::initialize( PatchTables const & patchTables ) { +PatchMap::initialize( PatchTable const & patchTable ) { int nfaces = 0, - narrays = (int)patchTables.GetNumPatchArrays(), - npatches = (int)patchTables.GetNumPatchesTotal(); + narrays = (int)patchTable.GetNumPatchArrays(), + npatches = (int)patchTable.GetNumPatchesTotal(); if (not narrays or not npatches) return; @@ -77,11 +77,11 @@ PatchMap::initialize( PatchTables const & patchTables ) { for (int parray=0, current=0; parray @@ -38,7 +38,7 @@ namespace Far { /// \brief An quadtree-based map connecting coarse faces to their sub-patches /// -/// PatchTables::PatchArrays contain lists of patches that represent the limit +/// PatchTable::PatchArrays contain lists of patches that represent the limit /// surface of a mesh, sorted by their topological type. These arrays break the /// connection between coarse faces and their sub-patches. /// @@ -49,13 +49,13 @@ namespace Far { class PatchMap { public: - typedef PatchTables::PatchHandle Handle; + typedef PatchTable::PatchHandle Handle; /// \brief Constructor /// - /// @param patchTables A valid set of PatchTables + /// @param patchTable A valid set of PatchTable /// - PatchMap( PatchTables const & patchTables ); + PatchMap( PatchTable const & patchTable ); /// \brief Returns a handle to the sub-patch of the face at the given (u,v). /// Note : the faceid corresponds to quadrangulated face indices (ie. quads @@ -74,7 +74,7 @@ public: private: - inline void initialize( PatchTables const & patchTables ); + inline void initialize( PatchTable const & patchTable ); // Quadtree node with 4 children struct QuadNode { diff --git a/opensubdiv/far/patchTables.cpp b/opensubdiv/far/patchTable.cpp similarity index 78% rename from opensubdiv/far/patchTables.cpp rename to opensubdiv/far/patchTable.cpp index ad32da24..84f13f80 100644 --- a/opensubdiv/far/patchTables.cpp +++ b/opensubdiv/far/patchTable.cpp @@ -22,7 +22,7 @@ // language governing permissions and limitations under the Apache License. // -#include "../far/patchTables.h" +#include "../far/patchTable.h" #include "../far/patchBasis.h" #include @@ -33,15 +33,15 @@ namespace OPENSUBDIV_VERSION { namespace Far { -PatchTables::PatchTables(int maxvalence) : +PatchTable::PatchTable(int maxvalence) : _maxValence(maxvalence), - _vertexStencilTables(NULL), - _varyingStencilTables(NULL) { + _vertexStencilTable(NULL), + _varyingStencilTable(NULL) { } // Copy constructor // XXXX manuelk we need to eliminate this constructor (C++11 smart pointers) -PatchTables::PatchTables(PatchTables const & src) : +PatchTable::PatchTable(PatchTable const & src) : _maxValence(src._maxValence), _numPtexFaces(src._numPtexFaces), _patchArrays(src._patchArrays), @@ -49,29 +49,29 @@ PatchTables::PatchTables(PatchTables const & src) : _paramTable(src._paramTable), _quadOffsetsTable(src._quadOffsetsTable), _vertexValenceTable(src._vertexValenceTable), - _vertexStencilTables(NULL), - _varyingStencilTables(NULL), + _vertexStencilTable(NULL), + _varyingStencilTable(NULL), _fvarChannels(src._fvarChannels), _sharpnessIndices(src._sharpnessIndices), _sharpnessValues(src._sharpnessValues) { - if (src._vertexStencilTables) { - _vertexStencilTables = new StencilTables(*src._vertexStencilTables); + if (src._vertexStencilTable) { + _vertexStencilTable = new StencilTable(*src._vertexStencilTable); } - if (src._varyingStencilTables) { - _varyingStencilTables = new StencilTables(*src._varyingStencilTables); + if (src._varyingStencilTable) { + _varyingStencilTable = new StencilTable(*src._varyingStencilTable); } } -PatchTables::~PatchTables() { - delete _vertexStencilTables; - delete _varyingStencilTables; +PatchTable::~PatchTable() { + delete _vertexStencilTable; + delete _varyingStencilTable; } // // PatchArrays // -struct PatchTables::PatchArray { +struct PatchTable::PatchArray { PatchArray(PatchDescriptor d, int np, Index v, Index p, Index qo) : desc(d), numPatches(np), vertIndex(v), @@ -91,24 +91,24 @@ struct PatchTables::PatchArray { // debug helper void -PatchTables::PatchArray::print() const { +PatchTable::PatchArray::print() const { desc.print(); printf(" numPatches=%d vertIndex=%d patchIndex=%d " "quadOffsetIndex=%d\n", numPatches, vertIndex, patchIndex, quadOffsetIndex); } -inline PatchTables::PatchArray & -PatchTables::getPatchArray(Index arrayIndex) { +inline PatchTable::PatchArray & +PatchTable::getPatchArray(Index arrayIndex) { assert(arrayIndex<(Index)GetNumPatchArrays()); return _patchArrays[arrayIndex]; } -inline PatchTables::PatchArray const & -PatchTables::getPatchArray(Index arrayIndex) const { +inline PatchTable::PatchArray const & +PatchTable::getPatchArray(Index arrayIndex) const { assert(arrayIndex<(Index)GetNumPatchArrays()); return _patchArrays[arrayIndex]; } void -PatchTables::reservePatchArrays(int numPatchArrays) { +PatchTable::reservePatchArrays(int numPatchArrays) { _patchArrays.reserve(numPatchArrays); } @@ -117,16 +117,16 @@ PatchTables::reservePatchArrays(int numPatchArrays) { // // Stores a record for each patch in the primitive : // -// - Each patch in the PatchTables has a corresponding patch in each +// - Each patch in the PatchTable has a corresponding patch in each // face-varying patch channel. Patch vertex indices are sorted in the same -// patch-type order as PatchTables::PTables. Face-varying data for a patch +// patch-type order as PatchTable::PTables. Face-varying data for a patch // can therefore be quickly accessed by using the patch primitive ID as // index into patchValueOffsets to locate the face-varying control vertex // indices. // // - Face-varying channels can have a different interpolation modes // -// - Unlike "vertex" PatchTables, there are no "transition" patterns required +// - Unlike "vertex" PatchTable, there are no "transition" patterns required // for face-varying patches. // // - No transition patterns means vertex indices of face-varying patches can @@ -139,7 +139,7 @@ PatchTables::reservePatchArrays(int numPatchArrays) { // similar to single-crease to resolve this condition without requiring // isolation if possible // -struct PatchTables::FVarPatchChannel { +struct PatchTable::FVarPatchChannel { // Channel interpolation mode Sdc::Options::FVarLinearInterpolation interpolation; @@ -157,22 +157,22 @@ struct PatchTables::FVarPatchChannel { std::vector patchValues; // point values for each patch }; -inline PatchTables::FVarPatchChannel & -PatchTables::getFVarPatchChannel(int channel) { +inline PatchTable::FVarPatchChannel & +PatchTable::getFVarPatchChannel(int channel) { assert(channel<(int)_fvarChannels.size()); return _fvarChannels[channel]; } -inline PatchTables::FVarPatchChannel const & -PatchTables::getFVarPatchChannel(int channel) const { +inline PatchTable::FVarPatchChannel const & +PatchTable::getFVarPatchChannel(int channel) const { assert(channel<(int)_fvarChannels.size()); return _fvarChannels[channel]; } void -PatchTables::allocateFVarPatchChannels(int numChannels) { +PatchTable::allocateFVarPatchChannels(int numChannels) { _fvarChannels.resize(numChannels); } void -PatchTables::allocateChannelValues(int channel, +PatchTable::allocateChannelValues(int channel, int numPatches, int numVerticesTotal) { FVarPatchChannel & c = getFVarPatchChannel(channel); @@ -192,22 +192,22 @@ PatchTables::allocateChannelValues(int channel, } } void -PatchTables::setFVarPatchChannelLinearInterpolation(int channel, +PatchTable::setFVarPatchChannelLinearInterpolation(int channel, Sdc::Options::FVarLinearInterpolation interpolation) { FVarPatchChannel & c = getFVarPatchChannel(channel); c.interpolation = interpolation; } void -PatchTables::setFVarPatchChannelPatchesType(int channel, PatchDescriptor::Type type) { +PatchTable::setFVarPatchChannelPatchesType(int channel, PatchDescriptor::Type type) { FVarPatchChannel & c = getFVarPatchChannel(channel); c.patchesType = type; } void -PatchTables::setBicubicFVarPatchChannelValues(int channel, int patchSize, +PatchTable::setBicubicFVarPatchChannelValues(int channel, int patchSize, std::vector const & values) { // This method populates the sparse array of values held in the patch - // tables from a non-sparse array of value indices generated during + // table from a non-sparse array of value indices generated during // the second traversal of an adaptive TopologyRefiner. // It is assumed that the patch types have been stored in the channel's // 'patchTypes' vector during the first traversal. @@ -245,7 +245,7 @@ PatchTables::setBicubicFVarPatchChannelValues(int channel, int patchSize, } // -// PatchTables +// PatchTable // inline int @@ -254,7 +254,7 @@ getPatchSize(PatchDescriptor desc) { } void -PatchTables::pushPatchArray(PatchDescriptor desc, int npatches, +PatchTable::pushPatchArray(PatchDescriptor desc, int npatches, Index * vidx, Index * pidx, Index * qoidx) { if (npatches>0) { @@ -271,52 +271,52 @@ PatchTables::pushPatchArray(PatchDescriptor desc, int npatches, } int -PatchTables::getPatchIndex(int arrayIndex, int patchIndex) const { +PatchTable::getPatchIndex(int arrayIndex, int patchIndex) const { PatchArray const & pa = getPatchArray(arrayIndex); assert(patchIndex(&_quadOffsetsTable[pa.quadOffsetIndex + handle.vertIndex], 4); } bool -PatchTables::IsFeatureAdaptive() const { +PatchTable::IsFeatureAdaptive() const { // XXX: // revisit this function, since we'll add uniform cubic patches later. @@ -418,22 +418,22 @@ PatchTables::IsFeatureAdaptive() const { } int -PatchTables::GetNumFVarChannels() const { +PatchTable::GetNumFVarChannels() const { return (int)_fvarChannels.size(); } Sdc::Options::FVarLinearInterpolation -PatchTables::GetFVarChannelLinearInterpolation(int channel) const { +PatchTable::GetFVarChannelLinearInterpolation(int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); return c.interpolation; } Vtr::Array -PatchTables::getFVarPatchTypes(int channel) { +PatchTable::getFVarPatchTypes(int channel) { FVarPatchChannel & c = getFVarPatchChannel(channel); return Vtr::Array(&c.patchTypes[0], (int)c.patchTypes.size()); } Vtr::ConstArray -PatchTables::GetFVarPatchTypes(int channel) const { +PatchTable::GetFVarPatchTypes(int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); if (c.patchesType!=PatchDescriptor::NON_PATCH) { return Vtr::ConstArray(&c.patchesType, 1); @@ -443,17 +443,17 @@ PatchTables::GetFVarPatchTypes(int channel) const { } } ConstIndexArray -PatchTables::GetFVarPatchesValues(int channel) const { +PatchTable::GetFVarPatchesValues(int channel) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); return ConstIndexArray(&c.patchValues[0], (int)c.patchValues.size()); } IndexArray -PatchTables::getFVarPatchesValues(int channel) { +PatchTable::getFVarPatchesValues(int channel) { FVarPatchChannel & c = getFVarPatchChannel(channel); return IndexArray(&c.patchValues[0], (int)c.patchValues.size()); } PatchDescriptor::Type -PatchTables::getFVarPatchType(int channel, int patch) const { +PatchTable::getFVarPatchType(int channel, int patch) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); PatchDescriptor::Type type; if (c.patchesType!=PatchDescriptor::NON_PATCH) { @@ -466,15 +466,15 @@ PatchTables::getFVarPatchType(int channel, int patch) const { return type; } PatchDescriptor::Type -PatchTables::GetFVarPatchType(int channel, PatchHandle const & handle) const { +PatchTable::GetFVarPatchType(int channel, PatchHandle const & handle) const { return getFVarPatchType(channel, handle.patchIndex); } PatchDescriptor::Type -PatchTables::GetFVarPatchType(int channel, int arrayIndex, int patchIndex) const { +PatchTable::GetFVarPatchType(int channel, int arrayIndex, int patchIndex) const { return getFVarPatchType(channel, getPatchIndex(arrayIndex, patchIndex)); } ConstIndexArray -PatchTables::getFVarPatchValues(int channel, int patch) const { +PatchTable::getFVarPatchValues(int channel, int patch) const { FVarPatchChannel const & c = getFVarPatchChannel(channel); @@ -489,17 +489,17 @@ PatchTables::getFVarPatchValues(int channel, int patch) const { } } ConstIndexArray -PatchTables::GetFVarPatchValues(int channel, PatchHandle const & handle) const { +PatchTable::GetFVarPatchValues(int channel, PatchHandle const & handle) const { return getFVarPatchValues(channel, handle.patchIndex); } ConstIndexArray -PatchTables::GetFVarPatchValues(int channel, int arrayIndex, int patchIndex) const { +PatchTable::GetFVarPatchValues(int channel, int arrayIndex, int patchIndex) const { return getFVarPatchValues(channel, getPatchIndex(arrayIndex, patchIndex)); } void -PatchTables::print() const { - printf("patchTables (0x%p)\n", this); +PatchTable::print() const { + printf("patchTable (0x%p)\n", this); printf(" numPatches = %d\n", GetNumPatchesTotal()); for (int i=0; i PatchFVarPointers; namespace Far { void -PatchTablesFactory::PatchFaceTag::clear() { +PatchTableFactory::PatchFaceTag::clear() { std::memset(this, 0, sizeof(*this)); } void -PatchTablesFactory::PatchFaceTag::assignBoundaryPropertiesFromEdgeMask(int boundaryEdgeMask) { +PatchTableFactory::PatchFaceTag::assignBoundaryPropertiesFromEdgeMask(int boundaryEdgeMask) { // // The number of rotations to apply for boundary or corner patches varies on both // where the boundary/corner occurs and whether boundary or corner -- so using a @@ -134,7 +134,7 @@ PatchTablesFactory::PatchFaceTag::assignBoundaryPropertiesFromEdgeMask(int bound } void -PatchTablesFactory::PatchFaceTag::assignBoundaryPropertiesFromVertexMask(int boundaryVertexMask) { +PatchTableFactory::PatchFaceTag::assignBoundaryPropertiesFromVertexMask(int boundaryVertexMask) { // // This is strictly needed for the irregular case when a vertex is a boundary in // the presence of no boundary edges -- an extra-ordinary face with only one corner @@ -179,7 +179,7 @@ offsetAndPermuteIndices(Far::Index const indices[], int count, // The patch vertices for boundary and corner patches // are assigned index values even though indices will // be undefined along boundary and corner edges. - // When the resulting patch tables are going to be used + // When the resulting patch table is going to be used // as indices for drawing, it is convenient for invalid // indices to be replaced with known good values, such // as the first un-permuted index, which is the index @@ -217,7 +217,7 @@ class FVarChannelCursor { public: FVarChannelCursor(TopologyRefiner const & refiner, - PatchTablesFactory::Options options) { + PatchTableFactory::Options options) { if (options.generateFVarTables) { // If client-code does not select specific channels, default to all // the channels in the refiner. @@ -278,13 +278,13 @@ private: // Adaptive Context // // Helper class aggregating transient contextual data structures during the -// creation of feature adaptive patch tables. The structure simplifies +// creation of feature adaptive patch table. The structure simplifies // the function prototypes of high-level private methods in the factory. // This helps keeping the factory class stateless. // // Note : struct members are not re-entrant nor are they intended to be ! // -struct PatchTablesFactory::AdaptiveContext { +struct PatchTableFactory::AdaptiveContext { public: AdaptiveContext(TopologyRefiner const & refiner, Options options); @@ -293,8 +293,8 @@ public: Options const options; - // The patch tables being created - PatchTables * tables; + // The patch table being created + PatchTable * table; public: @@ -341,16 +341,16 @@ public: }; // Constructor -PatchTablesFactory::AdaptiveContext::AdaptiveContext( +PatchTableFactory::AdaptiveContext::AdaptiveContext( TopologyRefiner const & ref, Options opts) : - refiner(ref), options(opts), tables(0), + refiner(ref), options(opts), table(0), fvarChannelCursor(ref, opts) { fvarPatchValues.resize(fvarChannelCursor.size()); } void -PatchTablesFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) { +PatchTableFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) { FVarChannelCursor & fvc = fvarChannelCursor; for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { @@ -367,31 +367,31 @@ PatchTablesFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) { } bool -PatchTablesFactory::AdaptiveContext::RequiresFVarPatches() const { +PatchTableFactory::AdaptiveContext::RequiresFVarPatches() const { return not fvarPatchValues.empty(); } // -// Reserves tables based on the contents of the PatchArrayVector in the PatchTables: +// Reserves tables based on the contents of the PatchArrayVector in the PatchTable: // void -PatchTablesFactory::allocateVertexTables(PatchTables * tables, int /* nlevels */, bool hasSharpness) { +PatchTableFactory::allocateVertexTables(PatchTable * table, int /* nlevels */, bool hasSharpness) { int ncvs = 0, npatches = 0; - for (int i=0; iGetNumPatchArrays(); ++i) { - npatches += tables->GetNumPatches(i); - ncvs += tables->GetNumControlVertices(i); + for (int i=0; iGetNumPatchArrays(); ++i) { + npatches += table->GetNumPatches(i); + ncvs += table->GetNumControlVertices(i); } if (ncvs==0 or npatches==0) return; - tables->_patchVerts.resize( ncvs ); + table->_patchVerts.resize( ncvs ); - tables->_paramTable.resize( npatches ); + table->_paramTable.resize( npatches ); if (hasSharpness) { - tables->_sharpnessIndices.resize( npatches, Vtr::INDEX_INVALID ); + table->_sharpnessIndices.resize( npatches, Vtr::INDEX_INVALID ); } } @@ -399,11 +399,11 @@ PatchTablesFactory::allocateVertexTables(PatchTables * tables, int /* nlevels */ // Allocate face-varying tables // void -PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner, - Options options, int npatches, PatchTables * tables) { +PatchTableFactory::allocateFVarChannels(TopologyRefiner const & refiner, + Options options, int npatches, PatchTable * table) { assert(options.generateFVarTables and - refiner.GetNumFVarChannels()>0 and npatches>0 and tables); + refiner.GetNumFVarChannels()>0 and npatches>0 and table); // Create a channel cursor to iterate over client-selected channels or // default to the channels found in the TopologyRefiner @@ -412,7 +412,7 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner, return; } - tables->allocateFVarPatchChannels(fvc.size()); + table->allocateFVarPatchChannels(fvc.size()); // Iterate with the cursor to initialize each channel for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { @@ -420,7 +420,7 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner, Sdc::Options::FVarLinearInterpolation interpolation = refiner.GetFVarLinearInterpolation(*fvc); - tables->setFVarPatchChannelLinearInterpolation(fvc.pos(), interpolation); + table->setFVarPatchChannelLinearInterpolation(fvc.pos(), interpolation); int nverts = 0; if (interpolation==Sdc::Options::FVAR_LINEAR_ALL) { @@ -428,20 +428,20 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner, PatchDescriptor::Type type = options.triangulateQuads ? PatchDescriptor::TRIANGLES : PatchDescriptor::QUADS; - tables->setFVarPatchChannelPatchesType(fvc.pos(), type); + table->setFVarPatchChannelPatchesType(fvc.pos(), type); nverts = npatches * PatchDescriptor::GetNumFVarControlVertices(type); } - tables->allocateChannelValues(fvc.pos(), npatches, nverts); + table->allocateChannelValues(fvc.pos(), npatches, nverts); } } // gather face-varying patch points int -PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level, +PatchTableFactory::gatherFVarData(AdaptiveContext & context, int level, Index faceIndex, Index levelFaceOffset, int rotation, Index const * levelFVarVertOffsets, Index fofss, Index ** fptrs) { @@ -451,7 +451,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level, TopologyRefiner const & refiner = context.refiner; - PatchTables * tables = context.tables; + PatchTable * table = context.table; assert((levelFaceOffset + faceIndex)<(int)context.patchTags.size()); PatchFaceTag & vertexPatchTag = context.patchTags[levelFaceOffset + faceIndex]; @@ -572,7 +572,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level, } Vtr::Array patchTypes = - tables->getFVarPatchTypes(fvc.pos()); + table->getFVarPatchTypes(fvc.pos()); assert(not patchTypes.empty()); patchTypes[fofss] = fvarPatchType; @@ -652,7 +652,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level, // a pointer to the next descriptor // PatchParam * -PatchTablesFactory::computePatchParam( +PatchTableFactory::computePatchParam( TopologyRefiner const & refiner, PtexIndices const &ptexIndices, int depth, Vtr::Index faceIndex, int boundaryMask, int transitionMask, PatchParam *coord) { @@ -665,7 +665,7 @@ PatchTablesFactory::computePatchParam( v = 0, ofs = 1; - bool nonquad = (refiner.GetFaceVertices(depth, faceIndex).size() != 4); + bool nonquad = (refiner.GetLevel(depth).GetFaceVertices(faceIndex).size() != 4); for (int i = depth; i > 0; --i) { Vtr::Refinement const& refinement = refiner.getRefinement(i-1); @@ -733,8 +733,8 @@ assignSharpnessIndex(float sharpness, std::vector & sharpnessValues) { // cases. In the past, more additional arguments were passed to the uniform version, // but that may no longer be necessary (see notes in the uniform version below)... // -PatchTables * -PatchTablesFactory::Create(TopologyRefiner const & refiner, Options options) { +PatchTable * +PatchTableFactory::Create(TopologyRefiner const & refiner, Options options) { if (refiner.IsUniform()) { return createUniform(refiner, options); @@ -743,8 +743,8 @@ PatchTablesFactory::Create(TopologyRefiner const & refiner, Options options) { } } -PatchTables * -PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options options) { +PatchTable * +PatchTableFactory::createUniform(TopologyRefiner const & refiner, Options options) { assert(refiner.IsUniform()); @@ -772,22 +772,26 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio assert(ptype!=PatchDescriptor::NON_PATCH); // - // Create the instance of the tables and allocate and initialize its members. + // Create the instance of the table and allocate and initialize its members. // - PatchTables * tables = new PatchTables(maxvalence); + PatchTable * table = new PatchTable(maxvalence); - tables->_numPtexFaces = ptexIndices.GetNumFaces(); + table->_numPtexFaces = ptexIndices.GetNumFaces(); - tables->reservePatchArrays(nlevels); + table->reservePatchArrays(nlevels); PatchDescriptor desc(ptype); // generate patch arrays for (int level=firstlevel, poffset=0, voffset=0; level<=maxlevel; ++level) { - int npatches = refiner.GetNumFaces(level); + TopologyLevel const & refLevel = refiner.GetLevel(level); + + int npatches = refLevel.GetNumFaces(); if (refiner.HasHoles()) { - npatches -= refiner.GetNumHoles(level); + for (int i = npatches - 1; i >= 0; --i) { + npatches -= refLevel.IsFaceHole(i); + } } assert(npatches>=0); @@ -795,31 +799,31 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio npatches *= 2; if (level>=firstlevel) { - tables->pushPatchArray(desc, npatches, &voffset, &poffset, 0); + table->pushPatchArray(desc, npatches, &voffset, &poffset, 0); } } // Allocate various tables - allocateVertexTables( tables, 0, /*hasSharpness=*/false ); + allocateVertexTables( table, 0, /*hasSharpness=*/false ); bool generateFVarPatches=false; FVarChannelCursor fvc(refiner, options); if (options.generateFVarTables and fvc.size()>0) { - int npatches = tables->GetNumPatchesTotal(); - allocateFVarChannels(refiner, options, npatches, tables); - assert(fvc.size() == tables->GetNumFVarChannels()); + int npatches = table->GetNumPatchesTotal(); + allocateFVarChannels(refiner, options, npatches, table); + assert(fvc.size() == table->GetNumFVarChannels()); } // // Now populate the patches: // - Index * iptr = &tables->_patchVerts[0]; - PatchParam * pptr = &tables->_paramTable[0]; + Index * iptr = &table->_patchVerts[0]; + PatchParam * pptr = &table->_paramTable[0]; Index ** fptr = 0; Index levelVertOffset = options.generateAllLevels ? - 0 : refiner.GetNumVertices(0); + 0 : refiner.GetLevel(0).GetNumVertices(); Index * levelFVarVertOffsets = 0; if (generateFVarPatches) { @@ -829,21 +833,23 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio fptr = (Index **)alloca(fvc.size()*sizeof(Index *)); for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { - fptr[fvc.pos()] = tables->getFVarPatchesValues(fvc.pos()).begin(); + fptr[fvc.pos()] = table->getFVarPatchesValues(fvc.pos()).begin(); } } for (int level=1; level<=maxlevel; ++level) { - int nfaces = refiner.GetNumFaces(level); + TopologyLevel const & refLevel = refiner.GetLevel(level); + + int nfaces = refLevel.GetNumFaces(); if (level>=firstlevel) { for (int face=0; facegetFVarPatchesValues(fvc.pos()).size()); + assert((levelVertOffset + fvalues[vert]) < (int)table->getFVarPatchesValues(fvc.pos()).size()); fptr[fvc.pos()][vert] = levelFVarVertOffsets[fvc.pos()] + fvalues[vert]; } fptr[fvc.pos()]+=fvalues.size(); @@ -884,17 +890,17 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio } if (options.generateAllLevels) { - levelVertOffset += refiner.GetNumVertices(level); + levelVertOffset += refiner.GetLevel(level).GetNumVertices(); for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { - levelFVarVertOffsets[fvc.pos()] += refiner.GetNumFVarValues(level, fvc.pos()); + levelFVarVertOffsets[fvc.pos()] += refiner.GetLevel(level).GetNumFVarValues(fvc.pos()); } } } - return tables; + return table; } -PatchTables * -PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options options) { +PatchTable * +PatchTableFactory::createAdaptive(TopologyRefiner const & refiner, Options options) { assert(not refiner.IsUniform()); @@ -909,15 +915,15 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti identifyAdaptivePatches(context); // - // Create the instance of the tables and allocate and initialize its members based on + // Create the instance of the table and allocate and initialize its members based on // the inventory of patches determined above: // int maxValence = refiner.GetMaxValence(); - context.tables = new PatchTables(maxValence); + context.table = new PatchTable(maxValence); // Populate the patch array descriptors - context.tables->reservePatchArrays(context.patchInventory.getNumPatchArrays()); + context.table->reservePatchArrays(context.patchInventory.getNumPatchArrays()); // Sort through the inventory and push back non-empty patch arrays ConstPatchDescriptorArray const & descs = @@ -926,21 +932,21 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti int voffset=0, poffset=0, qoffset=0; for (int i=0; ipushPatchArray(desc, + context.table->pushPatchArray(desc, context.patchInventory.getValue(desc), &voffset, &poffset, &qoffset ); } - context.tables->_numPtexFaces = ptexIndices.GetNumFaces(); + context.table->_numPtexFaces = ptexIndices.GetNumFaces(); // Allocate various tables bool hasSharpness = context.options.useSingleCreasePatch; - allocateVertexTables(context.tables, 0, hasSharpness); + allocateVertexTables(context.table, 0, hasSharpness); if (context.RequiresFVarPatches()) { - int npatches = context.tables->GetNumPatchesTotal(); + int npatches = context.table->GetNumPatchesTotal(); - allocateFVarChannels(refiner, options, npatches, context.tables); + allocateFVarChannels(refiner, options, npatches, context.table); // Reserve temporary non-sparse storage for non-linear fvar channels. // FVar Values for these channels are copied into the final @@ -954,7 +960,7 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti // populateAdaptivePatches(context, ptexIndices); - return context.tables; + return context.table; } // @@ -963,7 +969,7 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti // later with no additional analysis. // void -PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) { +PatchTableFactory::identifyAdaptivePatches(AdaptiveContext & context) { TopologyRefiner const & refiner = context.refiner; @@ -1225,12 +1231,12 @@ PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) { // idenified. // void -PatchTablesFactory::populateAdaptivePatches( +PatchTableFactory::populateAdaptivePatches( AdaptiveContext & context, PtexIndices const & ptexIndices) { TopologyRefiner const & refiner = context.refiner; - PatchTables * tables = context.tables; + PatchTable * table = context.table; // // Setup convenience pointers at the beginning of each patch array for each @@ -1249,33 +1255,33 @@ PatchTablesFactory::populateAdaptivePatches( PatchDescriptor desc = descs[i]; - Index arrayIndex = tables->findPatchArray(desc); + Index arrayIndex = table->findPatchArray(desc); if (arrayIndex==Vtr::INDEX_INVALID) { continue; } - iptrs.getValue(desc) = tables->getPatchArrayVertices(arrayIndex).begin(); - pptrs.getValue(desc) = tables->getPatchParams(arrayIndex).begin(); + iptrs.getValue(desc) = table->getPatchArrayVertices(arrayIndex).begin(); + pptrs.getValue(desc) = table->getPatchParams(arrayIndex).begin(); if (context.options.useSingleCreasePatch) { - sptrs.getValue(desc) = tables->getSharpnessIndices(arrayIndex); + sptrs.getValue(desc) = table->getSharpnessIndices(arrayIndex); } if (context.RequiresFVarPatches()) { Index & offsets = fofss.getValue(desc); - offsets = tables->getPatchIndex(arrayIndex, 0); + offsets = table->getPatchIndex(arrayIndex, 0); // XXXX manuelk this stuff will go away as we use offsets from FVarPatchChannel FVarChannelCursor & fvc = context.fvarChannelCursor; - assert(fvc.size() == tables->GetNumFVarChannels()); + assert(fvc.size() == table->GetNumFVarChannels()); Index ** fptr = (Index **)alloca(fvc.size()*sizeof(Index *)); for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { - Index pidx = tables->getPatchIndex(arrayIndex, 0); + Index pidx = table->getPatchIndex(arrayIndex, 0); int ofs = pidx * 4; - fptr[fvc.pos()] = &tables->getFVarPatchesValues(fvc.pos())[ofs]; + fptr[fvc.pos()] = &table->getFVarPatchesValues(fvc.pos())[ofs]; } fptrs.getValue(desc) = fptr; } @@ -1371,7 +1377,7 @@ PatchTablesFactory::populateAdaptivePatches( iptrs.R += 16; pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, boundaryMask, transitionMask, pptrs.R); // XXX: sharpness will be integrated into patch param soon. - if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues); + if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues); fofss.R += gatherFVarData(context, i, faceIndex, levelFaceOffset, /*rotation*/0, levelFVarVertOffsets, fofss.R, fptrs.R); @@ -1389,7 +1395,7 @@ PatchTablesFactory::populateAdaptivePatches( iptrs.R += 16; pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, /*boundary*/0, transitionMask, pptrs.R); - if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(sharpness, tables->_sharpnessValues); + if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(sharpness, table->_sharpnessValues); fofss.R += gatherFVarData(context, i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.R, fptrs.R); @@ -1410,7 +1416,7 @@ PatchTablesFactory::populateAdaptivePatches( iptrs.GP += cvs.size(); pptrs.GP = computePatchParam( refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.GP); - if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues); + if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues); fofss.GP += gatherFVarData(context, i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.GP, fptrs.GP); @@ -1425,7 +1431,7 @@ PatchTablesFactory::populateAdaptivePatches( iptrs.R += cvs.size(); pptrs.R = computePatchParam( refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.R); - if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues); + if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues); fofss.R += gatherFVarData(context, i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.R, fptrs.R); @@ -1441,7 +1447,7 @@ PatchTablesFactory::populateAdaptivePatches( iptrs.G += cvs.size(); pptrs.G = computePatchParam( refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.G); - if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues); + if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues); fofss.G += gatherFVarData(context, i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.G, fptrs.G); @@ -1450,7 +1456,7 @@ PatchTablesFactory::populateAdaptivePatches( iptrs.GB += cvs.size(); pptrs.GB = computePatchParam( refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.GB); - if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues); + if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues); fofss.GB += gatherFVarData(context, i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.GB, fptrs.GB); @@ -1480,24 +1486,24 @@ PatchTablesFactory::populateAdaptivePatches( // finalize end patches switch(context.options.GetEndCapType()) { case Options::ENDCAP_GREGORY_BASIS: - tables->_vertexStencilTables = - endCapGregoryBasis->CreateVertexStencilTables(); - tables->_varyingStencilTables = - endCapGregoryBasis->CreateVaryingStencilTables(); + table->_vertexStencilTable = + endCapGregoryBasis->CreateVertexStencilTable(); + table->_varyingStencilTable = + endCapGregoryBasis->CreateVaryingStencilTable(); delete endCapGregoryBasis; break; case Options::ENDCAP_BSPLINE_BASIS: - tables->_vertexStencilTables = - endCapBSpline->CreateVertexStencilTables(); - tables->_varyingStencilTables = - endCapBSpline->CreateVaryingStencilTables(); + table->_vertexStencilTable = + endCapBSpline->CreateVertexStencilTable(); + table->_varyingStencilTable = + endCapBSpline->CreateVaryingStencilTable(); delete endCapBSpline; break; case Options::ENDCAP_LEGACY_GREGORY: endCapLegacyGregory->Finalize( - tables->GetMaxValence(), - &tables->_quadOffsetsTable, - &tables->_vertexValenceTable); + table->GetMaxValence(), + &table->_quadOffsetsTable, + &table->_vertexValenceTable); delete endCapLegacyGregory; break; default: @@ -1511,8 +1517,8 @@ PatchTablesFactory::populateAdaptivePatches( FVarChannelCursor & fvc = context.fvarChannelCursor; for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { - if (tables->GetFVarChannelLinearInterpolation(fvc.pos())!=Sdc::Options::FVAR_LINEAR_ALL) { - tables->setBicubicFVarPatchChannelValues(fvc.pos(), + if (table->GetFVarChannelLinearInterpolation(fvc.pos())!=Sdc::Options::FVAR_LINEAR_ALL) { + table->setBicubicFVarPatchChannelValues(fvc.pos(), context.fvarPatchSize, context.fvarPatchValues[fvc.pos()]); } } diff --git a/opensubdiv/far/patchTablesFactory.h b/opensubdiv/far/patchTableFactory.h similarity index 89% rename from opensubdiv/far/patchTablesFactory.h rename to opensubdiv/far/patchTableFactory.h index 28d6c409..b32cf2ad 100644 --- a/opensubdiv/far/patchTablesFactory.h +++ b/opensubdiv/far/patchTableFactory.h @@ -22,12 +22,12 @@ // language governing permissions and limitations under the Apache License. // -#ifndef OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H -#define OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H +#ifndef OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H +#define OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H #include "../version.h" -#include "../far/patchTables.h" +#include "../far/patchTable.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { @@ -40,12 +40,12 @@ namespace Far { class PtexIndices; class TopologyRefiner; -class PatchTablesFactory { +class PatchTableFactory { public: // PatchFaceTag // A simple struct containing all information gathered about a face that is relevant // to constructing a patch for it (some of these enums should probably be defined more - // as part of PatchTables) + // as part of PatchTable) // // Like the HbrFace::AdaptiveFlags, this struct aggregates all of the face tags // supporting feature adaptive refinement. For now it is not used elsewhere and can @@ -125,16 +125,16 @@ public: int const * fvarChannelIndices; ///< List containing the indices of the channels selected for the factory }; - /// \brief Factory constructor for PatchTables + /// \brief Factory constructor for PatchTable /// /// @param refiner TopologyRefiner from which to generate patches /// - /// @param options Options controlling the creation of the tables + /// @param options Options controlling the creation of the table /// - /// @return A new instance of PatchTables + /// @return A new instance of PatchTable /// - static PatchTables * Create(TopologyRefiner const & refiner, - Options options=Options()); + static PatchTable * Create(TopologyRefiner const & refiner, + Options options=Options()); private: // @@ -145,11 +145,11 @@ private: // // Methods for allocating and managing the patch table data arrays: // - static PatchTables * createUniform(TopologyRefiner const & refiner, - Options options); + static PatchTable * createUniform(TopologyRefiner const & refiner, + Options options); - static PatchTables * createAdaptive(TopologyRefiner const & refiner, - Options options); + static PatchTable * createAdaptive(TopologyRefiner const & refiner, + Options options); // // High-level methods for identifying and populating patches associated with faces: @@ -160,10 +160,10 @@ private: static void populateAdaptivePatches(AdaptiveContext & state, PtexIndices const &ptexIndices); - static void allocateVertexTables(PatchTables * tables, int nlevels, bool hasSharpness); + static void allocateVertexTables(PatchTable * table, int nlevels, bool hasSharpness); static void allocateFVarChannels(TopologyRefiner const & refiner, - Options options, int npatches, PatchTables * tables); + Options options, int npatches, PatchTable * table); static PatchParam * computePatchParam(TopologyRefiner const & refiner, PtexIndices const & ptexIndices, @@ -184,4 +184,4 @@ using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv -#endif /* OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H */ +#endif /* OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H */ diff --git a/opensubdiv/far/protoStencil.h b/opensubdiv/far/protoStencil.h deleted file mode 100644 index 13eb209a..00000000 --- a/opensubdiv/far/protoStencil.h +++ /dev/null @@ -1,504 +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 OPENSUBDIV3_FAR_PROTOSTENCIL_H -#define OPENSUBDIV3_FAR_PROTOSTENCIL_H - -#include "../far/stencilTables.h" - -#include -#include -#include - -namespace OpenSubdiv { -namespace OPENSUBDIV_VERSION { - -namespace Far { - -// -// Proto-stencil Pool Allocator classes -// -// Strategy: allocate up-front a data pool for supporting PROTOSTENCILS of a size -// (maxsize) slightly above average. For the (rare) BIG_PROTOSTENCILS that -// require more support vertices, switch to (slow) heap allocation. -// -template -class Allocator { - -public: - - // Constructor - Allocator(int maxSize, bool interpolateVarying=false) : - _maxsize(maxSize), _interpolateVarying(interpolateVarying) { } - - ~Allocator() { - clearBigStencils(); - } - - // Returns the number of stencils in the allocator - int GetNumStencils() const { - return (int)_sizes.size(); - } - - // Returns the total number of control vertices used by the all the stencils - int GetNumVerticesTotal() const { - int nverts=0; - for (int i=0; i_indices.push_back(vert); - dst->_weights.push_back(weight); - } - ++size; - } - - // Returns the local index in 'stencil' of a given vertex index, or - // INDEX_INVALID if the stencil does not contain this vertex - int FindVertex(Index protoStencil, Index vert) { - int size = _sizes[protoStencil]; - Index const * indices = GetIndices(protoStencil); - for (int i=0; i=_maxsize; - } - - // Returns the size of a given proto-stencil - int GetSize(Index protoStencil) const { - assert(protoStencil<(int)_sizes.size()); - return _sizes[protoStencil]; - } - - // Resolve memory pool and return a pointer to the indices of a given - // proto-stencil - Index * GetIndices(Index protoStencil) { - if (not IsBigStencil(protoStencil)) { - return &_indices[protoStencil*_maxsize]; - } else { - assert(_bigStencils.find(protoStencil)!=_bigStencils.end()); - return &_bigStencils[protoStencil]->_indices[0]; - } - } - - // Resolve memory pool and return a pointer to the weights of a given - // proto-stencil - float * GetWeights(Index protoStencil) { - if (not IsBigStencil(protoStencil)) { - return &_weights[protoStencil*_maxsize]; - } else { - assert(_bigStencils.find(protoStencil)!=_bigStencils.end()); - return &_bigStencils[protoStencil]->_weights[0]; - } - } - - // Returns the proto-stencil at a given index - PROTOSTENCIL operator[] (Index protoStencil) { - // If the allocator is empty, AddWithWeight() expects a coarse control - // vertex instead of a stencil and we only need to pass the index - return PROTOSTENCIL(protoStencil, this->GetNumStencils()>0 ? this : 0); - } - - // Returns the proto-stencil at a given index - PROTOSTENCIL operator[] (Index protoStencil) const { - // If the allocator is empty, AddWithWeight() expects a coarse control - // vertex instead of a stencil and we only need to pass the index - return PROTOSTENCIL(protoStencil, this->GetNumStencils()>0 ? - const_cast *>(this) : 0); - } - - // Copy the proto-stencil out of the pool - int CopyStencil(Index protoStencil, - Index * indices, float * weights) { - int size = GetSize(protoStencil); - memcpy(indices, this->GetIndices(protoStencil), size*sizeof(Index)); - memcpy(weights, this->GetWeights(protoStencil), size*sizeof(float)); - return size; - } - -protected: - - // delete 'slow' memory pool - void clearBigStencils() { - typename BigStencilMap::iterator it; - for (it=_bigStencils.begin(); it!=_bigStencils.end(); ++it) { - delete it->second; - } - _bigStencils.clear(); - } - -protected: - - int _maxsize; // max size of stencil that fits in the 'fast' pool - - bool _interpolateVarying; // true for varying interpolation - - std::vector _sizes; // 'fast' memory pool - std::vector _indices; - std::vector _weights; - - typedef std::map BigStencilMap; - BigStencilMap _bigStencils; // 'slow' memory pool -}; - -// -// Specialization of the Allocator for stencils with tangents that require -// additional derivative weights. -// -template -class LimitAllocator : public Allocator { - -public: - - // Constructor - LimitAllocator(int maxSize) : - Allocator(maxSize) { } - - void Resize(int size) { - Allocator::Resize(size); - int nelems = (int)this->_weights.size(); - _tan1Weights.resize(nelems); - _tan2Weights.resize(nelems); - } - - void PushBackVertex(Index protoStencil, - Index vert, float weight, float tan1Weight, float tan2Weight) { - assert(weight!=0.0f or tan1Weight!=0.0f or tan2Weight!=0.0f); - int & size = this->_sizes[protoStencil]; - Index idx = protoStencil*this->_maxsize; - if (size < (this->_maxsize-1)) { - idx += size; - this->_indices[idx] = vert; - this->_weights[idx] = weight; - this->_tan1Weights[idx] = tan1Weight; - this->_tan2Weights[idx] = tan2Weight; - } else { - BIG_PROTOSTENCIL * dst = 0; - if (size==(this->_maxsize-1)) { - dst = new BIG_PROTOSTENCIL(size, - &this->_indices[idx], &this->_weights[idx], - &this->_tan1Weights[idx], &this->_tan2Weights[idx]); - assert(this->_bigStencils.find(protoStencil)==this->_bigStencils.end()); - this->_bigStencils[protoStencil] = dst; - } else { - assert(this->_bigStencils.find(protoStencil)!=this->_bigStencils.end()); - dst = this->_bigStencils[protoStencil]; - } - dst->_indices.push_back(vert); - dst->_weights.push_back(weight); - dst->_tan1Weights.push_back(tan1Weight); - dst->_tan2Weights.push_back(tan2Weight); - } - ++size; - } - - float * GetTan1Weights(Index protoStencil) { - if (not this->IsBigStencil(protoStencil)) { - return &_tan1Weights[protoStencil*this->_maxsize]; - } else { - assert(this->_bigStencils.find(protoStencil)!=this->_bigStencils.end()); - return &this->_bigStencils[protoStencil]->_tan1Weights[0]; - } - } - - float * GetTan2Weights(Index protoStencil) { - if (not this->IsBigStencil(protoStencil)) { - return &_tan2Weights[protoStencil*this->_maxsize]; - } else { - assert(this->_bigStencils.find(protoStencil)!=this->_bigStencils.end()); - return &this->_bigStencils[protoStencil]->_tan2Weights[0]; - } - } - - PROTOSTENCIL operator[] (Index protoStencil) { - assert(this->GetNumStencils()>0); - return PROTOSTENCIL(protoStencil, this); - } - - void ClearStencil(Index protoStencil) { - Allocator::ClearStencil(protoStencil); - memset(GetTan1Weights(protoStencil), 0, this->_sizes[protoStencil]*sizeof(float)); - memset(GetTan2Weights(protoStencil), 0, this->_sizes[protoStencil]*sizeof(float)); - } - - int CopyLimitStencil(Index protoStencil, - Index * indices, float * weights, float * tan1Weights, float * tan2Weights) { - int size = Allocator::CopyStencil( - protoStencil, indices, weights); - memcpy(tan1Weights, this->GetTan1Weights(protoStencil), size*sizeof(Index)); - memcpy(tan2Weights, this->GetTan2Weights(protoStencil), size*sizeof(float)); - return size; - } - -private: - std::vector _tan1Weights, - _tan2Weights; -}; - -// -// 'Big' Proto stencil classes -// -// When proto-stencils exceed _maxsize, fall back to dynamically allocated -// "BigStencils" (with 'Limit' specialization to handle tangents) -// -struct BigStencil { - - BigStencil(int size, Index const * indices, - float const * weights) { - _indices.reserve(size+5); _indices.resize(size); - memcpy(&_indices.at(0), indices, size*sizeof(int)); - _weights.reserve(size+5); _weights.resize(size); - memcpy(&_weights.at(0), weights, size*sizeof(float)); - } - - std::vector _indices; - std::vector _weights; -}; -struct BigLimitStencil : public BigStencil { - - BigLimitStencil(int size, Index const * indices, float const * weights, - float const * tan1Weights, float const * tan2Weights) : - BigStencil(size, indices, weights) { - - _tan1Weights.reserve(size+5); _tan1Weights.resize(size); - memcpy(&_tan1Weights.at(0), tan1Weights, size*sizeof(float)); - _tan2Weights.reserve(size+5); _tan2Weights.resize(size); - memcpy(&_tan2Weights.at(0), tan2Weights, size*sizeof(float)); - } - - std::vector _tan1Weights, - _tan2Weights; -}; - -// -// ProtoStencils -// -// Proto-stencils are used to interpolate stencils from supporting vertices. -// These stencils are backed by a pool allocator to allow for fast push-back -// of contributing control-vertices weights & indices as they are discovered. -// -class ProtoStencil { - -public: - - ProtoStencil(Index id, Allocator * alloc) : - _id(id), _alloc(alloc) { } - - void Clear() { - // Clear() can only ever be called on an empty stencil: nothing to do - assert(_alloc->GetSize(_id)==0); - } - - // Factorize from a proto-stencil allocator - void AddWithWeight(ProtoStencil const & src, float weight) { - - if(weight==0.0f) { - return; - } - - if (src._alloc) { - // Stencil contribution - int srcSize = src._alloc->GetSize(src._id); - Index const * srcIndices = src._alloc->GetIndices(src._id); - float const * srcWeights = src._alloc->GetWeights(src._id); - - addWithWeight(weight, srcSize, srcIndices, srcWeights); - } else { - // Coarse vertex contribution - Index n = _alloc->FindVertex(_id, src._id); - if (Vtr::IndexIsValid(n)) { - _alloc->GetWeights(_id)[n] += weight; - assert(_alloc->GetWeights(_id)[n]>0.0f); - } else { - _alloc->PushBackVertex(_id, src._id, weight); - } - } - } - - // Factorize from a finished stencil table - void AddWithWeight(StencilTables const & table, Index idx, float weight) { - - assert(idxGetInterpolateVarying()) { - AddWithWeight(src, weight); - } - } - -protected: - - void addWithWeight(float weight, int srcSize, - Index const * srcIndices, float const * srcWeights) { - - for (int i=0; iFindVertex(_id, vertIndex); - if (Vtr::IndexIsValid(n)) { - _alloc->GetWeights(_id)[n] += w; - assert(_alloc->GetWeights(_id)[n]!=0.0f); - } else { - _alloc->PushBackVertex(_id, vertIndex, w); - } - } - } - - Index _id; - Allocator * _alloc; -}; - -typedef Allocator StencilAllocator; - - -// -// ProtoLimitStencil -// -class ProtoLimitStencil { - -public: - - ProtoLimitStencil(Index id, - LimitAllocator * alloc) : - _id(id), _alloc(alloc) { } - - void Clear() { - // Clear() can only ever be called on an empty stencil: nothing to do - assert(_alloc->GetSize(_id)==0); - } - - void AddWithWeight(Stencil const & src, - float weight, float tan1Weight, float tan2Weight) { - - if(weight==0.0f and tan1Weight==0.0f and tan2Weight==0.0f) { - return; - } - - int srcSize = *src.GetSizePtr(); - Index const * srcIndices = src.GetVertexIndices(); - float const * srcWeights = src.GetWeights(); - - for (int i=0; iFindVertex(_id, vertIndex); - if (Vtr::IndexIsValid(n)) { - _alloc->GetWeights(_id)[n] += weight*w; - _alloc->GetTan1Weights(_id)[n] += tan1Weight*w; - _alloc->GetTan2Weights(_id)[n] += tan2Weight*w; - - } else { - _alloc->PushBackVertex(_id, vertIndex, - weight*w, tan1Weight*w, tan2Weight*w); - } - } - } - -private: - Index _id; - LimitAllocator * _alloc; -}; - -typedef LimitAllocator LimitStencilAllocator; - - - -} // end namespace Far - -} // end namespace OPENSUBDIV_VERSION -} // end namespace OpenSubdiv - -#endif // OPENSUBDIV3_FAR_PROTOSTENCIL_H diff --git a/opensubdiv/far/stencilBuilder.cpp b/opensubdiv/far/stencilBuilder.cpp new file mode 100644 index 00000000..30ca68cd --- /dev/null +++ b/opensubdiv/far/stencilBuilder.cpp @@ -0,0 +1,453 @@ +// +// 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 "../far/stencilBuilder.h" +#include "../far/topologyRefiner.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Far { +namespace Internal { + +struct PointDerivWeight { + float p; + float du; + float dv; + + PointDerivWeight() + : p(0.0f), du(0.0f), dv(0.0f) + { } + PointDerivWeight(float w) + : p(w), du(w), dv(w) + { } + PointDerivWeight(float w, float wDu, float wDv) + : p(w), du(wDu), dv(wDv) + { } + + friend PointDerivWeight operator*(PointDerivWeight lhs, + PointDerivWeight const& rhs) { + lhs.p *= rhs.p; + lhs.du *= rhs.du; + lhs.dv *= rhs.dv; + return lhs; + } + PointDerivWeight& operator+=(PointDerivWeight const& rhs) { + p += rhs.p; + du += rhs.du; + dv += rhs.dv; + return *this; + } +}; + +/// Stencil table constructor set. +/// +class WeightTable { +public: + WeightTable(int coarseVerts, + bool genCtrlVertStencils, + bool compactWeights) + : _size(0) + , _lastOffset(0) + , _coarseVertCount(coarseVerts) + , _compactWeights(compactWeights) + { + // These numbers were chosen by profiling production assets at uniform + // level 3. + size_t n = std::max(coarseVerts, + std::min(int(5*1024*1024), + coarseVerts*2)); + _dests.reserve(n); + _sources.reserve(n); + _weights.reserve(n); + + if (!genCtrlVertStencils) + return; + + // Generate trivial control vert stencils + _sources.resize(coarseVerts); + _weights.resize(coarseVerts); + _dests.resize(coarseVerts); + _indices.resize(coarseVerts); + _sizes.resize(coarseVerts); + + for (int i = 0; i < coarseVerts; i++) { + _indices[i] = i; + _sizes[i] = 1; + _dests[i] = i; + _sources[i] = i; + _weights[i] = 1.0; + } + + _size = _sources.size(); + _lastOffset = _sources.size() - 1; + } + + template + void AddWithWeight(int src, int dest, W weight, WACCUM weights) + { + // Factorized stencils are expressed purely in terms of the control + // mesh verts. Without this flattening, level_i's weights would point + // to level_i-1, which would point to level_i-2, until the final level + // points to the control verts. + // + // So here, we check if the incoming vert (src) is in the control mesh, + // if it is, we can simply merge it without attempting to resolve it + // first. + if (src < _coarseVertCount) { + merge(src, dest, weight, W(1.0), _lastOffset, _size, weights); + return; + } + + // src is not in the control mesh, so resolve all contributing coarse + // verts (src itself is made up of many control vert weights). + // + // Find the src stencil and number of contributing CVs. + int len = _sizes[src]; + int start = _indices[src]; + + for (int i = start; i < start+len; i++) { + // Invariant: by processing each level in order and each vertex in + // dependent order, any src stencil vertex reference is guaranteed + // to consist only of coarse verts: therefore resolving src verts + // must yield verts in the coarse mesh. + assert(_sources[i] < _coarseVertCount); + + // Merge each of src's contributing verts into this stencil. + merge(_sources[i], dest, weights.Get(i), weight, + _lastOffset, _size, weights); + } + } + + class PointDerivAccumulator { + WeightTable* _tbl; + public: + PointDerivAccumulator(WeightTable* tbl) : _tbl(tbl) + { } + void PushBack(PointDerivWeight weight) { + _tbl->_weights.push_back(weight.p); + _tbl->_duWeights.push_back(weight.du); + _tbl->_dvWeights.push_back(weight.dv); + } + void Add(size_t i, PointDerivWeight weight) { + _tbl->_weights[i] += weight.p; + _tbl->_duWeights[i] += weight.du; + _tbl->_dvWeights[i] += weight.dv; + } + PointDerivWeight Get(size_t index) { + return PointDerivWeight(_tbl->_weights[index], + _tbl->_duWeights[index], + _tbl->_dvWeights[index]); + } + }; + PointDerivAccumulator GetPointDerivAccumulator() { + return PointDerivAccumulator(this); + }; + + class ScalarAccumulator { + WeightTable* _tbl; + public: + ScalarAccumulator(WeightTable* tbl) : _tbl(tbl) + { } + void PushBack(PointDerivWeight weight) { + _tbl->_weights.push_back(weight.p); + } + void Add(size_t i, float w) { + _tbl->_weights[i] += w; + } + float Get(size_t index) { + return _tbl->_weights[index]; + } + }; + ScalarAccumulator GetScalarAccumulator() { + return ScalarAccumulator(this); + }; + + std::vector const& + GetOffsets() const { return _indices; } + + std::vector const& + GetSizes() const { return _sizes; } + + std::vector const& + GetSources() const { return _sources; } + + std::vector const& + GetWeights() const { return _weights; } + + std::vector const& + GetDuWeights() const { return _duWeights; } + + std::vector const& + GetDvWeights() const { return _dvWeights; } + +private: + + // Merge a vertex weight into the stencil table, if there is an existing + // weight for a given source vertex it will be combined. + // + // PERFORMANCE: caution, this function is super hot. + template + void merge(int src, int dst, W weight, + // Delaying weight*factor multiplication hides memory latency of + // accessing weight[i], yielding more stable performance. + W weightFactor, + // Similarly, passing offset & tableSize as params yields higher + // performance than accessing the class members directly. + int lastOffset, int tableSize, WACCUM weights) + { + // The lastOffset is the vertex we're currently processing, by + // leveraging this we need not lookup the dest stencil size or offset. + // + // Additionally, if the client does not want the resulting verts + // compacted, do not attempt to combine weights. + if (_compactWeights and _dests[lastOffset] == dst) { + + // tableSize is exactly _sources.size(), but using tableSize is + // significantly faster. + for (int i = lastOffset; i < tableSize; i++) { + + // If we find an existing vertex that matches src, we need to + // combine the weights to avoid duplicate entries for src. + if (_sources[i] == src) { + weights.Add(i, weight*weightFactor); + return; + } + } + } + + // We haven't seen src yet, insert it as a new vertex weight. + add(src, dst, weight*weightFactor, weights); + } + + // Add a new vertex weight to the stencil table. + template + void add(int src, int dst, W weight, WACCUM weights) + { + // The _dests array has num(weights) elements mapping each individual + // element back to a specific stencil. The array is constructed in such + // a way that the current stencil being built is always at the end of + // the array, so if the dests array is empty or back() doesn't match + // dst, then we just started building a new stencil. + if (_dests.empty() or dst != _dests.back()) { + // _indices and _sizes always have num(stencils) elements so that + // stencils can be directly looked up by their index in these + // arrays. So here, ensure that they are large enough to hold the + // new stencil about to be built. + if (dst+1 > (int)_indices.size()) { + _indices.resize(dst+1); + _sizes.resize(dst+1); + } + // Initialize the new stencil's meta-data (offset, size). + _indices[dst] = _sources.size(); + _sizes[dst] = 0; + // Keep track of where the current stencil begins, which lets us + // avoid having to look it up later. + _lastOffset = _sources.size(); + } + // Cache the number of elements as an optimization, it's faster than + // calling size() on any of the vectors. + _size++; + + // Increment the current stencil element size. + _sizes[dst]++; + // Track this element as belonging to the stencil "dst". + _dests.push_back(dst); + + // Store the actual stencil data. + _sources.push_back(src); + weights.PushBack(weight); + } + + // The following vectors are explicitly stored as non-interleaved elements + // to reduce cache misses. + + // Stencil to destination vertex map. + std::vector _dests; + + // The actual stencil data. + std::vector _sources; + std::vector _weights; + std::vector _duWeights; + std::vector _dvWeights; + + // Index data used to recover stencil-to-vertex mapping. + std::vector _indices; + std::vector _sizes; + + // Acceleration members to avoid pointer chasing and reverse loops. + int _size; + int _lastOffset; + int _coarseVertCount; + bool _compactWeights; +}; + +StencilBuilder::StencilBuilder(int coarseVertCount, + bool isVarying, + bool genCtrlVertStencils, + bool compactWeights) + : _weightTable(new WeightTable(coarseVertCount, + genCtrlVertStencils, + compactWeights)) + , _isVarying(isVarying) +{ +} + +StencilBuilder::~StencilBuilder() +{ + delete _weightTable; +} + +size_t +StencilBuilder::GetNumVerticesTotal() const +{ + return _weightTable->GetWeights().size(); +} + + +int +StencilBuilder::GetNumVertsInStencil(size_t stencilIndex) const +{ + if (stencilIndex > _weightTable->GetSizes().size() - 1) + return 0; + + return (int)_weightTable->GetSizes()[stencilIndex]; +} + +std::vector const& +StencilBuilder::GetStencilOffsets() const { + return _weightTable->GetOffsets(); +} + +std::vector const& +StencilBuilder::GetStencilSizes() const { + return _weightTable->GetSizes(); +} + +std::vector const& +StencilBuilder::GetStencilSources() const { + return _weightTable->GetSources(); +} + +std::vector const& +StencilBuilder::GetStencilWeights() const { + return _weightTable->GetWeights(); +} + +std::vector const& +StencilBuilder::GetStencilDuWeights() const { + return _weightTable->GetDuWeights(); +} + +std::vector const& +StencilBuilder::GetStencilDvWeights() const { + return _weightTable->GetDvWeights(); +} + +void +StencilBuilder::Index::AddWithWeight(Index const & src, float weight) +{ + if (_owner->_isVarying) + return; + // Ignore no-op weights. + if (weight == 0) + return; + _owner->_weightTable->AddWithWeight(src._index, _index, weight, + _owner->_weightTable->GetScalarAccumulator()); +} + +void +StencilBuilder::Index::AddWithWeight(Stencil const& src, float weight) +{ + if(weight == 0.0f) { + return; + } + + int srcSize = *src.GetSizePtr(); + Vtr::Index const * srcIndices = src.GetVertexIndices(); + float const * srcWeights = src.GetWeights(); + + for (int i = 0; i < srcSize; ++i) { + float w = srcWeights[i]; + if (w == 0.0f) { + continue; + } + + Vtr::Index srcIndex = srcIndices[i]; + + float wgt = weight * w; + _owner->_weightTable->AddWithWeight(srcIndex, _index, wgt, + _owner->_weightTable->GetScalarAccumulator()); + } +} + +void +StencilBuilder::Index::AddWithWeight(Stencil const& src, + float weight, float du, float dv) +{ + if(weight == 0.0f and du == 0.0f and dv == 0.0f) { + return; + } + + int srcSize = *src.GetSizePtr(); + Vtr::Index const * srcIndices = src.GetVertexIndices(); + float const * srcWeights = src.GetWeights(); + + for (int i = 0; i < srcSize; ++i) { + float w = srcWeights[i]; + if (w == 0.0f) { + continue; + } + + Vtr::Index srcIndex = srcIndices[i]; + + PointDerivWeight wgt = PointDerivWeight(weight, du, dv) * w; + _owner->_weightTable->AddWithWeight(srcIndex, _index, wgt, + _owner->_weightTable->GetPointDerivAccumulator()); + } +} + +void +StencilBuilder::Index::AddVaryingWithWeight(Index const &src, float weight) +{ + if (not _owner->_isVarying) + return; + // Ignore no-op weights. + if (weight == 0) + return; + _owner->_weightTable->AddWithWeight(src._index, _index, weight, + _owner->_weightTable->GetScalarAccumulator()); +} + +void +StencilBuilder::Index::AddFaceVaryingWithWeight(Index const &, float) +{ + // Not supported. +} + +} // end namespace Internal +} // end namespace Far +} // end namespace OPENSUBDIV_VERSION +} // end namespace OpenSubdiv + diff --git a/opensubdiv/far/stencilBuilder.h b/opensubdiv/far/stencilBuilder.h new file mode 100644 index 00000000..3623302d --- /dev/null +++ b/opensubdiv/far/stencilBuilder.h @@ -0,0 +1,110 @@ +// +// 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 OPENSUBDIV3_FAR_STENCILBUILDER_H +#define OPENSUBDIV3_FAR_STENCILBUILDER_H + +#include + +#include "../version.h" +#include "../far/stencilTable.h" + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Far { +namespace Internal { + +class WeightTable; + +class StencilBuilder { +public: + StencilBuilder(int coarseVertCount, + bool isVarying=false, + bool genCtrlVertStencils=true, + bool compactWeights=true); + ~StencilBuilder(); + + // TODO: noncopyable. + + size_t GetNumVerticesTotal() const; + + int GetNumVertsInStencil(size_t stencilIndex) const; + + // Mapping from stencil[i] to it's starting offset in the sources[] and weights[] arrays; + std::vector const& GetStencilOffsets() const; + + // The number of contributing sources and weights in stencil[i] + std::vector const& GetStencilSizes() const; + + // The absolute source vertex offsets. + std::vector const& GetStencilSources() const; + + // The individual vertex weights, each weight is paired with one source. + std::vector const& GetStencilWeights() const; + std::vector const& GetStencilDuWeights() const; + std::vector const& GetStencilDvWeights() const; + + // Vertex Facade. + class Index { + public: + Index(StencilBuilder* owner, int index) + : _owner(owner) + , _index(index) + {} + + // Add with point/vertex weight only. + void AddWithWeight(Index const & src, float weight); + void AddWithWeight(Stencil const& src, float weight); + + // Add with first derivative. + void AddWithWeight(Stencil const& src, + float weight, float du, float dv); + + void AddVaryingWithWeight(Index const &, float); + void AddFaceVaryingWithWeight(Index const &, float); + + Index operator[](int index) const { + return Index(_owner, index+_index); + } + + int GetOffset() const { return _index; } + + void Clear() {/*nothing to do here*/} + private: + StencilBuilder* _owner; + int _index; + }; + +private: + WeightTable* _weightTable; + bool _isVarying; +}; + +} // end namespace Internal +} // end namespace Far +} // end namespace OPENSUBDIV_VERSION +} // end namespace OpenSubdiv + +#endif // FAR_STENCILBUILDER_H diff --git a/opensubdiv/far/stencilTables.h b/opensubdiv/far/stencilTable.h similarity index 67% rename from opensubdiv/far/stencilTables.h rename to opensubdiv/far/stencilTable.h index 83cb8d1a..acf4879b 100644 --- a/opensubdiv/far/stencilTables.h +++ b/opensubdiv/far/stencilTable.h @@ -22,24 +22,102 @@ // language governing permissions and limitations under the Apache License. // -#ifndef OPENSUBDIV3_FAR_STENCILTABLES_H -#define OPENSUBDIV3_FAR_STENCILTABLES_H +#ifndef OPENSUBDIV3_FAR_STENCILTABLE_H +#define OPENSUBDIV3_FAR_STENCILTABLE_H #include "../version.h" #include "../far/types.h" #include +#include #include +#include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { +namespace { + void + copyStencilData(int numControlVerts, + bool includeCoarseVerts, + size_t firstOffset, + std::vector const* offsets, + std::vector * _offsets, + std::vector const* sizes, + std::vector * _sizes, + std::vector const* sources, + std::vector * _sources, + std::vector const* weights, + std::vector * _weights, + std::vector const* duWeights=NULL, + std::vector * _duWeights=NULL, + std::vector const* dvWeights=NULL, + std::vector * _dvWeights=NULL) + { + size_t off = includeCoarseVerts ? 0 : firstOffset; + + _offsets->resize(offsets->size()); + _sizes->resize(sizes->size()); + _sources->resize(sources->size()); + _weights->resize(weights->size()); + if (_duWeights) + _duWeights->resize(duWeights->size()); + if (_dvWeights) + _dvWeights->resize(dvWeights->size()); + + // The stencils are probably not in order, so we must copy/sort them. + // Note here that loop index 'i' represents stencil_i for vertex_i. + int curOffset = 0; + + size_t stencilCount = 0, + weightCount = 0; + + for (size_t i = off; i < offsets->size(); i++) { + // Once we've copied out all the control verts, jump to the offset + // where the actual stencils begin. + if ((int)i == numControlVerts) + i = firstOffset; + + // Copy the stencil. + int sz = (*sizes)[i]; + int off = (*offsets)[i]; + (*_offsets)[stencilCount] = curOffset; + (*_sizes)[stencilCount] = sz; + std::memcpy(&(*_sources)[curOffset], + &(*sources)[off], sz*sizeof(int)); + std::memcpy(&(*_weights)[curOffset], + &(*weights)[off], sz*sizeof(float)); + + if (_duWeights) { + std::memcpy(&(*_duWeights)[curOffset], + &(*duWeights)[off], sz*sizeof(float)); + } + if (_dvWeights) { + std::memcpy(&(*_dvWeights)[curOffset], + &(*dvWeights)[off], sz*sizeof(float)); + } + + curOffset += sz; + stencilCount++; + weightCount += sz; + } + + _offsets->resize(stencilCount); + _sizes->resize(stencilCount); + _sources->resize(weightCount); + if (_duWeights) + _duWeights->resize(weightCount); + if (_dvWeights) + _dvWeights->resize(weightCount); + } +}; + /// \brief Vertex stencil descriptor /// -/// Allows access and manipulation of a single stencil in a StencilTables. +/// Allows access and manipulation of a single stencil in a StencilTable. /// class Stencil { @@ -100,8 +178,8 @@ public: } protected: - friend class StencilTablesFactory; - friend class LimitStencilTablesFactory; + friend class StencilTableFactory; + friend class LimitStencilTableFactory; int * _size; Index * _indices; @@ -120,7 +198,24 @@ protected: /// recomputed simply by applying the blending weights to the series of coarse /// control vertices. /// -class StencilTables { +class StencilTable { + StencilTable(int numControlVerts, + std::vector const& offsets, + std::vector const& sizes, + std::vector const& sources, + std::vector const& weights, + bool includeCoarseVerts, + size_t firstOffset) + : _numControlVertices(numControlVerts) + { + copyStencilData(numControlVerts, + includeCoarseVerts, + firstOffset, + &offsets, &_offsets, + &sizes, &_sizes, + &sources, &_indices, + &weights, &_weights); + } public: @@ -134,7 +229,7 @@ public: return _numControlVertices; } - /// \brief Returns a Stencil at index i in the tables + /// \brief Returns a Stencil at index i in the table Stencil GetStencil(Index i) const; /// \brief Returns the number of control vertices of each stencil in the table @@ -157,7 +252,7 @@ public: return _weights; } - /// \brief Returns the stencil at index i in the tables + /// \brief Returns the stencil at index i in the table Stencil operator[] (Index index) const; /// \brief Updates point values based on the control values @@ -202,9 +297,12 @@ protected: void resize(int nstencils, int nelems); protected: - StencilTables() : _numControlVertices(0) {} + StencilTable() : _numControlVertices(0) {} + StencilTable(int numControlVerts) + : _numControlVertices(numControlVerts) + { } - friend class StencilTablesFactory; + friend class StencilTableFactory; // XXX: temporarily, GregoryBasis class will go away. friend class GregoryBasis; @@ -267,8 +365,8 @@ public: private: - friend class StencilTablesFactory; - friend class LimitStencilTablesFactory; + friend class StencilTableFactory; + friend class LimitStencilTableFactory; float * _duWeights, // pointer to stencil u derivative limit weights * _dvWeights; // pointer to stencil v derivative limit weights @@ -277,10 +375,33 @@ private: /// \brief Table of limit subdivision stencils. /// /// -class LimitStencilTables : public StencilTables { +class LimitStencilTable : public StencilTable { public: + // TODO: share construction logic + LimitStencilTable(int numControlVerts, + std::vector const& offsets, + std::vector const& sizes, + std::vector const& sources, + std::vector const& weights, + std::vector const& duWeights, + std::vector const& dvWeights, + bool includeCoarseVerts, + size_t firstOffset) + : StencilTable(numControlVerts) + { + copyStencilData(numControlVerts, + includeCoarseVerts, + firstOffset, + &offsets, &_offsets, + &sizes, &_sizes, + &sources, &_indices, + &weights, &_weights, + &duWeights, &_duWeights, + &dvWeights, &_dvWeights); + } + /// \brief Returns the 'u' derivative stencil interpolation weights std::vector const & GetDuWeights() const { return _duWeights; @@ -318,13 +439,13 @@ public: /// \brief Clears the stencils from the table void Clear() { - StencilTables::Clear(); + StencilTable::Clear(); _duWeights.clear(); _dvWeights.clear(); } private: - friend class LimitStencilTablesFactory; + friend class LimitStencilTableFactory; // Resize the table arrays (factory helper) void resize(int nstencils, int nelems); @@ -337,7 +458,7 @@ private: // Update values by appling cached stencil weights to new control values template void -StencilTables::update(T const *controlValues, T *values, +StencilTable::update(T const *controlValues, T *values, std::vector const &valueWeights, Index start, Index end) const { int const * sizes = &_sizes.at(0); @@ -370,7 +491,7 @@ StencilTables::update(T const *controlValues, T *values, } inline void -StencilTables::generateOffsets() { +StencilTable::generateOffsets() { Index offset=0; int noffsets = (int)_sizes.size(); _offsets.resize(noffsets); @@ -381,7 +502,7 @@ StencilTables::generateOffsets() { } inline void -StencilTables::resize(int nstencils, int nelems) { +StencilTable::resize(int nstencils, int nelems) { _sizes.resize(nstencils); _indices.resize(nelems); @@ -390,7 +511,7 @@ StencilTables::resize(int nstencils, int nelems) { // Returns a Stencil at index i in the table inline Stencil -StencilTables::GetStencil(Index i) const { +StencilTable::GetStencil(Index i) const { assert((not _offsets.empty()) and i<(int)_offsets.size()); @@ -402,14 +523,14 @@ StencilTables::GetStencil(Index i) const { } inline Stencil -StencilTables::operator[] (Index index) const { +StencilTable::operator[] (Index index) const { return GetStencil(index); } inline void -LimitStencilTables::resize(int nstencils, int nelems) { +LimitStencilTable::resize(int nstencils, int nelems) { - StencilTables::resize(nstencils, nelems); + StencilTable::resize(nstencils, nelems); _duWeights.resize(nelems); _dvWeights.resize(nelems); } @@ -422,4 +543,4 @@ using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv -#endif // OPENSUBDIV3_FAR_STENCILTABLES_H +#endif // OPENSUBDIV3_FAR_STENCILTABLE_H diff --git a/opensubdiv/far/stencilTableFactory.cpp b/opensubdiv/far/stencilTableFactory.cpp new file mode 100644 index 00000000..8a5326c9 --- /dev/null +++ b/opensubdiv/far/stencilTableFactory.cpp @@ -0,0 +1,482 @@ +// +// 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 "../far/stencilTableFactory.h" +#include "../far/stencilBuilder.h" +#include "../far/endCapGregoryBasisPatchFactory.h" +#include "../far/patchTable.h" +#include "../far/patchTableFactory.h" +#include "../far/patchMap.h" +#include "../far/topologyRefiner.h" + +#include +#include +#include + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { + +namespace Far { + +//------------------------------------------------------------------------------ + +void +StencilTableFactory::generateControlVertStencils( + int numControlVerts, Stencil & dst) { + + // Control vertices contribute a single index with a weight of 1.0 + for (int i=0; i_numControlVertices = refiner.GetLevel(0).GetNumVertices(); + return result; + } + + bool interpolateVarying = options.interpolationMode==INTERPOLATE_VARYING; + Internal::StencilBuilder builder(refiner.GetLevel(0).GetNumVertices(), + interpolateVarying, + /*genControlVerts*/ true, + /*compactWeights*/ true); + + // + // Interpolate stencils for each refinement level using + // TopologyRefiner::InterpolateLevel<>() + // + Internal::StencilBuilder::Index srcIndex(&builder, 0); + Internal::StencilBuilder::Index dstIndex(&builder, + refiner.GetLevel(0).GetNumVertices()); + for (int level=1; level<=maxlevel; ++level) { + if (not interpolateVarying) { + refiner.Interpolate(level, srcIndex, dstIndex); + } else { + refiner.InterpolateVarying(level, srcIndex, dstIndex); + } + + srcIndex = dstIndex; + dstIndex = dstIndex[refiner.GetLevel(level).GetNumVertices()]; + } + + + size_t firstOffset = refiner.GetLevel(0).GetNumVertices(); + if (not options.generateIntermediateLevels) + firstOffset = srcIndex.GetOffset(); + + // Copy stencils from the pool allocator into the tables + // always initialize numControlVertices (useful for torus case) + StencilTable * result = + new StencilTable(refiner.GetLevel(0).GetNumVertices(), + builder.GetStencilOffsets(), + builder.GetStencilSizes(), + builder.GetStencilSources(), + builder.GetStencilWeights(), + options.generateControlVerts, + firstOffset); + return result; +} + +//------------------------------------------------------------------------------ + +StencilTable const * +StencilTableFactory::Create(int numTables, StencilTable const ** tables) { + + // XXXtakahito: + // This function returns NULL for empty inputs or erroneous condition. + // It's convenient for skipping varying stencils etc, however, + // other Create() API returns an empty stencil instead of NULL. + // They need to be consistent. + + if ( (numTables<=0) or (not tables)) { + return NULL; + } + + int ncvs = -1, + nstencils = 0, + nelems = 0; + + for (int i=0; i= 0 and st->GetNumControlVertices() != ncvs) { + return NULL; + } + ncvs = st->GetNumControlVertices(); + nstencils += st->GetNumStencils(); + nelems += (int)st->GetControlIndices().size(); + } + + if (ncvs == -1) { + return NULL; + } + + StencilTable * result = new StencilTable; + result->resize(nstencils, nelems); + + int * sizes = &result->_sizes[0]; + Index * indices = &result->_indices[0]; + float * weights = &result->_weights[0]; + for (int i=0; iGetNumStencils(), + st_nelems = (int)st->_indices.size(); + memcpy(sizes, &st->_sizes[0], st_nstencils*sizeof(int)); + memcpy(indices, &st->_indices[0], st_nelems*sizeof(Index)); + memcpy(weights, &st->_weights[0], st_nelems*sizeof(float)); + + sizes += st_nstencils; + indices += st_nelems; + weights += st_nelems; + } + + result->_numControlVertices = ncvs; + + // have to re-generate offsets from scratch + result->generateOffsets(); + + return result; +} + +//------------------------------------------------------------------------------ + +StencilTable const * +StencilTableFactory::AppendEndCapStencilTable( + TopologyRefiner const &refiner, + StencilTable const * baseStencilTable, + StencilTable const * endCapStencilTable, + bool factorize) { + + // factorize and append. + if (baseStencilTable == NULL or + endCapStencilTable == NULL) return NULL; + + // endcap stencils have indices that are relative to the level + // (maxlevel) of subdivision. These indices need to be offset to match + // the indices from the multi-level adaptive stencil table. + // In addition: stencil table can be built with singular stencils + // (single weight of 1.0f) as place-holders for coarse mesh vertices, + // which also needs to be accounted for. + + int stencilsIndexOffset = 0; + int controlVertsIndexOffset = 0; + int nBaseStencils = baseStencilTable->GetNumStencils(); + int nBaseStencilsElements = (int)baseStencilTable->_indices.size(); + { + int maxlevel = refiner.GetMaxLevel(); + int nverts = refiner.GetNumVerticesTotal(); + if (nBaseStencils == nverts) { + + // the table contain stencils for the control vertices + // + // <----------------- nverts ------------------> + // + // +---------------+----------------------------+-----------------+ + // | control verts | refined verts : (max lv) | endcap points | + // +---------------+----------------------------+-----------------+ + // | base stencil table | endcap stencils | + // +--------------------------------------------+-----------------+ + // : ^ / + // : \_________/ + // <--------------------------------> + // stencilsIndexOffset + // + // + stencilsIndexOffset = nverts - refiner.GetLevel(maxlevel).GetNumVertices(); + controlVertsIndexOffset = stencilsIndexOffset; + + } else if (nBaseStencils == (nverts -refiner.GetLevel(0).GetNumVertices())) { + + // the table does not contain stencils for the control vertices + // + // <----------------- nverts ------------------> + // <------ nBaseStencils -------> + // +---------------+----------------------------+-----------------+ + // | control verts | refined verts : (max lv) | endcap points | + // +---------------+----------------------------+-----------------+ + // | base stencil table | endcap stencils | + // +----------------------------+-----------------+ + // : ^ / + // : \_________/ + // <----------------> + // stencilsIndexOffset + // <--------------------------------> + // controlVertsIndexOffset + // + stencilsIndexOffset = nBaseStencils - refiner.GetLevel(maxlevel).GetNumVertices(); + controlVertsIndexOffset = nverts - refiner.GetLevel(maxlevel).GetNumVertices(); + + } else { + // these are not the stencils you are looking for. + assert(0); + return NULL; + } + } + + // copy all endcap stencils to proto stencils, and factorize if needed. + int nEndCapStencils = endCapStencilTable->GetNumStencils(); + int nEndCapStencilsElements = 0; + + Internal::StencilBuilder builder(refiner.GetLevel(0).GetNumVertices(), + /*isVarying*/ false, + /*genControlVerts*/ false, + /*compactWeights*/ factorize); + Internal::StencilBuilder::Index origin(&builder, 0); + Internal::StencilBuilder::Index dst = origin; + Internal::StencilBuilder::Index srcIdx = origin; + + for (int i = 0 ; i < nEndCapStencils; ++i) { + Stencil src = endCapStencilTable->GetStencil(i); + dst = origin[i]; + for (int j = 0; j < src.GetSize(); ++j) { + Index index = src.GetVertexIndices()[j]; + float weight = src.GetWeights()[j]; + if (weight == 0.0) continue; + + if (factorize) { + dst.AddWithWeight( + baseStencilTable->GetStencil(index+stencilsIndexOffset), + weight); + } else { + srcIdx = origin[index + controlVertsIndexOffset]; + dst.AddWithWeight(srcIdx, weight); + } + } + nEndCapStencilsElements += builder.GetNumVertsInStencil(i); + } + + // create new stencil table + StencilTable * result = new StencilTable; + result->_numControlVertices = refiner.GetLevel(0).GetNumVertices(); + result->resize(nBaseStencils + nEndCapStencils, + nBaseStencilsElements + nEndCapStencilsElements); + + int* sizes = &result->_sizes[0]; + Index * indices = &result->_indices[0]; + float * weights = &result->_weights[0]; + + // put base stencils first + memcpy(sizes, &baseStencilTable->_sizes[0], + nBaseStencils*sizeof(int)); + memcpy(indices, &baseStencilTable->_indices[0], + nBaseStencilsElements*sizeof(Index)); + memcpy(weights, &baseStencilTable->_weights[0], + nBaseStencilsElements*sizeof(float)); + + sizes += nBaseStencils; + indices += nBaseStencilsElements; + weights += nBaseStencilsElements; + + // endcap stencils second + for (int i = 0 ; i < nEndCapStencils; ++i) { + int size = builder.GetNumVertsInStencil(i); + int idx = builder.GetStencilOffsets()[i]; + for (int j = 0; j < size; ++j) { + *indices++ = builder.GetStencilSources()[idx+j]; + *weights++ = builder.GetStencilWeights()[idx+j]; + } + *sizes++ = size; + } + + // have to re-generate offsets from scratch + result->generateOffsets(); + + return result; +} + +//------------------------------------------------------------------------------ +LimitStencilTable const * +LimitStencilTableFactory::Create(TopologyRefiner const & refiner, + LocationArrayVec const & locationArrays, StencilTable const * cvStencilsIn, + PatchTable const * patchTableIn) { + + // Compute the total number of stencils to generate + int numStencils=0, numLimitStencils=0; + for (int i=0; i<(int)locationArrays.size(); ++i) { + assert(locationArrays[i].numLocations>=0); + numStencils += locationArrays[i].numLocations; + } + if (numStencils<=0) { + return 0; + } + + bool uniform = refiner.IsUniform(); + + int maxlevel = refiner.GetMaxLevel(); + + StencilTable const * cvstencils = cvStencilsIn; + if (not cvstencils) { + // Generate stencils for the control vertices - this is necessary to + // properly factorize patches with control vertices at level 0 (natural + // regular patches, such as in a torus) + // note: the control vertices of the mesh are added as single-index + // stencils of weight 1.0f + StencilTableFactory::Options options; + options.generateIntermediateLevels = uniform ? false :true; + options.generateControlVerts = true; + options.generateOffsets = true; + + // PERFORMANCE: We could potentially save some mem-copies by not + // instanciating the stencil tables and work directly off the source + // data. + cvstencils = StencilTableFactory::Create(refiner, options); + } else { + // Sanity checks + if (cvstencils->GetNumStencils() != (uniform ? + refiner.GetLevel(maxlevel).GetNumVertices() : + refiner.GetNumVerticesTotal())) { + return 0; + } + } + + // If a stencil table was given, use it, otherwise, create a new one + PatchTable const * patchtable = patchTableIn; + + if (not patchtable) { + // XXXX (manuelk) If no patch-table was passed, we should be able to + // infer the patches fairly easily from the refiner. Once more tags + // have been added to the refiner, maybe we can remove the need for the + // patch table. + + PatchTableFactory::Options options; + options.SetEndCapType( + Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS); + + patchtable = PatchTableFactory::Create(refiner, options); + + if (not cvStencilsIn) { + // if cvstencils is just created above, append endcap stencils + if (StencilTable const *endCapStencilTable = + patchtable->GetEndCapVertexStencilTable()) { + StencilTable const *table = + StencilTableFactory::AppendEndCapStencilTable( + refiner, cvstencils, endCapStencilTable); + delete cvstencils; + cvstencils = table; + } + } + } else { + // Sanity checks + if (patchtable->IsFeatureAdaptive()==uniform) { + if (not cvStencilsIn) { + assert(cvstencils and cvstencils!=cvStencilsIn); + delete cvstencils; + } + return 0; + } + } + + assert(patchtable and cvstencils); + + // Create a patch-map to locate sub-patches faster + PatchMap patchmap( *patchtable ); + + // + // Generate limit stencils for locations + // + + Internal::StencilBuilder builder(refiner.GetLevel(0).GetNumVertices(), + /*isVarying*/ false, + /*genControlVerts*/ false, + /*compactWeights*/ true); + Internal::StencilBuilder::Index origin(&builder, 0); + Internal::StencilBuilder::Index dst = origin; + + float wP[20], wDs[20], wDt[20]; + + for (size_t i=0; i=0); + + for (int j=0; jGetPatchVertices(*handle); + + patchtable->EvaluateBasis(*handle, s, t, wP, wDs, wDt); + + StencilTable const & src = *cvstencils; + dst = origin[numLimitStencils]; + + dst.Clear(); + for (int k = 0; k < cvs.size(); ++k) { + dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k]); + } + + ++numLimitStencils; + } + } + } + + if (not cvStencilsIn) { + delete cvstencils; + } + + if (not patchTableIn) { + delete patchtable; + } + + // + // Copy the proto-stencils into the limit stencil table + // + size_t firstOffset = refiner.GetLevel(0).GetNumVertices(); + + LimitStencilTable * result = new LimitStencilTable( + refiner.GetLevel(0).GetNumVertices(), + builder.GetStencilOffsets(), + builder.GetStencilSizes(), + builder.GetStencilSources(), + builder.GetStencilWeights(), + builder.GetStencilDuWeights(), + builder.GetStencilDvWeights(), + /*ctrlVerts*/false, + firstOffset); + return result; +} + +} // end namespace Far + +} // end namespace OPENSUBDIV_VERSION +} // end namespace OpenSubdiv diff --git a/opensubdiv/far/stencilTablesFactory.h b/opensubdiv/far/stencilTableFactory.h similarity index 76% rename from opensubdiv/far/stencilTablesFactory.h rename to opensubdiv/far/stencilTableFactory.h index 57925231..d7544c58 100644 --- a/opensubdiv/far/stencilTablesFactory.h +++ b/opensubdiv/far/stencilTableFactory.h @@ -27,7 +27,7 @@ #include "../version.h" -#include "../far/patchTables.h" +#include "../far/patchTable.h" #include @@ -39,13 +39,13 @@ namespace Far { class TopologyRefiner; class Stencil; -class StencilTables; +class StencilTable; class LimitStencil; -class LimitStencilTables; +class LimitStencilTable; -/// \brief A specialized factory for StencilTables +/// \brief A specialized factory for StencilTable /// -class StencilTablesFactory { +class StencilTableFactory { public: @@ -73,7 +73,7 @@ public: maxLevel : 4; ///< generate stencils up to 'maxLevel' }; - /// \brief Instantiates StencilTables from TopologyRefiner that have been + /// \brief Instantiates StencilTable from TopologyRefiner that have been /// refined uniformly or adaptively. /// /// \note The factory only creates stencils for vertices that have already @@ -82,45 +82,45 @@ public: /// /// @param refiner The TopologyRefiner containing the topology /// - /// @param options Options controlling the creation of the tables + /// @param options Options controlling the creation of the table /// - static StencilTables const * Create(TopologyRefiner const & refiner, + static StencilTable const * Create(TopologyRefiner const & refiner, Options options = Options()); - /// \brief Instantiates StencilTables by concatenating an array of existing - /// stencil tables. + /// \brief Instantiates StencilTable by concatenating an array of existing + /// stencil table. /// - /// \note This factory checks that the stencil tables point to the same set + /// \note This factory checks that the stencil table point to the same set /// of supporting control vertices - no re-indexing is done. /// GetNumControlVertices() *must* return the same value for all input /// tables. /// /// @param numTables Number of input StencilTables /// - /// @param tables Array of input StencilTables + /// @param table Array of input StencilTables /// - static StencilTables const * Create(int numTables, StencilTables const ** tables); + static StencilTable const * Create(int numTables, StencilTable const ** tables); /// \brief Utility function for stencil splicing for endcap stencils. /// /// @param refiner The TopologyRefiner containing the topology /// - /// @param baseStencilTables Input StencilTables for refined vertices + /// @param baseStencilTable Input StencilTable for refined vertices /// - /// @param endCapStencilTables EndCap basis conversion stencils. This stenciltable + /// @param endCapStencilTable EndCap basis conversion stencils. This stenciltable /// has to be relative to the max level of subdivision. /// /// @param factorize If factorize sets to true, endcap stencils will be /// factorized with supporting vertices from baseStencil - /// tables so that the endcap points can be computed + /// table so that the endcap points can be computed /// directly from control vertices. /// - static StencilTables const * AppendEndCapStencilTables( + static StencilTable const * AppendEndCapStencilTable( TopologyRefiner const &refiner, - StencilTables const *baseStencilTables, - StencilTables const *endCapStencilTables, + StencilTable const *baseStencilTable, + StencilTable const *endCapStencilTable, bool factorize = true); private: @@ -129,9 +129,9 @@ private: static void generateControlVertStencils(int numControlVerts, Stencil & dst); }; -/// \brief A specialized factory for LimitStencilTables +/// \brief A specialized factory for LimitStencilTable /// -/// The LimitStencilTablesFactory creates tables of limit stencils. Limit +/// The LimitStencilTableFactory creates a table of limit stencils. Limit /// stencils can interpolate any arbitrary location on the limit surface. /// The stencils will be bilinear if the surface is refined uniformly, and /// bicubic if feature adaptive isolation is used instead. @@ -140,7 +140,7 @@ private: /// normalized (s,t) patch coordinates. The factory exposes the LocationArray /// struct as a container for these location descriptors. /// -class LimitStencilTablesFactory { +class LimitStencilTableFactory { public: @@ -158,7 +158,7 @@ public: typedef std::vector LocationArrayVec; - /// \brief Instantiates LimitStencilTables from a TopologyRefiner that has + /// \brief Instantiates LimitStencilTable from a TopologyRefiner that has /// been refined either uniformly or adaptively. /// /// @param refiner The TopologyRefiner containing the topology @@ -166,18 +166,18 @@ public: /// @param locationArrays An array of surface location descriptors /// (see LocationArray) /// - /// @param cvStencils A set of StencilTables generated from the + /// @param cvStencils A set of StencilTable generated from the /// TopologyRefiner (optional: prevents redundant - /// instanciation of the tables if available) + /// instanciation of the table if available) /// - /// @param patchTables A set of PatchTables generated from the + /// @param patchTable A set of PatchTable generated from the /// TopologyRefiner (optional: prevents redundant - /// instanciation of the tables if available) + /// instanciation of the table if available) /// - static LimitStencilTables const * Create(TopologyRefiner const & refiner, + static LimitStencilTable const * Create(TopologyRefiner const & refiner, LocationArrayVec const & locationArrays, - StencilTables const * cvStencils=0, - PatchTables const * patchTables=0); + StencilTable const * cvStencils=0, + PatchTable const * patchTable=0); }; diff --git a/opensubdiv/far/stencilTablesFactory.cpp b/opensubdiv/far/stencilTablesFactory.cpp deleted file mode 100644 index 16c4448c..00000000 --- a/opensubdiv/far/stencilTablesFactory.cpp +++ /dev/null @@ -1,573 +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 "../far/stencilTablesFactory.h" -#include "../far/endCapGregoryBasisPatchFactory.h" -#include "../far/patchTables.h" -#include "../far/patchTablesFactory.h" -#include "../far/patchMap.h" -#include "../far/protoStencil.h" -#include "../far/topologyRefiner.h" - -#include -#include - -namespace OpenSubdiv { -namespace OPENSUBDIV_VERSION { - -namespace Far { - -//------------------------------------------------------------------------------ - -void -StencilTablesFactory::generateControlVertStencils( - int numControlVerts, Stencil & dst) { - - // Control vertices contribute a single index with a weight of 1.0 - for (int i=0; i_numControlVertices = refiner.GetNumVertices(0); - - int maxlevel = std::min(int(options.maxLevel), refiner.GetMaxLevel()); - if (maxlevel==0 and (not options.generateControlVerts)) { - return result; - } - - // 'maxsize' reflects the size of the default supporting basis factorized - // in the stencils, with a little bit of head-room. Each subdivision scheme - // has a set valence for 'regular' vertices, which drives the size of the - // supporting basis of control-vertices. The goal is to reduce the number - // of incidences where the pool allocator has to switch to dynamically - // allocated heap memory when encountering extraordinary vertices that - // require a larger supporting basis. - // - // The maxsize settings we use follow the assumption that the vast - // majority of the vertices in a mesh are regular, and that the valence - // of the extraordinary vertices is only higher by 1 edge. - int maxsize = 0; - bool interpolateVarying = false; - switch (options.interpolationMode) { - case INTERPOLATE_VERTEX: { - Sdc::SchemeType type = refiner.GetSchemeType(); - switch (type) { - case Sdc::SCHEME_BILINEAR : maxsize = 5; break; - case Sdc::SCHEME_CATMARK : maxsize = 17; break; - case Sdc::SCHEME_LOOP : maxsize = 10; break; - default: - assert(0); - } - } break; - case INTERPOLATE_VARYING: maxsize = 5; interpolateVarying=true; break; - default: - assert(0); - } - - std::vector allocators( - options.generateIntermediateLevels ? maxlevel+1 : 2, - StencilAllocator(maxsize, interpolateVarying)); - - StencilAllocator * srcAlloc = &allocators[0], - * dstAlloc = &allocators[1]; - - // - // Interpolate stencils for each refinement level using - // TopologyRefiner::InterpolateLevel<>() - // - for (int level=1;level<=maxlevel; ++level) { - - dstAlloc->Resize(refiner.GetNumVertices(level)); - - if (options.interpolationMode==INTERPOLATE_VERTEX) { - refiner.Interpolate(level, *srcAlloc, *dstAlloc); - } else { - refiner.InterpolateVarying(level, *srcAlloc, *dstAlloc); - } - - if (options.generateIntermediateLevels) { - if (levelGetNumStencils(); - nelems = srcAlloc->GetNumVerticesTotal(); - } - - // Allocate - result->_numControlVertices = refiner.GetNumVertices(0); - - if (options.generateControlVerts) { - nstencils += result->_numControlVertices; - nelems += result->_numControlVertices; - } - result->resize(nstencils, nelems); - - // Copy stencils - Stencil dst(&result->_sizes.at(0), - &result->_indices.at(0), &result->_weights.at(0)); - - if (options.generateControlVerts) { - generateControlVertStencils(result->_numControlVertices, dst); - } - - if (options.generateIntermediateLevels) { - for (int level=1; level<=maxlevel; ++level) { - for (int i=0; iGetNumStencils(); ++i) { - *dst._size = srcAlloc->CopyStencil(i, dst._indices, dst._weights); - dst.Next(); - } - } - - if (options.generateOffsets) { - result->generateOffsets(); - } - } - - return result; -} - -//------------------------------------------------------------------------------ - -StencilTables const * -StencilTablesFactory::Create(int numTables, StencilTables const ** tables) { - - // XXXtakahito: - // This function returns NULL for empty inputs or erroneous condition. - // It's convenient for skipping varying stencils etc, however, - // other Create() API returns an empty stencil instead of NULL. - // They need to be consistent. - - if ( (numTables<=0) or (not tables)) { - return NULL; - } - - int ncvs = -1, - nstencils = 0, - nelems = 0; - - for (int i=0; i= 0 and st->GetNumControlVertices() != ncvs) { - return NULL; - } - ncvs = st->GetNumControlVertices(); - nstencils += st->GetNumStencils(); - nelems += (int)st->GetControlIndices().size(); - } - - if (ncvs == -1) { - return NULL; - } - - StencilTables * result = new StencilTables; - result->resize(nstencils, nelems); - - int * sizes = &result->_sizes[0]; - Index * indices = &result->_indices[0]; - float * weights = &result->_weights[0]; - for (int i=0; iGetNumStencils(), - st_nelems = (int)st->_indices.size(); - memcpy(sizes, &st->_sizes[0], st_nstencils*sizeof(int)); - memcpy(indices, &st->_indices[0], st_nelems*sizeof(Index)); - memcpy(weights, &st->_weights[0], st_nelems*sizeof(float)); - - sizes += st_nstencils; - indices += st_nelems; - weights += st_nelems; - } - - result->_numControlVertices = ncvs; - - // have to re-generate offsets from scratch - result->generateOffsets(); - - return result; -} - -//------------------------------------------------------------------------------ - -StencilTables const * -StencilTablesFactory::AppendEndCapStencilTables( - TopologyRefiner const &refiner, - StencilTables const *baseStencilTables, - StencilTables const *endCapStencilTables, - bool factorize) { - - // factorize and append. - if (baseStencilTables == NULL or - endCapStencilTables == NULL) return NULL; - - // endcap stencils have indices that are relative to the level - // (maxlevel) of subdivision. These indices need to be offset to match - // the indices from the multi-level adaptive stencil tables. - // In addition: stencil tables can be built with singular stencils - // (single weight of 1.0f) as place-holders for coarse mesh vertices, - // which also needs to be accounted for. - - int stencilsIndexOffset = 0; - int controlVertsIndexOffset = 0; - int nBaseStencils = baseStencilTables->GetNumStencils(); - int nBaseStencilsElements = (int)baseStencilTables->_indices.size(); - { - int maxlevel = refiner.GetMaxLevel(); - int nverts = refiner.GetNumVerticesTotal(); - if (nBaseStencils == nverts) { - - // the table contain stencils for the control vertices - // - // <----------------- nverts ------------------> - // - // +---------------+----------------------------+-----------------+ - // | control verts | refined verts : (max lv) | endcap points | - // +---------------+----------------------------+-----------------+ - // | base stencil tables | endcap stencils | - // +--------------------------------------------+-----------------+ - // : ^ / - // : \_________/ - // <--------------------------------> - // stencilsIndexOffset - // - // - stencilsIndexOffset = nverts - refiner.GetNumVertices(maxlevel); - controlVertsIndexOffset = stencilsIndexOffset; - - } else if (nBaseStencils == (nverts -refiner.GetNumVertices(0))) { - - // the table does not contain stencils for the control vertices - // - // <----------------- nverts ------------------> - // <------ nBaseStencils -------> - // +---------------+----------------------------+-----------------+ - // | control verts | refined verts : (max lv) | endcap points | - // +---------------+----------------------------+-----------------+ - // | base stencil tables | endcap stencils | - // +----------------------------+-----------------+ - // : ^ / - // : \_________/ - // <----------------> - // stencilsIndexOffset - // <--------------------------------> - // controlVertsIndexOffset - // - stencilsIndexOffset = nBaseStencils - refiner.GetNumVertices(maxlevel); - controlVertsIndexOffset = nverts - refiner.GetNumVertices(maxlevel); - - } else { - // these are not the stencils you are looking for. - assert(0); - return NULL; - } - } - - // copy all endcap stencils to proto stencils, and factorize if needed. - int nEndCapStencils = endCapStencilTables->GetNumStencils(); - int nEndCapStencilsElements = 0; - - // we exclude zero weight stencils. the resulting number of - // stencils of endcap may be different from input. - StencilAllocator allocator(16); - allocator.Resize(nEndCapStencils); - for (int i = 0 ; i < nEndCapStencils; ++i) { - Stencil src = endCapStencilTables->GetStencil(i); - allocator[i].Clear(); - for (int j = 0; j < src.GetSize(); ++j) { - Index index = src.GetVertexIndices()[j]; - float weight = src.GetWeights()[j]; - if (weight == 0.0) continue; - - if (factorize) { - allocator[i].AddWithWeight(*baseStencilTables, - index + stencilsIndexOffset, - weight); - } else { - allocator.PushBackVertex(i, - index + controlVertsIndexOffset, - weight); - } - } - nEndCapStencilsElements += allocator.GetSize(i); - } - - // create new stencil tables - StencilTables * result = new StencilTables; - result->_numControlVertices = refiner.GetNumVertices(0); - result->resize(nBaseStencils + nEndCapStencils, - nBaseStencilsElements + nEndCapStencilsElements); - - int* sizes = &result->_sizes[0]; - Index * indices = &result->_indices[0]; - float * weights = &result->_weights[0]; - - // put base stencils first - memcpy(sizes, &baseStencilTables->_sizes[0], - nBaseStencils*sizeof(int)); - memcpy(indices, &baseStencilTables->_indices[0], - nBaseStencilsElements*sizeof(Index)); - memcpy(weights, &baseStencilTables->_weights[0], - nBaseStencilsElements*sizeof(float)); - - sizes += nBaseStencils; - indices += nBaseStencilsElements; - weights += nBaseStencilsElements; - - // endcap stencils second - for (int i = 0 ; i < nEndCapStencils; ++i) { - int size = allocator.GetSize(i); - for (int j = 0; j < size; ++j) { - *indices++ = allocator.GetIndices(i)[j]; - *weights++ = allocator.GetWeights(i)[j]; - } - *sizes++ = size; - } - - // have to re-generate offsets from scratch - result->generateOffsets(); - - return result; -} - -//------------------------------------------------------------------------------ -LimitStencilTables const * -LimitStencilTablesFactory::Create(TopologyRefiner const & refiner, - LocationArrayVec const & locationArrays, StencilTables const * cvStencils, - PatchTables const * patchTables) { - - // Compute the total number of stencils to generate - int numStencils=0, numLimitStencils=0; - for (int i=0; i<(int)locationArrays.size(); ++i) { - assert(locationArrays[i].numLocations>=0); - numStencils += locationArrays[i].numLocations; - } - if (numStencils<=0) { - return 0; - } - - bool uniform = refiner.IsUniform(); - - int maxlevel = refiner.GetMaxLevel(), maxsize=17; - - StencilTables const * cvstencils = cvStencils; - if (not cvstencils) { - // Generate stencils for the control vertices - this is necessary to - // properly factorize patches with control vertices at level 0 (natural - // regular patches, such as in a torus) - // note: the control vertices of the mesh are added as single-index - // stencils of weight 1.0f - StencilTablesFactory::Options options; - options.generateIntermediateLevels = uniform ? false :true; - options.generateControlVerts = true; - options.generateOffsets = true; - - // XXXX (manuelk) We could potentially save some mem-copies by not - // instanciating the stencil tables and work directly off the pool - // allocators. - cvstencils = StencilTablesFactory::Create(refiner, options); - } else { - // Sanity checks - if (cvstencils->GetNumStencils() != (uniform ? - refiner.GetNumVertices(maxlevel) : - refiner.GetNumVerticesTotal())) { - return 0; - } - } - - // If a stencil table was given, use it, otherwise, create a new one - PatchTables const * patchtables = patchTables; - - if (not patchTables) { - // XXXX (manuelk) If no patch-tables was passed, we should be able to - // infer the patches fairly easily from the refiner. Once more tags - // have been added to the refiner, maybe we can remove the need for the - // patch tables. - - PatchTablesFactory::Options options; - options.SetEndCapType( - Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS); - - patchtables = PatchTablesFactory::Create(refiner, options); - - if (not cvStencils) { - // if cvstencils is just created above, append endcap stencils - if (StencilTables const *endCapStencilTables = - patchtables->GetEndCapVertexStencilTables()) { - StencilTables const *tables = - StencilTablesFactory::AppendEndCapStencilTables( - refiner, cvstencils, endCapStencilTables); - delete cvstencils; - cvstencils = tables; - } - } - } else { - // Sanity checks - if (patchTables->IsFeatureAdaptive()==uniform) { - if (not cvStencils) { - assert(cvstencils and cvstencils!=cvStencils); - delete cvstencils; - } - return 0; - } - } - - assert(patchtables and cvstencils); - - // Create a patch-map to locate sub-patches faster - PatchMap patchmap( *patchtables ); - - // - // Generate limit stencils for locations - // - - // Create a pool allocator to accumulate ProtoLimitStencils - LimitStencilAllocator alloc(maxsize); - alloc.Resize(numStencils); - - // XXXX (manuelk) we can make uniform (bilinear) stencils faster with a - // dedicated code path that does not use PatchTables or the PatchMap - float wP[20], wDs[20], wDt[20]; - - for (int i=0, currentStencil=0; i<(int)locationArrays.size(); ++i) { - - LocationArray const & array = locationArrays[i]; - - assert(array.ptexIdx>=0); - - for (int j=0; jGetPatchVertices(*handle); - - patchTables->EvaluateBasis(*handle, s, t, wP, wDs, wDt); - - StencilTables const & src = *cvstencils; - ProtoLimitStencil dst = alloc[currentStencil]; - - dst.Clear(); - for (int k = 0; k < cvs.size(); ++k) { - dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k]); - } - - ++numLimitStencils; - } - } - } - - if (not cvStencils) { - delete cvstencils; - } - - if (not patchTables) { - delete patchtables; - } - - // - // Copy the proto-stencils into the limit stencil tables - // - LimitStencilTables * result = new LimitStencilTables; - - int nelems = alloc.GetNumVerticesTotal(); - if (nelems>0) { - - // Allocate - result->resize(numLimitStencils, nelems); - - // Copy stencils - LimitStencil dst(&result->_sizes.at(0), &result->_indices.at(0), - &result->_weights.at(0), &result->_duWeights.at(0), - &result->_dvWeights.at(0)); - - for (int i=0; igenerateOffsets(); - } - result->_numControlVertices = refiner.GetNumVertices(0); - - return result; -} - -} // end namespace Far - -} // end namespace OPENSUBDIV_VERSION -} // end namespace OpenSubdiv diff --git a/opensubdiv/far/topologyRefiner.cpp b/opensubdiv/far/topologyRefiner.cpp index 385eee0f..f9e208fe 100644 --- a/opensubdiv/far/topologyRefiner.cpp +++ b/opensubdiv/far/topologyRefiner.cpp @@ -192,18 +192,6 @@ TopologyRefiner::GetNumFVarValuesTotal(int channel) const { return sum; } -int -TopologyRefiner::GetNumHoles(int level) const { - int sum = 0; - Vtr::Level const & lvl = getLevel(level); - for (Index face = 0; face < lvl.getNumFaces(); ++face) { - if (lvl.isFaceHole(face)) { - ++sum; - } - } - return sum; -} - // // Main refinement method -- allocating and initializing levels and refinements: diff --git a/opensubdiv/far/topologyRefiner.h b/opensubdiv/far/topologyRefiner.h index d27d7705..48cd5753 100644 --- a/opensubdiv/far/topologyRefiner.h +++ b/opensubdiv/far/topologyRefiner.h @@ -217,8 +217,8 @@ public: /// \brief Apply vertex and varying interpolation weights to a primvar /// buffer /// - /// The destination buffer must allocate an array of data for all the - /// refined vertices (at least GetNumVerticesTotal()-GetNumVertices(0)) + /// The destination buffer must allocate an array of data for all the refined + /// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices()) /// /// @param src Source primvar buffer (\ref templating control vertex data) /// @@ -231,7 +231,7 @@ public: /// level of refinement. /// /// The destination buffer must allocate an array of data for all the - /// refined vertices (at least GetNumVertices(level)) + /// refined vertices (at least GetLevel(level).GetNumVertices()) /// /// @param level The refinement level /// @@ -247,8 +247,8 @@ public: /// This method can be a useful alternative if the varying primvar data /// does not need to be re-computed over time. /// - /// The destination buffer must allocate an array of data for all the - /// refined vertices (at least GetNumVerticesTotal()-GetNumVertices(0)) + /// The destination buffer must allocate an array of data for all the refined + /// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices()) /// /// @param src Source primvar buffer (\ref templating control vertex data) /// @@ -263,7 +263,7 @@ public: /// does not need to be re-computed over time. /// /// The destination buffer must allocate an array of data for all the - /// refined vertices (at least GetNumVertices(level)) + /// refined vertices (at least GetLevel(level).GetNumVertices()) /// /// @param level The refinement level /// @@ -288,7 +288,7 @@ public: /// The source buffer must refer to an array of previously interpolated /// vertex data for the last refinement level. The destination buffer /// must allocate an array for all vertices at the last refinement level - /// (at least GetNumVertices(GetMaxLevel())) + /// (at least GetLevel(GetMaxLevel()).GetNumVertices()) /// /// @param src Source primvar buffer (refined vertex data) for last level /// @@ -317,73 +317,6 @@ public: //@} - - // - // Access to data per-level -- being made obsolete via this->GetLevel(level).Method(): - // - // Component inventory: - int GetNumVertices(int level) const { return GetLevel(level).GetNumVertices(); } - int GetNumEdges(int level) const { return GetLevel(level).GetNumEdges(); } - int GetNumFaces(int level) const { return GetLevel(level).GetNumFaces(); } - int GetNumFaceVertices(int level) const { return GetLevel(level).GetNumFaceVertices(); } - - // Component tags: - float GetEdgeSharpness(int level, Index e) const { return GetLevel(level).GetEdgeSharpness(e); } - float GetVertexSharpness(int level, Index v) const { return GetLevel(level).GetVertexSharpness(v); } - bool IsFaceHole(int level, Index f) const { return GetLevel(level).IsFaceHole(f); } - - Sdc::Crease::Rule GetVertexRule(int level, Index v) const { return GetLevel(level).GetVertexRule(v); } - - // Face-varying values: - int GetNumFVarValues(int level, int channel = 0) const { return GetLevel(level).GetNumFVarValues(channel); } - ConstIndexArray GetFVarFaceValues(int level, Index f, int channel = 0) const { return GetLevel(level).GetFVarFaceValues(f, channel); } - - // Component neighbors: - ConstIndexArray GetFaceVertices(int level, Index f) const { return GetLevel(level).GetFaceVertices(f); } - ConstIndexArray GetFaceEdges(int level, Index f) const { return GetLevel(level).GetFaceEdges(f); } - ConstIndexArray GetEdgeVertices(int level, Index e) const { return GetLevel(level).GetEdgeVertices(e); } - ConstIndexArray GetEdgeFaces(int level, Index e) const { return GetLevel(level).GetEdgeFaces(e); } - ConstIndexArray GetVertexFaces(int level, Index v) const { return GetLevel(level).GetVertexFaces(v); } - ConstIndexArray GetVertexEdges(int level, Index v) const { return GetLevel(level).GetVertexEdges(v); } - - ConstLocalIndexArray GetEdgeFaceLocalIndices(int level, Index e) const { return GetLevel(level).GetEdgeFaceLocalIndices(e); } - ConstLocalIndexArray GetVertexFaceLocalIndices(int level, Index v) const { return GetLevel(level).GetVertexFaceLocalIndices(v); } - ConstLocalIndexArray GetVertexEdgeLocalIndices(int level, Index v) const { return GetLevel(level).GetVertexEdgeLocalIndices(v); } - - Index FindEdge(int level, Index v0, Index v1) const { return GetLevel(level).FindEdge(v0, v1); } - - // Child components: - ConstIndexArray GetFaceChildFaces(int level, Index f) const { return GetLevel(level).GetFaceChildFaces(f); } - ConstIndexArray GetFaceChildEdges(int level, Index f) const { return GetLevel(level).GetFaceChildEdges(f); } - ConstIndexArray GetEdgeChildEdges(int level, Index e) const { return GetLevel(level).GetEdgeChildEdges(e); } - - Index GetFaceChildVertex( int level, Index f) const { return GetLevel(level).GetFaceChildVertex(f); } - Index GetEdgeChildVertex( int level, Index e) const { return GetLevel(level).GetEdgeChildVertex(e); } - Index GetVertexChildVertex(int level, Index v) const { return GetLevel(level).GetVertexChildVertex(v); } - - // Parent components: - Index GetFaceParentFace(int level, Index f) const { return GetLevel(level).GetFaceParentFace(f); } - Index GetFaceBaseFace(int level, Index f) const { return GetLevel(level).GetFaceBaseFace(f); } - - // Debugging aides: - bool ValidateTopology(int level) const { return GetLevel(level).ValidateTopology(); } - void PrintTopology(int level, bool children = true) const { GetLevel(level).PrintTopology(children); } - - - // UNDER RE-CONSIDERATION... - // - // Potentially too special-purpose to warrant public method (needs to iterate through all faces): - int GetNumHoles(int level) const; - - // Appears to be completely unused: - bool FaceIsRegular(int level, Index face) const { - ConstIndexArray fVerts = _levels[level]->getFaceVertices(face); - Vtr::Level::VTag compFaceVertTag = - _levels[level]->getFaceCompositeVTag(fVerts); - return not compFaceVertTag._xordinary; - } - - protected: // @@ -440,7 +373,7 @@ protected: // Lower level protected methods intended strictly for internal use: // friend class TopologyRefinerFactoryBase; - friend class PatchTablesFactory; + friend class PatchTableFactory; friend class EndCapGregoryBasisPatchFactory; friend class EndCapLegacyGregoryPatchFactory; friend class PtexIndices; @@ -549,7 +482,7 @@ TopologyRefiner::Interpolate(T const * src, U * dst) const { Interpolate(level, src, dst); src = dst; - dst += GetNumVertices(level); + dst += GetLevel(level).GetNumVertices(); } } @@ -777,7 +710,7 @@ TopologyRefiner::InterpolateVarying(T const * src, U * dst) const { InterpolateVarying(level, src, dst); src = dst; - dst += GetNumVertices(level); + dst += GetLevel(level).GetNumVertices(); } } diff --git a/opensubdiv/far/topologyRefinerFactory.cpp b/opensubdiv/far/topologyRefinerFactory.cpp index c4ed57c0..49a07a2a 100644 --- a/opensubdiv/far/topologyRefinerFactory.cpp +++ b/opensubdiv/far/topologyRefinerFactory.cpp @@ -317,13 +317,14 @@ bool TopologyRefinerFactory::assignComponentTags( TopologyRefiner & refiner, TopologyDescriptor const & desc) { + TopologyLevel const & refBaseLevel = refiner.GetLevel(0); if ((desc.numCreases>0) and desc.creaseVertexIndexPairs and desc.creaseWeights) { int const * vertIndexPairs = desc.creaseVertexIndexPairs; for (int edge=0; edge::assignCo int idx = desc.cornerVertexIndices[vert]; - if (idx >= 0 and idx < refiner.GetNumVertices(0)) { + if (idx >= 0 and idx < refBaseLevel.GetNumVertices()) { refiner.setBaseVertexSharpness(idx, desc.cornerWeights[vert]); } else { char msg[1024]; diff --git a/opensubdiv/far/topologyRefinerFactory.h b/opensubdiv/far/topologyRefinerFactory.h index 9f49289a..d6d0eb98 100644 --- a/opensubdiv/far/topologyRefinerFactory.h +++ b/opensubdiv/far/topologyRefinerFactory.h @@ -343,7 +343,7 @@ TopologyRefinerFactory::assignComponentTopology(TopologyRefiner& /* refine // // void TopologyRefiner::setBaseVertexNonManifold(Index vertex, bool b); // - // Also consider using TopologyRefiner::ValidateTopology() when debugging to ensure + // Also consider using TopologyLevel::ValidateTopology() when debugging to ensure // that topolology has been completely and correctly specified. // return false; diff --git a/opensubdiv/osd/clEvaluator.cpp b/opensubdiv/osd/clEvaluator.cpp index edc6fbee..4c2efcf8 100644 --- a/opensubdiv/osd/clEvaluator.cpp +++ b/opensubdiv/osd/clEvaluator.cpp @@ -30,7 +30,7 @@ #include "../osd/opencl.h" #include "../far/error.h" -#include "../far/stencilTables.h" +#include "../far/stencilTable.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { @@ -61,22 +61,22 @@ createCLBuffer(std::vector const & src, cl_context clContext) { // ---------------------------------------------------------------------------- -CLStencilTables::CLStencilTables(Far::StencilTables const *stencilTables, - cl_context clContext) { - _numStencils = stencilTables->GetNumStencils(); +CLStencilTable::CLStencilTable(Far::StencilTable const *stencilTable, + cl_context clContext) { + _numStencils = stencilTable->GetNumStencils(); if (_numStencils > 0) { - _sizes = createCLBuffer(stencilTables->GetSizes(), clContext); - _offsets = createCLBuffer(stencilTables->GetOffsets(), clContext); - _indices = createCLBuffer(stencilTables->GetControlIndices(), + _sizes = createCLBuffer(stencilTable->GetSizes(), clContext); + _offsets = createCLBuffer(stencilTable->GetOffsets(), clContext); + _indices = createCLBuffer(stencilTable->GetControlIndices(), clContext); - _weights = createCLBuffer(stencilTables->GetWeights(), clContext); + _weights = createCLBuffer(stencilTable->GetWeights(), clContext); } else { _sizes = _offsets = _indices = _weights = NULL; } } -CLStencilTables::~CLStencilTables() { +CLStencilTable::~CLStencilTable() { if (_sizes) clReleaseMemObject(_sizes); if (_offsets) clReleaseMemObject(_offsets); if (_indices) clReleaseMemObject(_indices); diff --git a/opensubdiv/osd/clEvaluator.h b/opensubdiv/osd/clEvaluator.h index b427e082..62780fe5 100644 --- a/opensubdiv/osd/clEvaluator.h +++ b/opensubdiv/osd/clEvaluator.h @@ -34,29 +34,29 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { - class StencilTables; + class StencilTable; } namespace Osd { -/// \brief OpenCL stencil tables +/// \brief OpenCL stencil table /// -/// This class is an OpenCL buffer representation of Far::StencilTables. +/// This class is an OpenCL buffer representation of Far::StencilTable. /// /// CLCompute consumes this table to apply stencils /// /// -class CLStencilTables { +class CLStencilTable { public: template - static CLStencilTables *Create(Far::StencilTables const *stencilTables, - DEVICE_CONTEXT context) { - return new CLStencilTables(stencilTables, context->GetContext()); + static CLStencilTable *Create(Far::StencilTable const *stencilTable, + DEVICE_CONTEXT context) { + return new CLStencilTable(stencilTable, context->GetContext()); } - CLStencilTables(Far::StencilTables const *stencilTables, - cl_context clContext); - ~CLStencilTables(); + CLStencilTable(Far::StencilTable const *stencilTable, + cl_context clContext); + ~CLStencilTable(); // interfaces needed for CLComputeKernel cl_mem GetSizesBuffer() const { return _sizes; } @@ -123,7 +123,7 @@ public: /// /// @param dstDesc vertex buffer descriptor for the output buffer /// - /// @param stencilTables stencil table to be applied. The table must have + /// @param stencilTable stencil table to be applied. The table must have /// OpenCL memory interfaces. /// /// @param instance cached compiled instance. Clients are supposed to diff --git a/opensubdiv/osd/cpuEvaluator.cpp b/opensubdiv/osd/cpuEvaluator.cpp index 956f94ab..e15f09bd 100644 --- a/opensubdiv/osd/cpuEvaluator.cpp +++ b/opensubdiv/osd/cpuEvaluator.cpp @@ -59,10 +59,10 @@ CpuEvaluator::EvalStencils(const float *src, VertexBufferDescriptor const &srcDesc, float *dst, VertexBufferDescriptor const &dstDesc, - float *dstDu, - VertexBufferDescriptor const &dstDuDesc, - float *dstDv, - VertexBufferDescriptor const &dstDvDesc, + float *dstDs, + VertexBufferDescriptor const &dstDsDesc, + float *dstDt, + VertexBufferDescriptor const &dstDtDesc, const int * sizes, const int * offsets, const int * indices, @@ -72,13 +72,13 @@ CpuEvaluator::EvalStencils(const float *src, int start, int end) { if (end <= start) return true; if (srcDesc.length != dstDesc.length) return false; - if (srcDesc.length != dstDuDesc.length) return false; - if (srcDesc.length != dstDvDesc.length) return false; + if (srcDesc.length != dstDsDesc.length) return false; + if (srcDesc.length != dstDtDesc.length) return false; CpuEvalStencils(src, srcDesc, dst, dstDesc, - dstDu, dstDuDesc, - dstDv, dstDvDesc, + dstDs, dstDsDesc, + dstDt, dstDtDesc, sizes, offsets, indices, weights, duWeights, dvWeights, start, end); @@ -93,19 +93,21 @@ struct BufferAdapter { void Clear() { for (int i = 0; i < _length; ++i) _p[i] = 0; } - void AddWithWeight(T const *src, float w, float wu, float wv) { - (void)wu; - (void)wv; - // TODO: derivatives. - for (int i = 0; i < _length; ++i) { - _p[i] += src[i] * w; + void AddWithWeight(T const *src, float w) { + if (_p) { + // TODO: derivatives. + for (int i = 0; i < _length; ++i) { + _p[i] += src[i] * w; + } } } const T *operator[] (int index) const { return _p + _stride * index; } BufferAdapter & operator ++() { - _p += _stride; + if (_p) { + _p += _stride; + } return *this; } @@ -115,24 +117,23 @@ struct BufferAdapter { }; /* static */ -int +bool CpuEvaluator::EvalPatches(const float *src, VertexBufferDescriptor const &srcDesc, float *dst, VertexBufferDescriptor const &dstDesc, - PatchCoordArray const &patchCoords, - Far::PatchTables const *patchTable) { + int numPatchCoords, + PatchCoord const *patchCoords, + Far::PatchTable const *patchTable) { src += srcDesc.offset; - dst += dstDesc.offset; - int count = 0; + if (dst) dst += dstDesc.offset; - // XXX: this implementaion is temporary. BufferAdapter srcT(src, srcDesc.length, srcDesc.stride); BufferAdapter dstT(dst, dstDesc.length, dstDesc.stride); float wP[20], wDs[20], wDt[20]; - for (size_t i = 0; i < patchCoords.size(); ++i) { + for (int i = 0; i < numPatchCoords; ++i) { PatchCoord const &coords = patchCoords[i]; patchTable->EvaluateBasis(coords.handle, coords.s, coords.t, wP, wDs, wDt); @@ -141,13 +142,58 @@ CpuEvaluator::EvalPatches(const float *src, dstT.Clear(); for (int j = 0; j < cvs.size(); ++j) { - dstT.AddWithWeight(srcT[cvs[j]], wP[j], wDs[j], wDt[j]); + dstT.AddWithWeight(srcT[cvs[j]], wP[j]); } - - ++count; ++dstT; } - return count; + return true; +} + +/* static */ +bool +CpuEvaluator::EvalPatches(const float *src, + VertexBufferDescriptor const &srcDesc, + float *dst, + VertexBufferDescriptor const &dstDesc, + float *dstDs, + VertexBufferDescriptor const &dstDsDesc, + float *dstDt, + VertexBufferDescriptor const &dstDtDesc, + int numPatchCoords, + PatchCoord const *patchCoords, + Far::PatchTable const *patchTable) { + src += srcDesc.offset; + if (dst) dst += dstDesc.offset; + if (dstDs) dstDs += dstDsDesc.offset; + if (dstDt) dstDt += dstDtDesc.offset; + + BufferAdapter srcT(src, srcDesc.length, srcDesc.stride); + BufferAdapter dstT(dst, dstDesc.length, dstDesc.stride); + BufferAdapter dstDsT(dstDs, dstDsDesc.length, dstDsDesc.stride); + BufferAdapter dstDtT(dstDt, dstDtDesc.length, dstDtDesc.stride); + + float wP[20], wDs[20], wDt[20]; + + for (int i = 0; i < numPatchCoords; ++i) { + PatchCoord const &coords = patchCoords[i]; + + patchTable->EvaluateBasis(coords.handle, coords.s, coords.t, wP, wDs, wDt); + + Far::ConstIndexArray cvs = patchTable->GetPatchVertices(coords.handle); + + dstT.Clear(); + dstDsT.Clear(); + dstDtT.Clear(); + for (int j = 0; j < cvs.size(); ++j) { + dstT.AddWithWeight(srcT[cvs[j]], wP[j]); + dstDsT.AddWithWeight(srcT[cvs[j]], wDs[j]); + dstDtT.AddWithWeight(srcT[cvs[j]], wDt[j]); + } + ++dstT; + ++dstDsT; + ++dstDtT; + } + return true; } diff --git a/opensubdiv/osd/cpuEvaluator.h b/opensubdiv/osd/cpuEvaluator.h index 2e05b6ab..e03be1ee 100644 --- a/opensubdiv/osd/cpuEvaluator.h +++ b/opensubdiv/osd/cpuEvaluator.h @@ -30,7 +30,7 @@ #include #include #include "../osd/vertexDescriptor.h" -#include "../far/patchTables.h" +#include "../far/patchTable.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { @@ -49,21 +49,24 @@ struct PatchCoord { /// /// @param t parametric location on the patch /// - PatchCoord(Far::PatchTables::PatchHandle handle, float s, float t) : + PatchCoord(Far::PatchTable::PatchHandle handle, float s, float t) : handle(handle), s(s), t(t) { } - Far::PatchTables::PatchHandle handle; ///< patch handle + Far::PatchTable::PatchHandle handle; ///< patch handle float s, t; ///< parametric location on patch }; -typedef std::vector PatchCoordArray; - - class CpuEvaluator { public: + /// ---------------------------------------------------------------------- + /// + /// Stencil evaluations with StencilTable + /// + /// ---------------------------------------------------------------------- + /// \brief Generic static eval stencils function. This function has a same /// signature as other device kernels have so that it can be called - /// transparently from OsdMesh template interface. + /// in the same way from OsdMesh template interface. /// /// @param srcBuffer Input primvar buffer. /// must have BindCpuBuffer() method returning a @@ -108,7 +111,28 @@ public: /*end = */ stencilTable->GetNumStencils()); } - /// stencil evaluate function. + /// \brief Static eval stencils function which takes raw CPU pointers for + /// input and output. + /// + /// @param src Input primvar pointer. An offset of srcDesc + /// will be applied internally (i.e. the pointer + /// should not include the offset) + /// + /// @param srcDesc vertex buffer descriptor for the input buffer + /// + /// @param dst Output primvar pointer. An offset of dstDesc + /// will be applied internally. + /// + /// @param dstDesc vertex buffer descriptor for the output buffer + /// + /// @param stencilTable stencil table to be applied. + /// + /// @param instance not used in the cpu kernel + /// (declared as a typed pointer to prevent + /// undesirable template resolution) + /// + /// @param deviceContext not used in the cpu kernel + /// static bool EvalStencils(const float *src, VertexBufferDescriptor const &srcDesc, float *dst, @@ -120,15 +144,52 @@ public: int start, int end); + /// \brief Generic static eval stencils function with derivatives. + /// This function has a same signature as other device kernels + /// have so that it can be called in the same way from OsdMesh + /// template interface. + /// + /// @param srcBuffer Input primvar buffer. + /// must have BindCpuBuffer() method returning a + /// const float pointer for read + /// + /// @param srcDesc vertex buffer descriptor for the input buffer + /// + /// @param dstBuffer Output primvar buffer + /// must have BindCpuBuffer() method returning a + /// float pointer for write + /// + /// @param dstDesc vertex buffer descriptor for the output buffer + /// + /// @param dstDsBuffer Output s-derivative buffer + /// must have BindCpuBuffer() method returning a + /// float pointer for write + /// + /// @param dstDsDesc vertex buffer descriptor for the output buffer + /// + /// @param dstDtBuffer Output t-derivative buffer + /// must have BindCpuBuffer() method returning a + /// float pointer for write + /// + /// @param dstDtDesc vertex buffer descriptor for the output buffer + /// + /// @param stencilTable stencil table to be applied. + /// + /// @param instance not used in the cpu kernel + /// (declared as a typed pointer to prevent + /// undesirable template resolution) + /// + /// @param deviceContext not used in the cpu kernel + /// template static bool EvalStencils(SRC_BUFFER *srcBuffer, VertexBufferDescriptor const &srcDesc, DST_BUFFER *dstBuffer, VertexBufferDescriptor const &dstDesc, - DST_BUFFER *dstDuBuffer, - VertexBufferDescriptor const &dstDuDesc, - DST_BUFFER *dstDvBuffer, - VertexBufferDescriptor const &dstDvDesc, + DST_BUFFER *dstDsBuffer, + VertexBufferDescriptor const &dstDsDesc, + DST_BUFFER *dstDtBuffer, + VertexBufferDescriptor const &dstDtDesc, STENCIL_TABLE const *stencilTable, const CpuEvaluator *evaluator = NULL, void * deviceContext = NULL) { @@ -139,10 +200,10 @@ public: srcDesc, dstBuffer->BindCpuBuffer(), dstDesc, - dstDuBuffer->BindCpuBuffer(), - dstDuDesc, - dstDvBuffer->BindCpuBuffer(), - dstDvDesc, + dstDsBuffer->BindCpuBuffer(), + dstDsDesc, + dstDtBuffer->BindCpuBuffer(), + dstDtDesc, &stencilTable->GetSizes()[0], &stencilTable->GetOffsets()[0], &stencilTable->GetControlIndices()[0], @@ -153,14 +214,46 @@ public: /*end = */ stencilTable->GetNumStencils()); } + /// \brief Static eval stencils function with derivatives, which takes + /// raw CPU pointers for input and output. + /// + /// @param src Input primvar pointer. An offset of srcDesc + /// will be applied internally (i.e. the pointer + /// should not include the offset) + /// + /// @param srcDesc vertex buffer descriptor for the input buffer + /// + /// @param dst Output primvar pointer. An offset of dstDesc + /// will be applied internally. + /// + /// @param dstDesc vertex buffer descriptor for the output buffer + /// + /// @param dstDs Output s-derivatives pointer. An offset of + /// dstDsDesc will be applied internally. + /// + /// @param dstDsDesc vertex buffer descriptor for the output buffer + /// + /// @param dstDt Output t-derivatives pointer. An offset of + /// dstDtDesc will be applied internally. + /// + /// @param dstDtDesc vertex buffer descriptor for the output buffer + /// + /// @param stencilTable stencil table to be applied. + /// + /// @param instance not used in the cpu kernel + /// (declared as a typed pointer to prevent + /// undesirable template resolution) + /// + /// @param deviceContext not used in the cpu kernel + /// static bool EvalStencils(const float *src, VertexBufferDescriptor const &srcDesc, float *dst, VertexBufferDescriptor const &dstDesc, - float *dstDu, - VertexBufferDescriptor const &dstDuDesc, - float *dstDv, - VertexBufferDescriptor const &dstDvDesc, + float *dstDs, + VertexBufferDescriptor const &dstDsDesc, + float *dstDt, + VertexBufferDescriptor const &dstDtDesc, const int * sizes, const int * offsets, const int * indices, @@ -170,11 +263,15 @@ public: int start, int end); + /// ---------------------------------------------------------------------- + /// + /// Limit evaluations with PatchTable + /// + /// ---------------------------------------------------------------------- + /// \brief Generic limit eval function. This function has a same /// signature as other device kernels have so that it can be called - /// transparently. - /// - /// XXX: This interface is still work in progress. XXX + /// in the same way. /// /// @param srcBuffer Input primvar buffer. /// must have BindCpuBuffer() method returning a @@ -188,23 +285,26 @@ public: /// /// @param dstDesc vertex buffer descriptor for the output buffer /// - /// @param patchCoord array of locations to be evaluated. + /// @param numPatchCoords number of patchCoords. + /// + /// @param patchCoords array of locations to be evaluated. /// /// @param patchTable Far::PatchTable /// - /// @param instanced not used in the cpu evaluator + /// @param instance not used in the cpu evaluator /// /// @param deviceContext not used in the cpu evaluator /// template - static int EvalPatches(SRC_BUFFER *srcBuffer, - VertexBufferDescriptor const &srcDesc, - DST_BUFFER *dstBuffer, - VertexBufferDescriptor const &dstDesc, - PatchCoordArray const &patchCoords, - Far::PatchTables const *patchTable, - CpuEvaluator const *instance, - void * deviceContext = NULL) { + static bool EvalPatches(SRC_BUFFER *srcBuffer, + VertexBufferDescriptor const &srcDesc, + DST_BUFFER *dstBuffer, + VertexBufferDescriptor const &dstDesc, + int numPatchCoords, + PatchCoord const *patchCoords, + Far::PatchTable const *patchTable, + CpuEvaluator const *instance, + void * deviceContext = NULL) { (void)instance; // unused (void)deviceContext; // unused @@ -212,17 +312,158 @@ public: srcDesc, dstBuffer->BindCpuBuffer(), dstDesc, + numPatchCoords, patchCoords, patchTable); } - /// \brief limit eval function. - static int EvalPatches(const float *src, - VertexBufferDescriptor const &srcDesc, - float *dst, - VertexBufferDescriptor const &dstDesc, - PatchCoordArray const &patchCoords, - Far::PatchTables const *patchTable); + /// \brief Generic limit eval function with derivatives. This function has + /// a same signature as other device kernels have so that it can be + /// called in the same way. + /// + /// @param srcBuffer Input primvar buffer. + /// must have BindCpuBuffer() method returning a + /// const float pointer for read + /// + /// @param srcDesc vertex buffer descriptor for the input buffer + /// + /// @param dstBuffer Output primvar buffer + /// must have BindCpuBuffer() method returning a + /// float pointer for write + /// + /// @param dstDesc vertex buffer descriptor for the output buffer + /// + /// @param dstDsBuffer Output s-derivatives buffer + /// must have BindCpuBuffer() method returning a + /// float pointer for write + /// + /// @param dstDsDesc vertex buffer descriptor for the dstDsBuffer + /// + /// @param dstDtBuffer Output t-derivatives buffer + /// must have BindCpuBuffer() method returning a + /// float pointer for write + /// + /// @param dstDtDesc vertex buffer descriptor for the dstDtBuffer + /// + /// @param numPatchCoords number of patchCoords. + /// + /// @param patchCoords array of locations to be evaluated. + /// + /// @param patchTable Far::PatchTable + /// + /// @param instance not used in the cpu evaluator + /// + /// @param deviceContext not used in the cpu evaluator + /// + template + static bool EvalPatches(SRC_BUFFER *srcBuffer, + VertexBufferDescriptor const &srcDesc, + DST_BUFFER *dstBuffer, + VertexBufferDescriptor const &dstDesc, + DST_BUFFER *dstDsBuffer, + VertexBufferDescriptor const &dstDsDesc, + DST_BUFFER *dstDtBuffer, + VertexBufferDescriptor const &dstDtDesc, + int numPatchCoords, + PatchCoord const *patchCoords, + Far::PatchTable const *patchTable, + CpuEvaluator const *instance, + void * deviceContext = NULL) { + (void)instance; // unused + (void)deviceContext; // unused + + return EvalPatches(srcBuffer->BindCpuBuffer(), + srcDesc, + dstBuffer->BindCpuBuffer(), + dstDesc, + dstDsBuffer->BindCpuBuffer(), + dstDsDesc, + dstDtBuffer->BindCpuBuffer(), + dstDtDesc, + numPatchCoords, + patchCoords, + patchTable); + } + + /// \brief Static limit eval function. It takes an array of PatchCoord + /// and evaluate limit values on given PatchTable. + /// + /// @param src Input primvar pointer. An offset of srcDesc + /// will be applied internally (i.e. the pointer + /// should not include the offset) + /// + /// @param srcDesc vertex buffer descriptor for the input buffer + /// + /// @param dst Output primvar pointer. An offset of dstDesc + /// will be applied internally. + /// + /// @param dstDesc vertex buffer descriptor for the output buffer + /// + /// @param numPatchCoords number of patchCoords. + /// + /// @param patchCoords array of locations to be evaluated. + /// + /// @param patchTable Far::PatchTable on which primvars are evaluated + /// for the patchCoords + /// + /// @param instance not used in the cpu evaluator + /// + /// @param deviceContext not used in the cpu evaluator + /// + static bool EvalPatches(const float *src, + VertexBufferDescriptor const &srcDesc, + float *dst, + VertexBufferDescriptor const &dstDesc, + int numPatchCoords, + PatchCoord const *patchCoords, + Far::PatchTable const *patchTable); + + /// \brief Static limit eval function. It takes an array of PatchCoord + /// and evaluate limit values on given PatchTable. + /// + /// @param src Input primvar pointer. An offset of srcDesc + /// will be applied internally (i.e. the pointer + /// should not include the offset) + /// + /// @param srcDesc vertex buffer descriptor for the input buffer + /// + /// @param dst Output primvar pointer. An offset of dstDesc + /// will be applied internally. + /// + /// @param dstDesc vertex buffer descriptor for the output buffer + /// + /// @param dstDs Output s-derivatives pointer. An offset of + /// dstDsDesc will be applied internally. + /// + /// @param dstDsDesc vertex buffer descriptor for the dstDs buffer + /// + /// @param dstDt Output t-derivatives pointer. An offset of + /// dstDtDesc will be applied internally. + /// + /// @param dstDtDesc vertex buffer descriptor for the dstDt buffer + /// + /// @param numPatchCoords number of patchCoords. + /// + /// @param patchCoords array of locations to be evaluated. + /// + /// @param patchTable Far::PatchTable on which primvars are evaluated + /// for the patchCoords + /// + /// @param instance not used in the cpu evaluator + /// + /// @param deviceContext not used in the cpu evaluator + /// + static bool EvalPatches(const float *src, + VertexBufferDescriptor const &srcDesc, + float *dst, + VertexBufferDescriptor const &dstDesc, + float *dstDs, + VertexBufferDescriptor const &dstDsDesc, + float *dstDt, + VertexBufferDescriptor const &dstDtDesc, + int numPatchCoords, + PatchCoord const *patchCoords, + Far::PatchTable const *patchTable); /// \brief synchronize all asynchronous computation invoked on this device. static void Synchronize(void * /*deviceContext = NULL*/) { diff --git a/opensubdiv/osd/cpuSmoothNormalContext.cpp b/opensubdiv/osd/cpuSmoothNormalContext.cpp index a14a1e0b..dc11b13f 100644 --- a/opensubdiv/osd/cpuSmoothNormalContext.cpp +++ b/opensubdiv/osd/cpuSmoothNormalContext.cpp @@ -36,14 +36,14 @@ CpuSmoothNormalContext::CpuSmoothNormalContext( Far::TopologyRefiner const & refiner, int level, bool resetMemory) : _numVertices(0), _resetMemory(resetMemory) { - int nfaces = refiner.GetNumFaces(level), + int nfaces = refiner.GetLevel(level).GetNumFaces(), nverts = nfaces * 4; _faceVerts.resize(nverts); Far::Index * dest = &_faceVerts[0]; for (int face=0; face #include -#include "../far/stencilTables.h" +#include "../far/stencilTable.h" extern "C" { void CudaEvalStencils(const float *src, @@ -69,19 +69,19 @@ createCudaBuffer(std::vector const & src) { // ---------------------------------------------------------------------------- -CudaStencilTables::CudaStencilTables(Far::StencilTables const *stencilTables) { - _numStencils = stencilTables->GetNumStencils(); +CudaStencilTable::CudaStencilTable(Far::StencilTable const *stencilTable) { + _numStencils = stencilTable->GetNumStencils(); if (_numStencils > 0) { - _sizes = createCudaBuffer(stencilTables->GetSizes()); - _offsets = createCudaBuffer(stencilTables->GetOffsets()); - _indices = createCudaBuffer(stencilTables->GetControlIndices()); - _weights = createCudaBuffer(stencilTables->GetWeights()); + _sizes = createCudaBuffer(stencilTable->GetSizes()); + _offsets = createCudaBuffer(stencilTable->GetOffsets()); + _indices = createCudaBuffer(stencilTable->GetControlIndices()); + _weights = createCudaBuffer(stencilTable->GetWeights()); } else { _sizes = _offsets = _indices = _weights = NULL; } } -CudaStencilTables::~CudaStencilTables() { +CudaStencilTable::~CudaStencilTable() { if (_sizes) cudaFree(_sizes); if (_offsets) cudaFree(_offsets); if (_indices) cudaFree(_indices); diff --git a/opensubdiv/osd/cudaEvaluator.h b/opensubdiv/osd/cudaEvaluator.h index 661c5977..ee36e0b6 100644 --- a/opensubdiv/osd/cudaEvaluator.h +++ b/opensubdiv/osd/cudaEvaluator.h @@ -34,28 +34,28 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { - class StencilTables; + class StencilTable; } namespace Osd { -/// \brief CUDA stencil tables +/// \brief CUDA stencil table /// -/// This class is a cuda buffer representation of Far::StencilTables. +/// This class is a cuda buffer representation of Far::StencilTable. /// /// CudaComputeKernel consumes this table to apply stencils /// /// -class CudaStencilTables { +class CudaStencilTable { public: - static CudaStencilTables *Create(Far::StencilTables const *stencilTables, - void *deviceContext = NULL) { + static CudaStencilTable *Create(Far::StencilTable const *stencilTable, + void *deviceContext = NULL) { (void)deviceContext; // unused - return new CudaStencilTables(stencilTables); + return new CudaStencilTable(stencilTable); } - explicit CudaStencilTables(Far::StencilTables const *stencilTables); - ~CudaStencilTables(); + explicit CudaStencilTable(Far::StencilTable const *stencilTable); + ~CudaStencilTable(); // interfaces needed for CudaCompute void *GetSizesBuffer() const { return _sizes; } @@ -92,7 +92,7 @@ public: /// /// @param dstDesc vertex buffer descriptor for the output buffer /// - /// @param stencilTables stencil table to be applied. The table must have + /// @param stencilTable stencil table to be applied. The table must have /// Cuda memory interfaces. /// /// @param instance not used in the CudaEvaluator diff --git a/opensubdiv/osd/d3d11ComputeEvaluator.cpp b/opensubdiv/osd/d3d11ComputeEvaluator.cpp index 5da28ecb..1df4c0de 100644 --- a/opensubdiv/osd/d3d11ComputeEvaluator.cpp +++ b/opensubdiv/osd/d3d11ComputeEvaluator.cpp @@ -35,7 +35,7 @@ #include #include "../far/error.h" -#include "../far/stencilTables.h" +#include "../far/stencilTable.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { @@ -112,37 +112,37 @@ static ID3D11ShaderResourceView *createSRV(ID3D11Buffer *buffer, return srv; } -D3D11StencilTables::D3D11StencilTables(Far::StencilTables const *stencilTables, - ID3D11DeviceContext *deviceContext) +D3D11StencilTable::D3D11StencilTable(Far::StencilTable const *stencilTable, + ID3D11DeviceContext *deviceContext) { ID3D11Device *device = NULL; deviceContext->GetDevice(&device); assert(device); - _numStencils = stencilTables->GetNumStencils(); + _numStencils = stencilTable->GetNumStencils(); if (_numStencils > 0) { - std::vector const &sizes = stencilTables->GetSizes(); + std::vector const &sizes = stencilTable->GetSizes(); _sizesBuffer = createBuffer(sizes, device); - _offsetsBuffer = createBuffer(stencilTables->GetOffsets(), device); - _indicesBuffer = createBuffer(stencilTables->GetControlIndices(), device); - _weightsBuffer = createBuffer(stencilTables->GetWeights(), device); + _offsetsBuffer = createBuffer(stencilTable->GetOffsets(), device); + _indicesBuffer = createBuffer(stencilTable->GetControlIndices(), device); + _weightsBuffer = createBuffer(stencilTable->GetWeights(), device); _sizes = createSRV(_sizesBuffer, DXGI_FORMAT_R32_SINT, device, - stencilTables->GetSizes().size()); + stencilTable->GetSizes().size()); _offsets = createSRV(_offsetsBuffer, DXGI_FORMAT_R32_SINT, device, - stencilTables->GetOffsets().size()); + stencilTable->GetOffsets().size()); _indices = createSRV(_indicesBuffer, DXGI_FORMAT_R32_SINT, device, - stencilTables->GetControlIndices().size()); + stencilTable->GetControlIndices().size()); _weights= createSRV(_weightsBuffer, DXGI_FORMAT_R32_FLOAT, device, - stencilTables->GetWeights().size()); + stencilTable->GetWeights().size()); } else { _sizes = _offsets = _indices = _weights = NULL; _sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL; } } -D3D11StencilTables::~D3D11StencilTables() { +D3D11StencilTable::~D3D11StencilTable() { SAFE_RELEASE(_sizes); SAFE_RELEASE(_sizesBuffer); SAFE_RELEASE(_offsets); @@ -341,7 +341,7 @@ D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV, ID3D11ShaderResourceView *SRViews[] = { sizesSRV, offsetsSRV, indicesSRV, weightsSRV }; - // bind source vertex and stencil tables + // bind source vertex and stencil table deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4 if (srcUAV == dstUAV) { @@ -356,7 +356,7 @@ D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV, deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1); } - // unbind stencil tables and vertexbuffers + // unbind stencil table and vertexbuffers SRViews[0] = SRViews[1] = SRViews[2] = SRViews[3] = NULL; deviceContext->CSSetShaderResources(1, 4, SRViews); diff --git a/opensubdiv/osd/d3d11ComputeEvaluator.h b/opensubdiv/osd/d3d11ComputeEvaluator.h index fd034db5..9c9ad430 100644 --- a/opensubdiv/osd/d3d11ComputeEvaluator.h +++ b/opensubdiv/osd/d3d11ComputeEvaluator.h @@ -41,35 +41,35 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { - class StencilTables; + class StencilTable; } namespace Osd { -/// \brief D3D11 stencil tables +/// \brief D3D11 stencil table /// /// This class is a D3D11 Shader Resource View representation of -/// Far::StencilTables. +/// Far::StencilTable. /// /// D3D11ComputeEvaluator consumes this table to apply stencils /// -class D3D11StencilTables { +class D3D11StencilTable { public: template - static D3D11StencilTables *Create(Far::StencilTables const *stencilTables, + static D3D11StencilTable *Create(Far::StencilTable const *stencilTable, DEVICE_CONTEXT context) { - return new D3D11StencilTables(stencilTables, context->GetDeviceContext()); + return new D3D11StencilTable(stencilTable, context->GetDeviceContext()); } - static D3D11StencilTables *Create(Far::StencilTables const *stencilTables, + static D3D11StencilTable *Create(Far::StencilTable const *stencilTable, ID3D11DeviceContext *deviceContext) { - return new D3D11StencilTables(stencilTables, deviceContext); + return new D3D11StencilTable(stencilTable, deviceContext); } - D3D11StencilTables(Far::StencilTables const *stencilTables, + D3D11StencilTable(Far::StencilTable const *stencilTable, ID3D11DeviceContext *deviceContext); - ~D3D11StencilTables(); + ~D3D11StencilTable(); // interfaces needed for D3D11ComputeEvaluator ID3D11ShaderResourceView *GetSizesSRV() const { return _sizes; } @@ -122,7 +122,7 @@ public: /// /// @param dstDesc vertex buffer descriptor for the output buffer /// - /// @param stencilTables stencil table to be applied. The table must have + /// @param stencilTable stencil table to be applied. The table must have /// SSBO interfaces. /// /// @param instance cached compiled instance. Clients are supposed to diff --git a/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp b/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp index 06b21fc6..8064edb1 100644 --- a/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp +++ b/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp @@ -46,7 +46,7 @@ D3D11LegacyGregoryPatchTable::~D3D11LegacyGregoryPatchTable() { } D3D11LegacyGregoryPatchTable * -D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables, +D3D11LegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable, ID3D11DeviceContext *pd3d11DeviceContext) { ID3D11Device *pd3d11Device = NULL; pd3d11DeviceContext->GetDevice(&pd3d11Device); @@ -54,10 +54,10 @@ D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables, D3D11LegacyGregoryPatchTable *result = new D3D11LegacyGregoryPatchTable(); - Far::PatchTables::VertexValenceTable const & - valenceTable = farPatchTables->GetVertexValenceTable(); - Far::PatchTables::QuadOffsetsTable const & - quadOffsetsTable = farPatchTables->GetQuadOffsetsTable(); + Far::PatchTable::VertexValenceTable const & + valenceTable = farPatchTable->GetVertexValenceTable(); + Far::PatchTable::QuadOffsetsTable const & + quadOffsetsTable = farPatchTable->GetQuadOffsetsTable(); if (not valenceTable.empty()) { D3D11_BUFFER_DESC bd; @@ -126,11 +126,11 @@ D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables, result->_quadOffsetsBase[1] = 0; // scan patchtable to find quadOffsetsBase. - for (int i = 0; i < farPatchTables->GetNumPatchArrays(); ++i) { + for (int i = 0; i < farPatchTable->GetNumPatchArrays(); ++i) { // GREGORY_BOUNDARY's quadoffsets come after GREGORY's. - if (farPatchTables->GetPatchArrayDescriptor(i) == + if (farPatchTable->GetPatchArrayDescriptor(i) == Far::PatchDescriptor::GREGORY) { - result->_quadOffsetsBase[1] = farPatchTables->GetNumPatches(i) * 4; + result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4; break; } } diff --git a/opensubdiv/osd/d3d11LegacyGregoryPatchTable.h b/opensubdiv/osd/d3d11LegacyGregoryPatchTable.h index fdd16992..bdf731ed 100644 --- a/opensubdiv/osd/d3d11LegacyGregoryPatchTable.h +++ b/opensubdiv/osd/d3d11LegacyGregoryPatchTable.h @@ -27,7 +27,7 @@ #include "../version.h" -#include "../far/patchTables.h" +#include "../far/patchTable.h" #include "../osd/nonCopyable.h" struct ID3D11Buffer; @@ -47,12 +47,12 @@ public: template static D3D11LegacyGregoryPatchTable *Create( - Far::PatchTables const *farPatchTables, DEVICE_CONTEXT context) { - return Create(farPatchTables, context->GetDeviceContext()); + Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context) { + return Create(farPatchTable, context->GetDeviceContext()); } static D3D11LegacyGregoryPatchTable *Create( - Far::PatchTables const *farPatchTables, + Far::PatchTable const *farPatchTable, ID3D11DeviceContext *deviceContext); void UpdateVertexBuffer(ID3D11Buffer *vbo, diff --git a/opensubdiv/osd/d3d11PatchTable.cpp b/opensubdiv/osd/d3d11PatchTable.cpp index cb886668..8b09af1f 100644 --- a/opensubdiv/osd/d3d11PatchTable.cpp +++ b/opensubdiv/osd/d3d11PatchTable.cpp @@ -25,7 +25,7 @@ #include "../osd/d3d11PatchTable.h" #include -#include "../far/patchTables.h" +#include "../far/patchTable.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { @@ -43,17 +43,17 @@ D3D11PatchTable::~D3D11PatchTable() { } D3D11PatchTable * -D3D11PatchTable::Create(Far::PatchTables const *farPatchTables, +D3D11PatchTable::Create(Far::PatchTable const *farPatchTable, ID3D11DeviceContext *pd3d11DeviceContext) { D3D11PatchTable *instance = new D3D11PatchTable(); - if (instance->allocate(farPatchTables, pd3d11DeviceContext)) + if (instance->allocate(farPatchTable, pd3d11DeviceContext)) return instance; delete instance; return 0; } bool -D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables, +D3D11PatchTable::allocate(Far::PatchTable const *farPatchTable, ID3D11DeviceContext *pd3d11DeviceContext) { ID3D11Device *pd3d11Device = NULL; pd3d11DeviceContext->GetDevice(&pd3d11Device); @@ -63,18 +63,18 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables, std::vector ppBuffer; // needs reserve? - int nPatchArrays = farPatchTables->GetNumPatchArrays(); + int nPatchArrays = farPatchTable->GetNumPatchArrays(); // for each patchArray for (int j = 0; j < nPatchArrays; ++j) { - PatchArray patchArray(farPatchTables->GetPatchArrayDescriptor(j), - farPatchTables->GetNumPatches(j), + PatchArray patchArray(farPatchTable->GetPatchArrayDescriptor(j), + farPatchTable->GetNumPatches(j), (int)buffer.size(), (int)ppBuffer.size()/3); _patchArrays.push_back(patchArray); // indices - Far::ConstIndexArray indices = farPatchTables->GetPatchArrayVertices(j); + Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j); for (int k = 0; k < indices.size(); ++k) { buffer.push_back(indices[k]); } @@ -84,7 +84,7 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables, // XXX: we need sharpness interface for patcharray or put sharpness // into patchParam. Far::ConstPatchParamArray patchParams = - farPatchTables->GetPatchParams(j); + farPatchTable->GetPatchParams(j); for (int k = 0; k < patchParams.size(); ++k) { float sharpness = 0.0; ppBuffer.push_back(patchParams[k].faceIndex); @@ -93,21 +93,21 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables, } #else // XXX: workaround. GetPatchParamTable() will be deprecated though. - Far::PatchParamTable const & patchParamTables = - farPatchTables->GetPatchParamTable(); + Far::PatchParamTable const & patchParamTable = + farPatchTable->GetPatchParamTable(); std::vector const &sharpnessIndexTable = - farPatchTables->GetSharpnessIndexTable(); - int numPatches = farPatchTables->GetNumPatches(j); + farPatchTable->GetSharpnessIndexTable(); + int numPatches = farPatchTable->GetNumPatches(j); for (int k = 0; k < numPatches; ++k) { float sharpness = 0.0; int patchIndex = (int)ppBuffer.size()/3; if (patchIndex < (int)sharpnessIndexTable.size()) { int sharpnessIndex = sharpnessIndexTable[patchIndex]; if (sharpnessIndex >= 0) - sharpness = farPatchTables->GetSharpnessValues()[sharpnessIndex]; + sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex]; } - ppBuffer.push_back(patchParamTables[patchIndex].faceIndex); - ppBuffer.push_back(patchParamTables[patchIndex].bitField.field); + ppBuffer.push_back(patchParamTable[patchIndex].faceIndex); + ppBuffer.push_back(patchParamTable[patchIndex].bitField.field); ppBuffer.push_back(*((unsigned int *)&sharpness)); } #endif diff --git a/opensubdiv/osd/d3d11PatchTable.h b/opensubdiv/osd/d3d11PatchTable.h index 604f7404..5fed93b7 100644 --- a/opensubdiv/osd/d3d11PatchTable.h +++ b/opensubdiv/osd/d3d11PatchTable.h @@ -40,7 +40,7 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far{ - class PatchTables; + class PatchTable; }; namespace Osd { @@ -80,12 +80,12 @@ public: ~D3D11PatchTable(); template - static D3D11PatchTable *Create(Far::PatchTables const *farPatchTables, + static D3D11PatchTable *Create(Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context) { - return Create(farPatchTables, context->GetDeviceContext()); + return Create(farPatchTable, context->GetDeviceContext()); } - static D3D11PatchTable *Create(Far::PatchTables const *farPatchTables, + static D3D11PatchTable *Create(Far::PatchTable const *farPatchTable, ID3D11DeviceContext *deviceContext); PatchArrayVector const &GetPatchArrays() const { @@ -103,8 +103,8 @@ public: } protected: - // allocate buffers from patchTables - bool allocate(Far::PatchTables const *farPatchTables, + // allocate buffers from patchTable + bool allocate(Far::PatchTable const *farPatchTable, ID3D11DeviceContext *deviceContext); PatchArrayVector _patchArrays; diff --git a/opensubdiv/osd/glComputeEvaluator.cpp b/opensubdiv/osd/glComputeEvaluator.cpp index 387c84fb..a43bd99b 100644 --- a/opensubdiv/osd/glComputeEvaluator.cpp +++ b/opensubdiv/osd/glComputeEvaluator.cpp @@ -30,7 +30,7 @@ #include #include "../far/error.h" -#include "../far/stencilTables.h" +#include "../far/stencilTable.h" namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { @@ -65,20 +65,20 @@ createSSBO(std::vector const & src) { return devicePtr; } -GLStencilTablesSSBO::GLStencilTablesSSBO( - Far::StencilTables const *stencilTables) { - _numStencils = stencilTables->GetNumStencils(); +GLStencilTableSSBO::GLStencilTableSSBO( + Far::StencilTable const *stencilTable) { + _numStencils = stencilTable->GetNumStencils(); if (_numStencils > 0) { - _sizes = createSSBO(stencilTables->GetSizes()); - _offsets = createSSBO(stencilTables->GetOffsets()); - _indices = createSSBO(stencilTables->GetControlIndices()); - _weights = createSSBO(stencilTables->GetWeights()); + _sizes = createSSBO(stencilTable->GetSizes()); + _offsets = createSSBO(stencilTable->GetOffsets()); + _indices = createSSBO(stencilTable->GetControlIndices()); + _weights = createSSBO(stencilTable->GetWeights()); } else { _sizes = _offsets = _indices = _weights = 0; } } -GLStencilTablesSSBO::~GLStencilTablesSSBO() { +GLStencilTableSSBO::~GLStencilTableSSBO() { if (_sizes) glDeleteBuffers(1, &_sizes); if (_offsets) glDeleteBuffers(1, &_offsets); if (_weights) glDeleteBuffers(1, &_weights); diff --git a/opensubdiv/osd/glComputeEvaluator.h b/opensubdiv/osd/glComputeEvaluator.h index 5fb89bf8..1e469f6f 100644 --- a/opensubdiv/osd/glComputeEvaluator.h +++ b/opensubdiv/osd/glComputeEvaluator.h @@ -34,27 +34,27 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { - class StencilTables; + class StencilTable; } namespace Osd { -/// \brief GL stencil tables (Shader Storage buffer) +/// \brief GL stencil table (Shader Storage buffer) /// -/// This class is a GLSL SSBO representation of Far::StencilTables. +/// This class is a GLSL SSBO representation of Far::StencilTable. /// /// GLSLComputeKernel consumes this table to apply stencils /// -class GLStencilTablesSSBO { +class GLStencilTableSSBO { public: - static GLStencilTablesSSBO *Create(Far::StencilTables const *stencilTables, + static GLStencilTableSSBO *Create(Far::StencilTable const *stencilTable, void *deviceContext = NULL) { (void)deviceContext; // unused - return new GLStencilTablesSSBO(stencilTables); + return new GLStencilTableSSBO(stencilTable); } - explicit GLStencilTablesSSBO(Far::StencilTables const *stencilTables); - ~GLStencilTablesSSBO(); + explicit GLStencilTableSSBO(Far::StencilTable const *stencilTable); + ~GLStencilTableSSBO(); // interfaces needed for GLSLComputeKernel GLuint GetSizesBuffer() const { return _sizes; } @@ -190,7 +190,7 @@ public: private: GLuint _program; - GLuint _uniformSizes, // stencil tables + GLuint _uniformSizes, // stencil table _uniformOffsets, _uniformIndices, _uniformWeights, diff --git a/opensubdiv/osd/glLegacyGregoryPatchTable.cpp b/opensubdiv/osd/glLegacyGregoryPatchTable.cpp index 6e139fa3..0172fcba 100644 --- a/opensubdiv/osd/glLegacyGregoryPatchTable.cpp +++ b/opensubdiv/osd/glLegacyGregoryPatchTable.cpp @@ -45,17 +45,17 @@ GLLegacyGregoryPatchTable::~GLLegacyGregoryPatchTable() { } GLLegacyGregoryPatchTable * -GLLegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables) { +GLLegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable) { GLLegacyGregoryPatchTable *result = new GLLegacyGregoryPatchTable(); glGenTextures(1, &result->_vertexTextureBuffer); glGenTextures(1, &result->_vertexValenceTextureBuffer); glGenTextures(1, &result->_quadOffsetsTextureBuffer); - Far::PatchTables::VertexValenceTable const & - valenceTable = farPatchTables->GetVertexValenceTable(); - Far::PatchTables::QuadOffsetsTable const & - quadOffsetsTable = farPatchTables->GetQuadOffsetsTable(); + Far::PatchTable::VertexValenceTable const & + valenceTable = farPatchTable->GetVertexValenceTable(); + Far::PatchTable::QuadOffsetsTable const & + quadOffsetsTable = farPatchTable->GetQuadOffsetsTable(); GLuint buffers[2]; glGenBuffers(2, buffers); @@ -82,11 +82,11 @@ GLLegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables) { result->_quadOffsetsBase[0] = 0; result->_quadOffsetsBase[1] = 0; // scan patchtable to find quadOffsetsBase. - for (int i = 0; i < farPatchTables->GetNumPatchArrays(); ++i) { + for (int i = 0; i < farPatchTable->GetNumPatchArrays(); ++i) { // GREGORY_BOUNDARY's quadoffsets come after GREGORY's. - if (farPatchTables->GetPatchArrayDescriptor(i) == + if (farPatchTable->GetPatchArrayDescriptor(i) == Far::PatchDescriptor::GREGORY) { - result->_quadOffsetsBase[1] = farPatchTables->GetNumPatches(i) * 4; + result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4; break; } } diff --git a/opensubdiv/osd/glLegacyGregoryPatchTable.h b/opensubdiv/osd/glLegacyGregoryPatchTable.h index 221f6667..680bfaf4 100644 --- a/opensubdiv/osd/glLegacyGregoryPatchTable.h +++ b/opensubdiv/osd/glLegacyGregoryPatchTable.h @@ -27,7 +27,7 @@ #include "../version.h" -#include "../far/patchTables.h" +#include "../far/patchTable.h" #include "../osd/nonCopyable.h" #include "../osd/opengl.h" @@ -41,7 +41,7 @@ class GLLegacyGregoryPatchTable public: ~GLLegacyGregoryPatchTable(); - static GLLegacyGregoryPatchTable *Create(Far::PatchTables const *patchTable); + static GLLegacyGregoryPatchTable *Create(Far::PatchTable const *patchTable); void UpdateVertexBuffer(GLuint vbo); diff --git a/opensubdiv/osd/glPatchTable.cpp b/opensubdiv/osd/glPatchTable.cpp index 27f12ce2..986133d3 100644 --- a/opensubdiv/osd/glPatchTable.cpp +++ b/opensubdiv/osd/glPatchTable.cpp @@ -24,7 +24,7 @@ #include "../osd/glPatchTable.h" -#include "../far/patchTables.h" +#include "../far/patchTable.h" #include "../osd/opengl.h" namespace OpenSubdiv { @@ -42,16 +42,16 @@ GLPatchTable::~GLPatchTable() { } GLPatchTable * -GLPatchTable::Create(Far::PatchTables const *farPatchTables, +GLPatchTable::Create(Far::PatchTable const *farPatchTable, void * /*deviceContext*/) { GLPatchTable *instance = new GLPatchTable(); - if (instance->allocate(farPatchTables)) return instance; + if (instance->allocate(farPatchTable)) return instance; delete instance; return 0; } bool -GLPatchTable::allocate(Far::PatchTables const *farPatchTables) { +GLPatchTable::allocate(Far::PatchTable const *farPatchTable) { glGenBuffers(1, &_indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); @@ -60,18 +60,18 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) { // needs reserve? - int nPatchArrays = farPatchTables->GetNumPatchArrays(); + int nPatchArrays = farPatchTable->GetNumPatchArrays(); // for each patchArray for (int j = 0; j < nPatchArrays; ++j) { - PatchArray patchArray(farPatchTables->GetPatchArrayDescriptor(j), - farPatchTables->GetNumPatches(j), + PatchArray patchArray(farPatchTable->GetPatchArrayDescriptor(j), + farPatchTable->GetNumPatches(j), (int)buffer.size(), (int)ppBuffer.size()/3); _patchArrays.push_back(patchArray); // indices - Far::ConstIndexArray indices = farPatchTables->GetPatchArrayVertices(j); + Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j); for (int k = 0; k < indices.size(); ++k) { buffer.push_back(indices[k]); } @@ -81,7 +81,7 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) { // XXX: we need sharpness interface for patcharray or put sharpness // into patchParam. Far::ConstPatchParamArray patchParams = - farPatchTables->GetPatchParams(j); + farPatchTable->GetPatchParams(j); for (int k = 0; k < patchParams.size(); ++k) { float sharpness = 0.0; ppBuffer.push_back(patchParams[k].faceIndex); @@ -90,21 +90,21 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) { } #else // XXX: workaround. GetPatchParamTable() will be deprecated though. - Far::PatchParamTable const & patchParamTables = - farPatchTables->GetPatchParamTable(); + Far::PatchParamTable const & patchParamTable = + farPatchTable->GetPatchParamTable(); std::vector const &sharpnessIndexTable = - farPatchTables->GetSharpnessIndexTable(); - int numPatches = farPatchTables->GetNumPatches(j); + farPatchTable->GetSharpnessIndexTable(); + int numPatches = farPatchTable->GetNumPatches(j); for (int k = 0; k < numPatches; ++k) { float sharpness = 0.0; int patchIndex = (int)ppBuffer.size()/3; if (patchIndex < (int)sharpnessIndexTable.size()) { int sharpnessIndex = sharpnessIndexTable[patchIndex]; if (sharpnessIndex >= 0) - sharpness = farPatchTables->GetSharpnessValues()[sharpnessIndex]; + sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex]; } - ppBuffer.push_back(patchParamTables[patchIndex].faceIndex); - ppBuffer.push_back(patchParamTables[patchIndex].bitField.field); + ppBuffer.push_back(patchParamTable[patchIndex].faceIndex); + ppBuffer.push_back(patchParamTable[patchIndex].bitField.field); ppBuffer.push_back(*((unsigned int *)&sharpness)); } #endif diff --git a/opensubdiv/osd/glPatchTable.h b/opensubdiv/osd/glPatchTable.h index 43656ca8..4fbf1b0b 100644 --- a/opensubdiv/osd/glPatchTable.h +++ b/opensubdiv/osd/glPatchTable.h @@ -36,7 +36,7 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far{ - class PatchTables; + class PatchTable; }; namespace Osd { @@ -75,7 +75,7 @@ public: GLPatchTable(); ~GLPatchTable(); - static GLPatchTable *Create(Far::PatchTables const *farPatchTables, + static GLPatchTable *Create(Far::PatchTable const *farPatchTable, void *deviceContext = NULL); PatchArrayVector const &GetPatchArrays() const { @@ -93,8 +93,8 @@ public: } protected: - // allocate buffers from patchTables - bool allocate(Far::PatchTables const *farPatchTables); + // allocate buffers from patchTable + bool allocate(Far::PatchTable const *farPatchTable); PatchArrayVector _patchArrays; GLuint _indexBuffer; diff --git a/opensubdiv/osd/glXFBEvaluator.cpp b/opensubdiv/osd/glXFBEvaluator.cpp index 7da8bad3..807a7ec6 100644 --- a/opensubdiv/osd/glXFBEvaluator.cpp +++ b/opensubdiv/osd/glXFBEvaluator.cpp @@ -30,7 +30,7 @@ #include #include "../far/error.h" -#include "../far/stencilTables.h" +#include "../far/stencilTable.h" #if _MSC_VER #define snprintf _snprintf @@ -82,23 +82,23 @@ createGLTextureBuffer(std::vector const & src, GLenum type) { return devicePtr; } -GLStencilTablesTBO::GLStencilTablesTBO( - Far::StencilTables const *stencilTables) { +GLStencilTableTBO::GLStencilTableTBO( + Far::StencilTable const *stencilTable) { - _numStencils = stencilTables->GetNumStencils(); + _numStencils = stencilTable->GetNumStencils(); if (_numStencils > 0) { - _sizes = createGLTextureBuffer(stencilTables->GetSizes(), GL_R32UI); + _sizes = createGLTextureBuffer(stencilTable->GetSizes(), GL_R32UI); _offsets = createGLTextureBuffer( - stencilTables->GetOffsets(), GL_R32I); + stencilTable->GetOffsets(), GL_R32I); _indices = createGLTextureBuffer( - stencilTables->GetControlIndices(), GL_R32I); - _weights = createGLTextureBuffer(stencilTables->GetWeights(), GL_R32F); + stencilTable->GetControlIndices(), GL_R32I); + _weights = createGLTextureBuffer(stencilTable->GetWeights(), GL_R32F); } else { _sizes = _offsets = _indices = _weights = 0; } } -GLStencilTablesTBO::~GLStencilTablesTBO() { +GLStencilTableTBO::~GLStencilTableTBO() { if (_sizes) glDeleteTextures(1, &_sizes); if (_offsets) glDeleteTextures(1, &_offsets); if (_weights) glDeleteTextures(1, &_weights); @@ -277,7 +277,7 @@ GLXFBEvaluator::EvalStencils(GLuint srcBuffer, bindTexture(_uniformSrcBufferTexture, _srcBufferTexture, 0); - // bind stencil tables textures. + // bind stencil table textures. bindTexture(_uniformSizesTexture, sizesTexture, 1); bindTexture(_uniformOffsetsTexture, offsetsTexture, 2); bindTexture(_uniformIndicesTexture, indicesTexture, 3); diff --git a/opensubdiv/osd/glXFBEvaluator.h b/opensubdiv/osd/glXFBEvaluator.h index 205f229b..65881670 100644 --- a/opensubdiv/osd/glXFBEvaluator.h +++ b/opensubdiv/osd/glXFBEvaluator.h @@ -34,28 +34,28 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { - class StencilTables; + class StencilTable; } namespace Osd { -/// \brief GL TextureBuffer stencil tables +/// \brief GL TextureBuffer stencil table /// -/// This class is a GL Texture Buffer representation of Far::StencilTables. +/// This class is a GL Texture Buffer representation of Far::StencilTable. /// /// GLSLTransformFeedback consumes this table to apply stencils /// /// -class GLStencilTablesTBO { +class GLStencilTableTBO { public: - static GLStencilTablesTBO *Create( - Far::StencilTables const *stencilTables, void *deviceContext = NULL) { + static GLStencilTableTBO *Create( + Far::StencilTable const *stencilTable, void *deviceContext = NULL) { (void)deviceContext; // unused - return new GLStencilTablesTBO(stencilTables); + return new GLStencilTableTBO(stencilTable); } - explicit GLStencilTablesTBO(Far::StencilTables const *stencilTables); - ~GLStencilTablesTBO(); + explicit GLStencilTableTBO(Far::StencilTable const *stencilTable); + ~GLStencilTableTBO(); // interfaces needed for GLSLTransformFeedbackKernel GLuint GetSizesTexture() const { return _sizes; } diff --git a/opensubdiv/osd/mesh.h b/opensubdiv/osd/mesh.h index 107b1f98..00646512 100644 --- a/opensubdiv/osd/mesh.h +++ b/opensubdiv/osd/mesh.h @@ -33,9 +33,9 @@ #include #include "../far/topologyRefiner.h" -#include "../far/patchTablesFactory.h" -#include "../far/stencilTables.h" -#include "../far/stencilTablesFactory.h" +#include "../far/patchTableFactory.h" +#include "../far/stencilTable.h" +#include "../far/stencilTableFactory.h" #include "../osd/vertexDescriptor.h" @@ -87,7 +87,7 @@ public: virtual PatchTable * GetPatchTable() const = 0; - virtual Far::PatchTables const *GetFarPatchTables() const = 0; + virtual Far::PatchTable const *GetFarPatchTable() const = 0; virtual VertexBufferBinding BindVertexBuffer() = 0; @@ -114,32 +114,32 @@ protected: // --------------------------------------------------------------------------- -template -STENCIL_TABLES const * -convertToCompatibleStencilTables( - Far::StencilTables const *table, DEVICE_CONTEXT *context) { +template +STENCIL_TABLE const * +convertToCompatibleStencilTable( + Far::StencilTable const *table, DEVICE_CONTEXT *context) { if (not table) return NULL; - return STENCIL_TABLES::Create(table, context); + return STENCIL_TABLE::Create(table, context); } template <> -Far::StencilTables const * -convertToCompatibleStencilTables( - Far::StencilTables const *table, void * /*context*/) { +Far::StencilTable const * +convertToCompatibleStencilTable( + Far::StencilTable const *table, void * /*context*/) { // no need for conversion // XXX: We don't want to even copy. if (not table) return NULL; - return new Far::StencilTables(*table); + return new Far::StencilTable(*table); } template <> -Far::StencilTables const * -convertToCompatibleStencilTables( - Far::StencilTables const *table, ID3D11DeviceContext * /*context*/) { +Far::StencilTable const * +convertToCompatibleStencilTable( + Far::StencilTable const *table, ID3D11DeviceContext * /*context*/) { // no need for conversion // XXX: We don't want to even copy. if (not table) return NULL; - return new Far::StencilTables(*table); + return new Far::StencilTable(*table); } // --------------------------------------------------------------------------- @@ -231,7 +231,7 @@ static EVALUATOR *GetEvaluator( // --------------------------------------------------------------------------- template @@ -239,7 +239,7 @@ class Mesh : public MeshInterface { public: typedef VERTEX_BUFFER VertexBuffer; typedef EVALUATOR Evaluator; - typedef STENCIL_TABLES StencilTables; + typedef STENCIL_TABLE StencilTable; typedef PATCH_TABLE PatchTable; typedef DEVICE_CONTEXT DeviceContext; typedef EvaluatorCacheT EvaluatorCache; @@ -254,13 +254,13 @@ public: DeviceContext * deviceContext = NULL) : _refiner(refiner), - _farPatchTables(NULL), + _farPatchTable(NULL), _numVertices(0), _maxValence(0), _vertexBuffer(NULL), _varyingBuffer(NULL), - _vertexStencilTables(NULL), - _varyingStencilTables(NULL), + _vertexStencilTable(NULL), + _varyingStencilTable(NULL), _evaluatorCache(evaluatorCache), _patchTable(NULL), _deviceContext(deviceContext) { @@ -302,11 +302,11 @@ public: virtual ~Mesh() { delete _refiner; - delete _farPatchTables; + delete _farPatchTable; delete _vertexBuffer; delete _varyingBuffer; - delete _vertexStencilTables; - delete _varyingStencilTables; + delete _vertexStencilTable; + delete _varyingStencilTable; delete _patchTable; // deviceContext and evaluatorCache are not owned by this class. } @@ -325,7 +325,7 @@ public: virtual void Refine() { - int numControlVertices = _refiner->GetNumVertices(0); + int numControlVertices = _refiner->GetLevel(0).GetNumVertices(); VertexBufferDescriptor srcDesc = _vertexDesc; VertexBufferDescriptor dstDesc(srcDesc); @@ -339,7 +339,7 @@ public: Evaluator::EvalStencils(_vertexBuffer, srcDesc, _vertexBuffer, dstDesc, - _vertexStencilTables, + _vertexStencilTable, instance, _deviceContext); if (_varyingDesc.length > 0) { @@ -354,13 +354,13 @@ public: // non-interleaved Evaluator::EvalStencils(_varyingBuffer, srcDesc, _varyingBuffer, dstDesc, - _varyingStencilTables, + _varyingStencilTable, instance, _deviceContext); } else { // interleaved Evaluator::EvalStencils(_vertexBuffer, srcDesc, _vertexBuffer, dstDesc, - _varyingStencilTables, + _varyingStencilTable, instance, _deviceContext); } } @@ -374,8 +374,8 @@ public: return _patchTable; } - virtual Far::PatchTables const *GetFarPatchTables() const { - return _farPatchTables; + virtual Far::PatchTable const *GetFarPatchTable() const { + return _farPatchTable; } virtual int GetNumVertices() const { return _numVertices; } @@ -408,85 +408,85 @@ private: int level, MeshBitset bits) { assert(_refiner); - Far::StencilTablesFactory::Options options; + Far::StencilTableFactory::Options options; options.generateOffsets = true; options.generateIntermediateLevels = _refiner->IsUniform() ? false : true; - Far::StencilTables const * vertexStencils = NULL; - Far::StencilTables const * varyingStencils = NULL; + Far::StencilTable const * vertexStencils = NULL; + Far::StencilTable const * varyingStencils = NULL; if (numVertexElements>0) { - vertexStencils = Far::StencilTablesFactory::Create(*_refiner, - options); + vertexStencils = Far::StencilTableFactory::Create(*_refiner, + options); } if (numVaryingElements>0) { options.interpolationMode = - Far::StencilTablesFactory::INTERPOLATE_VARYING; + Far::StencilTableFactory::INTERPOLATE_VARYING; - varyingStencils = Far::StencilTablesFactory::Create(*_refiner, - options); + varyingStencils = Far::StencilTableFactory::Create(*_refiner, + options); } - Far::PatchTablesFactory::Options poptions(level); + Far::PatchTableFactory::Options poptions(level); poptions.generateFVarTables = bits.test(MeshFVarData); poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch); if (bits.test(MeshEndCapBSplineBasis)) { poptions.SetEndCapType( - Far::PatchTablesFactory::Options::ENDCAP_BSPLINE_BASIS); + Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS); } else if (bits.test(MeshEndCapGregoryBasis)) { poptions.SetEndCapType( - Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS); + Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS); // points on gregory basis endcap boundary can be shared among // adjacent patches to save some stencils. poptions.shareEndCapPatchPoints = true; } else if (bits.test(MeshEndCapLegacyGregory)) { poptions.SetEndCapType( - Far::PatchTablesFactory::Options::ENDCAP_LEGACY_GREGORY); + Far::PatchTableFactory::Options::ENDCAP_LEGACY_GREGORY); } - _farPatchTables = Far::PatchTablesFactory::Create(*_refiner, poptions); + _farPatchTable = Far::PatchTableFactory::Create(*_refiner, poptions); // if there's endcap stencils, merge it into regular stencils. - if (_farPatchTables->GetEndCapVertexStencilTables()) { + if (_farPatchTable->GetEndCapVertexStencilTable()) { // append stencils - if (Far::StencilTables const *vertexStencilsWithEndCap = - Far::StencilTablesFactory::AppendEndCapStencilTables( + if (Far::StencilTable const *vertexStencilsWithEndCap = + Far::StencilTableFactory::AppendEndCapStencilTable( *_refiner, vertexStencils, - _farPatchTables->GetEndCapVertexStencilTables())) { + _farPatchTable->GetEndCapVertexStencilTable())) { delete vertexStencils; vertexStencils = vertexStencilsWithEndCap; } if (varyingStencils) { - if (Far::StencilTables const *varyingStencilsWithEndCap = - Far::StencilTablesFactory::AppendEndCapStencilTables( + if (Far::StencilTable const *varyingStencilsWithEndCap = + Far::StencilTableFactory::AppendEndCapStencilTable( *_refiner, varyingStencils, - _farPatchTables->GetEndCapVaryingStencilTables())) { + _farPatchTable->GetEndCapVaryingStencilTable())) { delete varyingStencils; varyingStencils = varyingStencilsWithEndCap; } } } - _maxValence = _farPatchTables->GetMaxValence(); - _patchTable = PatchTable::Create(_farPatchTables, _deviceContext); + _maxValence = _farPatchTable->GetMaxValence(); + _patchTable = PatchTable::Create(_farPatchTable, _deviceContext); // numvertices = coarse verts + refined verts + gregory basis verts _numVertices = vertexStencils->GetNumControlVertices() + vertexStencils->GetNumStencils(); - // convert to device stenciltables if necessary. - _vertexStencilTables = - convertToCompatibleStencilTables( + // convert to device stenciltable if necessary. + _vertexStencilTable = + convertToCompatibleStencilTable( vertexStencils, _deviceContext); - _varyingStencilTables = - convertToCompatibleStencilTables( + _varyingStencilTable = + convertToCompatibleStencilTable( varyingStencils, _deviceContext); // FIXME: we do extra copyings for Far::Stencils. @@ -510,7 +510,7 @@ private: } Far::TopologyRefiner * _refiner; - Far::PatchTables * _farPatchTables; + Far::PatchTable * _farPatchTable; int _numVertices; int _maxValence; @@ -521,8 +521,8 @@ private: VertexBufferDescriptor _vertexDesc; VertexBufferDescriptor _varyingDesc; - StencilTables const * _vertexStencilTables; - StencilTables const * _varyingStencilTables; + StencilTable const * _vertexStencilTable; + StencilTable const * _varyingStencilTable; EvaluatorCache * _evaluatorCache; PatchTable *_patchTable; diff --git a/opensubdiv/vtr/fvarLevel.h b/opensubdiv/vtr/fvarLevel.h index 15ad434e..bcd0a9c5 100644 --- a/opensubdiv/vtr/fvarLevel.h +++ b/opensubdiv/vtr/fvarLevel.h @@ -40,15 +40,7 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { -// Forward declaration of friend classes: -namespace Far { - class TopologyRefiner; - class PatchTablesFactory; -} namespace Vtr { - class Refinement; - class FVarRefinement; -} // // FVarLevel: @@ -82,17 +74,8 @@ namespace Vtr { // Everything is being declared public for now to facilitate access until its // clearer how this functionality will be provided. // -namespace Vtr { - class FVarLevel { -protected: - friend class Level; - friend class Refinement; - friend class FVarRefinement; - friend class Far::TopologyRefiner; - friend class Far::PatchTablesFactory; - -protected: +public: // // Component tags -- trying to minimize the types needed here: // @@ -171,7 +154,7 @@ protected: typedef ConstLocalIndexArray ConstSiblingArray; typedef LocalIndexArray SiblingArray; -protected: +public: FVarLevel(Level const& level); ~FVarLevel(); @@ -250,7 +233,8 @@ protected: void print() const; void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector& fvSiblings) const; -protected: +// Members temporarily public pending re-assessment of friends: +public: Level const & _level; // Linear interpolation options vary between channels: diff --git a/opensubdiv/vtr/fvarRefinement.h b/opensubdiv/vtr/fvarRefinement.h index f56acd9e..499e555f 100644 --- a/opensubdiv/vtr/fvarRefinement.h +++ b/opensubdiv/vtr/fvarRefinement.h @@ -40,12 +40,7 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { -// -// Forward declaration of friend classes: -// -namespace Far { - class TopologyRefiner; -} +namespace Vtr { // // FVarRefinement: @@ -60,14 +55,8 @@ namespace Far { // the refinement between Levels serves most purposes and all that is required // in addition is a mapping from values in the child FVarLevel to the parent. // -namespace Vtr { - class FVarRefinement { -protected: - friend class Refinement; - friend class Far::TopologyRefiner; - -protected: +public: FVarRefinement(Refinement const& refinement, FVarLevel& parent, FVarLevel& child); ~FVarRefinement(); @@ -96,7 +85,8 @@ protected: void propagateValueCreases(); void reclassifySemisharpValues(); -protected: +// Members temporarily public pending re-assessment of friends: +public: // // Identify the Refinement, its Levels and assigned FVarLevels for more // immediate access -- child FVarLevel is non-const as it is to be assigned: diff --git a/opensubdiv/vtr/level.h b/opensubdiv/vtr/level.h index 8bb025b4..50d00d9a 100644 --- a/opensubdiv/vtr/level.h +++ b/opensubdiv/vtr/level.h @@ -40,20 +40,9 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { -// Forward declarations for friends: -namespace Far { - template class TopologyRefinerFactory; - class TopologyRefinerFactoryBase; - class TopologyRefiner; - class PatchTablesFactory; -} - namespace Vtr { class Refinement; -class QuadRefinement; -class TriRefinement; -class FVarRefinement; class FVarLevel; // @@ -63,13 +52,12 @@ class FVarLevel; // level can be used as the base level of another subdivision hierarchy and can // be considered a complete mesh independent of its ancestors. It currently // does contain a "depth" member -- as some inferences can then be made about -// the topology (i.e. all quads or all tris if not level 0) but that is still -// under consideration (e.g. a "regular" flag would serve the same purpose, and -// level 0 may even be regular). +// the topology (i.e. all quads or all tris if not level 0). // -// This class is intended for private use within the library. So really its -// interface should be fully protected and only those library classes that need -// it will be declared as friends, e.g. Refinement. +// This class is intended for private use within the library. There are still +// opportunities to specialize levels -- e.g. those supporing N-sided faces vs +// those are are purely quads or tris -- so we prefer to insulate it from public +// access. // // The represenation of topology here is to store six topological relationships // in tables of integers. Each is stored in its own array(s) so the result is @@ -87,38 +75,6 @@ class FVarLevel; // the Far layer essentially store 5 of these 6 in a permuted form -- we add // the face-edges here to simplify refinement. // -// Notes/limitations/stuff to do -- much of this code still reflects the early days -// when it was being prototyped and so it does not conform to OSD standards in many -// ways: -// - superficial stylistic issues: -// . replacing "m" prefix with "_" on member variables -// - done -// . replace "access" and "modify" prefixes on Array methods with "get" -// - done -// - replace use of "...Count" with "GetNum..." -// - use of Vertex vs Vert in non-local (or any?) methods -// - review public/protected/friend accessibility -// -// Most are more relevant to the refinement, which used to be part of this class: -// - short cuts that need revisiting: -// - support for face-vert counts > 4 -// - support for edge-face counts > 2 -// - some neighborhood searches avoidable with more "local indexing" -// - identify (informally) where scheme-specific code will be needed, so far: -// - topological splitting and associated marking -// - really the only variable here is whether to generate tris or -// quads from non-quads -// - interpolation -// - potentially not part of the pre-processing required for FarMesh -// and where it appears *not* to be needed: -// - subdivision of sharpness values -// - classification of vertex type/mask -// - apply classification of vertices (computing Rules or masks) -// - apply to base/course level on conversion -// - apply to child level after subdivision of sharpness -// - keep in mind desired similarity with FarMesh tables for ease of transfer -// (contradicts previous point to some degree) -// class Level { @@ -262,7 +218,7 @@ public: public: - // Debugging aides -- unclear what will persist... + // Debugging aides: enum TopologyError { TOPOLOGY_MISSING_EDGE_FACES=0, TOPOLOGY_MISSING_EDGE_VERTS, @@ -295,8 +251,7 @@ public: void print(const Refinement* parentRefinement = 0) const; public: - // High-level topology queries -- these are likely to be moved elsewhere, but here - // is the best place for them for now... + // High-level topology queries -- these may be moved elsewhere: bool isSingleCreasePatch(Index face, float* sharpnessOut=NULL, int* rotationOut=NULL) const; @@ -325,19 +280,7 @@ public: int gatherTriRegularCornerVertexPatchPoints( Index fIndex, Index patchVerts[], int cornerVertInFace) const; int gatherTriRegularCornerEdgePatchPoints( Index fIndex, Index patchVerts[], int cornerEdgeInFace) const; -protected: - - friend class Refinement; - friend class QuadRefinement; - friend class TriRefinement; - friend class FVarRefinement; - friend class FVarLevel; - - template friend class Far::TopologyRefinerFactory; - friend class Far::TopologyRefinerFactoryBase; - friend class Far::TopologyRefiner; - friend class Far::PatchTablesFactory; - +public: // Sizing methods used to construct a level to populate: void resizeFaces( int numFaces); void resizeFaceVertices(int numFaceVertsTotal); @@ -418,13 +361,14 @@ protected: void resizeVertexEdges(Index vertIndex, int count); void trimVertexEdges( Index vertIndex, int count); -protected: +public: // - // Plans where to have a few specific friend classes properly construct the topology, - // e.g. the Refinement class. There is now clearly a need to have some class - // construct full topology given only a simple face-vertex list. That can be done - // externally (either a Factory outside Vtr or another Vtr construction helper), but - // until we decide where, the required implementation is defined here. + // Initial plans were to have a few specific classes properly construct the + // topology from scratch, e.g. the Refinement class and a Factory class for + // the base level, by populating all topological relations. The need to have + // a class construct full topology given only a simple face-vertex list, made + // it necessary to write code to define and orient all relations -- and most + // of that seemed best placed here. // bool completeTopologyFromFaceVertices(); Index findEdge(Index v0, Index v1, ConstIndexArray v0Edges) const; @@ -437,7 +381,8 @@ protected: IndexArray shareFaceVertCountsAndOffsets() const; -protected: +// Members temporarily public pending re-assessment of friends: +public: // // A Level is independent of subdivision scheme or options. While it may have been // affected by them in its construction, they are not associated with it -- a Level diff --git a/opensubdiv/vtr/refinement.h b/opensubdiv/vtr/refinement.h index 3b780561..0269a216 100644 --- a/opensubdiv/vtr/refinement.h +++ b/opensubdiv/vtr/refinement.h @@ -39,14 +39,8 @@ namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { -namespace Far { - class TopologyRefiner; - class PatchTablesFactory; -} - namespace Vtr { -class SparseSelector; class FVarRefinement; // @@ -60,7 +54,7 @@ class FVarRefinement; // of topological splits that the supported subdivisions schemes collectively require, i.e. those // list in Sdc::SplitType. Note the virtual requirements expected of the subclasses in the list // of protected methods -- they differ mainly in the topology that is created in the child Level -// and not the propagation of tags through refinement, subdivision of sharpness values of the +// and not the propagation of tags through refinement, subdivision of sharpness values or the // treatment of face-varying data. The primary subclasses are QuadRefinement and TriRefinement. // // At a high level, all that is necessary in terms of interface is to construct, initialize @@ -156,22 +150,15 @@ public: Index getChildFaceBaseFace(Index f) const { return _childFaceBaseFaceIndex[f]; } // -// Non-public methods: +// Modifiers intended for internal/protected use: // -protected: - - friend class FVarRefinement; - friend class SparseSelector; - - friend class Far::TopologyRefiner; - friend class Far::PatchTablesFactory; - +public: IndexArray getFaceChildFaces(Index parentFace); IndexArray getFaceChildEdges(Index parentFace); IndexArray getEdgeChildEdges(Index parentEdge); -protected: +public: // // Tags have now been added per-component in Level, but there is additional need to tag // components within Refinement -- we can't tag the parent level components for any @@ -204,10 +191,8 @@ protected: unsigned char _indexInParent : 2; // index of child wrt parent: 0-3, or iterative if N > 4 }; -// -// Remaining methods should remain protected -- for use by subclasses... -// -protected: +// Remaining methods should really be protected -- for use by subclasses... +public: // // Methods involved in constructing the parent-to-child mapping -- when the // refinement is sparse, additional methods are needed to identify the selection: @@ -309,12 +294,12 @@ protected: // void subdivideFVarChannels(); -protected: +// Members temporarily public pending re-assessment of friends: +public: // // Data members -- the logical grouping of some of these (and methods that make use // of them) may lead to grouping them into a few utility classes or structs... // - friend class Level; // Access for some debugging information // Defined on construction: Level const * _parent; diff --git a/regression/common/cmp_utils.h b/regression/common/cmp_utils.h index 43aa1663..3f1d034e 100644 --- a/regression/common/cmp_utils.h +++ b/regression/common/cmp_utils.h @@ -70,10 +70,11 @@ GetReorderedHbrVertexData( { // Populate base level // note : topological ordering is identical between Hbr and Vtr // for the base level + OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0); - int nfaces = refiner.GetNumFaces(0), - nedges = refiner.GetNumEdges(0), - nverts = refiner.GetNumVertices(0); + int nfaces = refBaseLevel.GetNumFaces(), + nedges = refBaseLevel.GetNumEdges(), + nverts = refBaseLevel.GetNumVertices(); maps[0].faces.resize(nfaces, 0); maps[0].edges.resize(nedges, 0); @@ -85,7 +86,7 @@ GetReorderedHbrVertexData( for (int edge = 0; edge GetChild(i); } @@ -127,33 +131,33 @@ GetReorderedHbrVertexData( // populate child face-verts -- when present (none for Loop subdivision) if (!schemeIsLoop) { Hvertex * v = f->Subdivide(); - Index childVert = refiner.GetFaceChildVertex(level-1, face); + Index childVert = refPrevLevel.GetFaceChildVertex(face); assert(v->GetParentFace()); current.verts[childVert] = v; } } - for (int edge=0; edge < refiner.GetNumEdges(level-1); ++edge) { + for (int edge=0; edge < refPrevLevel.GetNumEdges(); ++edge) { // populate child edge-verts - Index childVert = refiner.GetEdgeChildVertex(level-1,edge); + Index childVert = refPrevLevel.GetEdgeChildVertex(edge); Hhalfedge * e = previous.edges[edge]; Hvertex * v = e->Subdivide(); assert(v->GetParentEdge()); current.verts[childVert] = v; } - for (int vert = 0; vert < refiner.GetNumVertices(level-1); ++vert) { + for (int vert = 0; vert < refPrevLevel.GetNumVertices(); ++vert) { // populate child vert-verts - Index childVert = refiner.GetVertexChildVertex(level-1, vert); + Index childVert = refPrevLevel.GetVertexChildVertex(vert); Hvertex * v = previous.verts[vert]->Subdivide(); current.verts[childVert] = v; assert(v->GetParentVertex()); } // populate child edges - for (int edge=0; edge < refiner.GetNumEdges(level); ++edge) { + for (int edge=0; edge < refLevel.GetNumEdges(); ++edge) { - ConstIndexArray vtrVerts = refiner.GetEdgeVertices(level, edge); + ConstIndexArray vtrVerts = refLevel.GetEdgeVertices(edge); Hvertex const * v0 = current.verts[vtrVerts[0]], * v1 = current.verts[vtrVerts[1]]; @@ -166,7 +170,7 @@ GetReorderedHbrVertexData( assert(e); current.edges[edge] = e; } - ecount += refiner.GetNumEdges(level-1); + ecount += refPrevLevel.GetNumEdges(); } } }; diff --git a/regression/common/vtr_utils.cpp b/regression/common/vtr_utils.cpp index 6afcac9f..37acaf7a 100644 --- a/regression/common/vtr_utils.cpp +++ b/regression/common/vtr_utils.cpp @@ -46,7 +46,7 @@ InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner, fvarWidth = 2; int numValuesTotal = refiner.GetNumFVarValuesTotal(channel), - numValues0 = refiner.GetNumFVarValues(0, channel); + numValues0 = refiner.GetLevel(0).GetNumFVarValues(channel); if (shape.uvs.empty() or numValuesTotal<=0) { return; @@ -57,7 +57,7 @@ InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner, std::vector buffer(numValuesTotal); int maxlevel = refiner.GetMaxLevel(), - numValuesM = refiner.GetNumFVarValues(maxlevel, channel); + numValuesM = refiner.GetLevel(maxlevel).GetNumFVarValues(channel); memcpy(&buffer[0], &shape.uvs[0], shape.uvs.size()*sizeof(float)); diff --git a/regression/common/vtr_utils.h b/regression/common/vtr_utils.h index 49788291..6a768e0b 100644 --- a/regression/common/vtr_utils.h +++ b/regression/common/vtr_utils.h @@ -155,14 +155,14 @@ InterpolateVtrVertexData(const char *shapeStr, Scheme scheme, int maxlevel, // populate coarse mesh positions data.resize(refiner->GetNumVerticesTotal()); - for (int i=0; iGetNumVertices(0); i++) { + for (int i=0; iGetLevel(0).GetNumVertices(); i++) { data[i].SetPosition(shape->verts[i*3+0], shape->verts[i*3+1], shape->verts[i*3+2]); } T * verts = &data[0]; - refiner->Interpolate(verts, verts+refiner->GetNumVertices(0)); + refiner->Interpolate(verts, verts+refiner->GetLevel(0).GetNumVertices()); delete shape; return refiner; @@ -204,7 +204,7 @@ TopologyRefinerFactory::assignComponentTopology( Far::TopologyRefiner & refiner, Shape const & shape) { { // Face relations: - int nfaces = refiner.GetNumFaces(0); + int nfaces = refiner.GetLevel(0).GetNumFaces(); for (int i=0, ofs=0; i < nfaces; ++i) { @@ -235,7 +235,7 @@ TopologyRefinerFactory::assignFaceVaryingTopology( // UV layyout (we only parse 1 channel) if (not shape.faceuvs.empty()) { - int nfaces = refiner.GetNumFaces(0), + int nfaces = refiner.GetLevel(0).GetNumFaces(), channel = refiner.createBaseFVarChannel( (int)shape.uvs.size()/2 ); for (int i=0, ofs=0; i < nfaces; ++i) { @@ -273,7 +273,7 @@ TopologyRefinerFactory::assignComponentTags( for (int j=0; j<(int)t->intargs.size()-1; j += 2) { - OpenSubdiv::Vtr::Index edge = refiner.FindEdge(/*level*/0, t->intargs[j], t->intargs[j+1]); + OpenSubdiv::Vtr::Index edge = refiner.GetLevel(0).FindEdge(t->intargs[j], t->intargs[j+1]); if (edge==OpenSubdiv::Vtr::INDEX_INVALID) { printf("cannot find edge for crease tag (%d,%d)\n", t->intargs[j], t->intargs[j+1] ); return false; @@ -287,7 +287,7 @@ TopologyRefinerFactory::assignComponentTags( for (int j=0; j<(int)t->intargs.size(); ++j) { int vertex = t->intargs[j]; - if (vertex<0 or vertex>=refiner.GetNumVertices(/*level*/0)) { + if (vertex<0 or vertex>=refiner.GetLevel(0).GetNumVertices()) { printf("cannot find vertex for corner tag (%d)\n", vertex ); return false; } else { diff --git a/regression/osd_regression/main.cpp b/regression/osd_regression/main.cpp index 552c60da..c63ce5ae 100644 --- a/regression/osd_regression/main.cpp +++ b/regression/osd_regression/main.cpp @@ -52,7 +52,7 @@ GLFWwindow* g_window=0; #include -#include +#include #include "../../regression/common/cmp_utils.h" #include "../../regression/common/hbr_utils.h" @@ -246,19 +246,19 @@ checkVertexBuffer( //------------------------------------------------------------------------------ static void -buildStencilTables( +buildStencilTable( const FarTopologyRefiner &refiner, - Far::StencilTables const **vertexStencils, - Far::StencilTables const **varyingStencils) + Far::StencilTable const **vertexStencils, + Far::StencilTable const **varyingStencils) { - Far::StencilTablesFactory::Options soptions; + Far::StencilTableFactory::Options soptions; soptions.generateOffsets = true; soptions.generateIntermediateLevels = true; - *vertexStencils = Far::StencilTablesFactory::Create(refiner, soptions); + *vertexStencils = Far::StencilTableFactory::Create(refiner, soptions); - soptions.interpolationMode = Far::StencilTablesFactory::INTERPOLATE_VARYING; - *varyingStencils = Far::StencilTablesFactory::Create(refiner, soptions); + soptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_VARYING; + *varyingStencils = Far::StencilTableFactory::Create(refiner, soptions); } @@ -269,9 +269,9 @@ checkMeshCPU( FarTopologyRefiner *refiner, const std::vector& coarseverts, xyzmesh * refmesh) { - Far::StencilTables const *vertexStencils; - Far::StencilTables const *varyingStencils; - buildStencilTables(*refiner, &vertexStencils, &varyingStencils); + Far::StencilTable const *vertexStencils; + Far::StencilTable const *varyingStencils; + buildStencilTable(*refiner, &vertexStencils, &varyingStencils); assert(coarseverts.size() == (size_t)refiner->GetNumVerticesTotal()); @@ -284,7 +284,7 @@ checkMeshCPU( FarTopologyRefiner *refiner, vb, Osd::VertexBufferDescriptor(0, 3, 3), vb, - Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3), + Osd::VertexBufferDescriptor(refiner->GetLevel(0).GetNumVertices()*3, 3, 3), vertexStencils); int result = checkVertexBuffer(*refiner, refmesh, vb->BindCpuBuffer(), @@ -303,9 +303,9 @@ checkMeshCPUGL(FarTopologyRefiner *refiner, const std::vector& coarseverts, xyzmesh * refmesh) { - Far::StencilTables const *vertexStencils; - Far::StencilTables const *varyingStencils; - buildStencilTables(*refiner, &vertexStencils, &varyingStencils); + Far::StencilTable const *vertexStencils; + Far::StencilTable const *varyingStencils; + buildStencilTable(*refiner, &vertexStencils, &varyingStencils); Osd::CpuGLVertexBuffer *vb = Osd::CpuGLVertexBuffer::Create(3, refiner->GetNumVerticesTotal()); @@ -316,7 +316,7 @@ checkMeshCPUGL(FarTopologyRefiner *refiner, vb, Osd::VertexBufferDescriptor(0, 3, 3), vb, - Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3), + Osd::VertexBufferDescriptor(refiner->GetLevel(0).GetNumVertices()*3, 3, 3), vertexStencils); int result = checkVertexBuffer(*refiner, refmesh, diff --git a/tutorials/far/tutorial_0/far_tutorial_0.cpp b/tutorials/far/tutorial_0/far_tutorial_0.cpp index 43293bb8..8b7071f9 100644 --- a/tutorials/far/tutorial_0/far_tutorial_0.cpp +++ b/tutorials/far/tutorial_0/far_tutorial_0.cpp @@ -149,23 +149,25 @@ int main(int, char **) { { // Output OBJ of the highest level refined ----------- + Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel); + // Print vertex positions for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { - for (int vert=0; vertGetNumVertices(maxlevel); ++vert) { + for (int vert=0; vertGetNumVertices(level); + firstVert += refiner->GetLevel(level).GetNumVertices(); } } // Print faces - for (int face=0; faceGetNumFaces(maxlevel); ++face) { + for (int face=0; faceGetFaceVertices(maxlevel, face); + Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face); // all refined Catmark faces should be quads assert(fverts.size()==4); diff --git a/tutorials/far/tutorial_1/far_tutorial_1.cpp b/tutorials/far/tutorial_1/far_tutorial_1.cpp index 7294d61c..0d7ebab9 100644 --- a/tutorials/far/tutorial_1/far_tutorial_1.cpp +++ b/tutorials/far/tutorial_1/far_tutorial_1.cpp @@ -454,23 +454,25 @@ int main(int, char **) { { // Output OBJ of the highest level refined ----------- + Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel); + // Print vertex positions for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { - for (int vert=0; vertGetNumVertices(maxlevel); ++vert) { + for (int vert=0; vertGetNumVertices(level); + firstVert += refiner->GetLevel(level).GetNumVertices(); } } // Print faces - for (int face=0; faceGetNumFaces(maxlevel); ++face) { + for (int face=0; faceGetFaceVertices(maxlevel, face); + Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face); // all refined Catmark faces should be quads assert(fverts.size()==4); diff --git a/tutorials/far/tutorial_1/hbr_to_vtr.h b/tutorials/far/tutorial_1/hbr_to_vtr.h index 142edcee..cf720e27 100644 --- a/tutorials/far/tutorial_1/hbr_to_vtr.h +++ b/tutorials/far/tutorial_1/hbr_to_vtr.h @@ -339,7 +339,7 @@ FarTopologyRefinerFactory::assignComponentTopology( OsdHbrConverter::EdgeMap & edges = const_cast(conv).GetEdges(); { // Face relations: - int nfaces = refiner.GetNumFaces(/*level*/0); + int nfaces = refiner.GetLevel(0).GetNumFaces(); for (int i=0; i < nfaces; ++i) { IndexArray dstFaceVerts = refiner.setBaseFaceVertices(i); @@ -377,7 +377,7 @@ FarTopologyRefinerFactory::assignComponentTopology( } { // Vert relations - for (int i=0; i::assignComponentTags( } // Initialize vertex sharpness - for (int i=0; iGetSharpness()); } diff --git a/tutorials/far/tutorial_2/far_tutorial_2.cpp b/tutorials/far/tutorial_2/far_tutorial_2.cpp index cd7add97..d3b5d6a4 100644 --- a/tutorials/far/tutorial_2/far_tutorial_2.cpp +++ b/tutorials/far/tutorial_2/far_tutorial_2.cpp @@ -166,11 +166,11 @@ int main(int, char **) { // 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); + int nverts = refiner->GetLevel(maxlevel).GetNumVertices(); // Position the 'verts' pointer to the first vertex of our 'maxlevel' level for (int level=0; levelGetNumVertices(level); + verts += refiner->GetLevel(level).GetNumVertices(); } // Output particle positions diff --git a/tutorials/far/tutorial_3/far_tutorial_3.cpp b/tutorials/far/tutorial_3/far_tutorial_3.cpp index 626d34c1..017957a1 100644 --- a/tutorials/far/tutorial_3/far_tutorial_3.cpp +++ b/tutorials/far/tutorial_3/far_tutorial_3.cpp @@ -214,7 +214,7 @@ int main(int, char **) { // Allocate & interpolate the 'face-varying' primvar data int channel = 0, - nCoarseFVVerts = refiner->GetNumFVarValues(0, channel); + nCoarseFVVerts = refiner->GetLevel(0).GetNumFVarValues(channel); std::vector fvBuffer(refiner->GetNumFVarValuesTotal(channel)); FVarVertex * fvVerts = &fvBuffer[0]; @@ -229,16 +229,18 @@ int main(int, char **) { { // Output OBJ of the highest level refined ----------- + Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel); + // Print vertex positions for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { - for (int vert=0; vertGetNumVertices(level); ++vert) { + for (int vert=0; vertGetNumVertices(level); + firstVert += refiner->GetLevel(level).GetNumVertices(); } } @@ -246,21 +248,21 @@ int main(int, char **) { for (int level=0, firstVert=0; level<=maxlevel; ++level) { if (level==maxlevel) { - for (int vert=0; vertGetNumFVarValues(level, channel); ++vert) { + for (int vert=0; vertGetNumFVarValues(level, channel); + firstVert += refiner->GetLevel(level).GetNumFVarValues(channel); } } // Print faces - for (int face=0; faceGetNumFaces(maxlevel); ++face) { + for (int face=0; faceGetFaceVertices(maxlevel, face), - fvverts = refiner->GetFVarFaceValues(maxlevel, face, channel); + Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face), + fvverts = refLastLevel.GetFVarFaceValues(face, channel); // all refined Catmark faces should be quads assert(fverts.size()==4 and fvverts.size()==4); diff --git a/tutorials/far/tutorial_4/far_tutorial_4.cpp b/tutorials/far/tutorial_4/far_tutorial_4.cpp index 8d65519b..b3815f5f 100644 --- a/tutorials/far/tutorial_4/far_tutorial_4.cpp +++ b/tutorials/far/tutorial_4/far_tutorial_4.cpp @@ -26,13 +26,13 @@ //------------------------------------------------------------------------------ // Tutorial description: // -// This tutorial shows how to create and manipulate FarStencilTables. We use the +// This tutorial shows how to create and manipulate FarStencilTable. We use the // factorized stencils to interpolate vertex primvar data buffers. // #include -#include -#include +#include +#include #include #include @@ -118,17 +118,17 @@ int main(int, char **) { refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel)); - // Use the FarStencilTables factory to create discrete stencil tables + // Use the FarStencilTable factory to create discrete stencil table // note: we only want stencils for the highest refinement level. - Far::StencilTablesFactory::Options options; + Far::StencilTableFactory::Options options; options.generateIntermediateLevels=false; options.generateOffsets=true; - Far::StencilTables const * stencilTables = - Far::StencilTablesFactory::Create(*refiner, options); + Far::StencilTable const * stencilTable = + Far::StencilTableFactory::Create(*refiner, options); // Allocate vertex primvar buffer (1 stencil for each vertex) - int nstencils = stencilTables->GetNumStencils(); + int nstencils = stencilTable->GetNumStencils(); std::vector vertexBuffer(nstencils); @@ -141,7 +141,7 @@ int main(int, char **) { // Apply stencils on the control vertex data to update the primvar data // of the refined vertices. - stencilTables->UpdateValues(controlValues, &vertexBuffer[0]); + stencilTable->UpdateValues(controlValues, &vertexBuffer[0]); } { // Visualization with Maya : print a MEL script that generates particles @@ -156,7 +156,7 @@ int main(int, char **) { } delete refiner; - delete stencilTables; + delete stencilTable; } //------------------------------------------------------------------------------ diff --git a/tutorials/far/tutorial_5/far_tutorial_5.cpp b/tutorials/far/tutorial_5/far_tutorial_5.cpp index bea126cb..48e1ee5d 100644 --- a/tutorials/far/tutorial_5/far_tutorial_5.cpp +++ b/tutorials/far/tutorial_5/far_tutorial_5.cpp @@ -27,13 +27,13 @@ // Tutorial description: // // This tutorial shows how to create and manipulate both 'vertex' and 'varying' -// Far::StencilTables to interpolate 2 primvar data buffers: vertex positions and +// Far::StencilTable to interpolate 2 primvar data buffers: vertex positions and // vertex colors. // #include -#include -#include +#include +#include #include #include @@ -121,10 +121,10 @@ int main(int, char **) { int maxlevel = 4; refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel)); - int nverts = refiner->GetNumVertices(maxlevel); + int nverts = refiner->GetLevel(maxlevel).GetNumVertices(); - // Use the Far::StencilTables factory to create discrete stencil tables - Far::StencilTablesFactory::Options options; + // Use the Far::StencilTable factory to create discrete stencil table + Far::StencilTableFactory::Options options; options.generateIntermediateLevels=false; // only the highest refinement level. options.generateOffsets=true; @@ -133,10 +133,10 @@ int main(int, char **) { // // Create stencils table for 'vertex' interpolation - options.interpolationMode=Far::StencilTablesFactory::INTERPOLATE_VERTEX; + options.interpolationMode=Far::StencilTableFactory::INTERPOLATE_VERTEX; - Far::StencilTables const * vertexStencils = - Far::StencilTablesFactory::Create(*refiner, options); + Far::StencilTable const * vertexStencils = + Far::StencilTableFactory::Create(*refiner, options); assert(nverts==vertexStencils->GetNumStencils()); // Allocate vertex primvar buffer (1 stencil for each vertex) @@ -150,10 +150,10 @@ int main(int, char **) { // // Create stencils table for 'varying' interpolation - options.interpolationMode=Far::StencilTablesFactory::INTERPOLATE_VARYING; + options.interpolationMode=Far::StencilTableFactory::INTERPOLATE_VARYING; - Far::StencilTables const * varyingStencils = - Far::StencilTablesFactory::Create(*refiner, options); + Far::StencilTable const * varyingStencils = + Far::StencilTableFactory::Create(*refiner, options); assert(nverts==varyingStencils->GetNumStencils()); // Allocate varying primvar buffer (1 stencil for each vertex) diff --git a/tutorials/far/tutorial_6/far_tutorial_6.cpp b/tutorials/far/tutorial_6/far_tutorial_6.cpp index fce5d6ed..0fbabfc5 100644 --- a/tutorials/far/tutorial_6/far_tutorial_6.cpp +++ b/tutorials/far/tutorial_6/far_tutorial_6.cpp @@ -41,7 +41,7 @@ // #include -#include +#include #include #include #include @@ -155,14 +155,14 @@ int main(int, char **) { refiner->Interpolate(&verts[0], &verts[g_nverts]); - // Generate a set of Far::PatchTables that we will use to evaluate the + // Generate a set of Far::PatchTable that we will use to evaluate the // surface limit Far::EndCapGregoryBasisPatchFactory endcapFactory(*refiner); - Far::PatchTables const * patchTables = - Far::PatchTablesFactory::Create(*refiner, Far::PatchTablesFactory::Options()); + Far::PatchTable const * patchTable = + Far::PatchTableFactory::Create(*refiner, Far::PatchTableFactory::Options()); // Create a Far::PatchMap to help locating patches in the table - Far::PatchMap patchmap(*patchTables); + Far::PatchMap patchmap(*patchTable); // Create a Far::PtexIndices to help find indices of ptex faces. Far::PtexIndices ptexIndices(*refiner); @@ -185,14 +185,14 @@ int main(int, char **) { t = (float)rand()/(float)RAND_MAX; // Locate the patch corresponding to the face ptex idx and (s,t) - Far::PatchTables::PatchHandle const * handle = + Far::PatchTable::PatchHandle const * handle = patchmap.FindPatch(face, s, t); assert(handle); // Evaluate the patch weights, identify the CVs and compute the limit frame: - patchTables->EvaluateBasis(*handle, s, t, pWeights, dsWeights, dtWeights); + patchTable->EvaluateBasis(*handle, s, t, pWeights, dsWeights, dtWeights); - Far::ConstIndexArray cvs = patchTables->GetPatchVertices(*handle); + Far::ConstIndexArray cvs = patchTable->GetPatchVertices(*handle); LimitFrame & dst = samples[count]; dst.Clear(); diff --git a/tutorials/far/tutorial_7/far_tutorial_7.cpp b/tutorials/far/tutorial_7/far_tutorial_7.cpp index 70a1e836..066b9b0c 100644 --- a/tutorials/far/tutorial_7/far_tutorial_7.cpp +++ b/tutorials/far/tutorial_7/far_tutorial_7.cpp @@ -26,12 +26,12 @@ //------------------------------------------------------------------------------ // Tutorial description: // -// This tutorial shows how to create and manipulate tables of cascading stencils. +// This tutorial shows how to create and manipulate table of cascading stencils. // // We initalize a Far::TopologyRefiner initalized with a cube and apply uniform -// refinement. We then use a Far::StencilTablesFactory to generate stencil -// tables. We set the factory Options to not factorize intermediate levels, -// thus giving tables of "cascading" stencils. +// refinement. We then use a Far::StencilTableFactory to generate a stencil +// table. We set the factory Options to not factorize intermediate levels, +// thus giving a table of "cascading" stencils. // // We then apply the stencils to the vertex position primvar data, and insert // a hierarchical edit at level 1. This edit is smoothed by the application @@ -42,8 +42,8 @@ // #include -#include -#include +#include +#include #include #include @@ -131,17 +131,17 @@ int main(int, char **) { int maxlevel = 4; refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel)); - // Use the FarStencilTables factory to create cascading stencil tables + // Use the FarStencilTable factory to create cascading stencil table // note: we want stencils for the each refinement level // "cascade" mode is achieved by setting "factorizeIntermediateLevels" // to false - Far::StencilTablesFactory::Options options; + Far::StencilTableFactory::Options options; options.generateIntermediateLevels=true; options.factorizeIntermediateLevels=false; options.generateOffsets=true; - Far::StencilTables const * stencilTables = - Far::StencilTablesFactory::Create(*refiner, options); + Far::StencilTable const * stencilTable = + Far::StencilTableFactory::Create(*refiner, options); std::vector vertexBuffer(refiner->GetNumVerticesTotal()-g_nverts); @@ -150,7 +150,7 @@ int main(int, char **) { int start = 0, end = 0; // stencils batches for each level of subdivision for (int level=0; levelGetNumVertices(level+1); + int nverts = refiner->GetLevel(level+1).GetNumVertices(); Vertex const * srcVerts = reinterpret_cast(g_verts); if (level>0) { @@ -160,7 +160,7 @@ int main(int, char **) { start = end; end += nverts; - stencilTables->UpdateValues(srcVerts, destVerts, start, end); + stencilTable->UpdateValues(srcVerts, destVerts, start, end); // apply 2 hierarchical edits on level 1 vertices if (level==1) { @@ -180,9 +180,11 @@ int main(int, char **) { // Print vertex positions for (int level=1, firstvert=0; level<=maxlevel; ++level) { + Far::TopologyLevel const & refLevel = refiner->GetLevel(level); + printf("g level_%d\n", level); - int nverts = refiner->GetNumVertices(level); + int nverts = refLevel.GetNumVertices(); for (int vert=0; vertGetNumFaces(level); ++face) { + for (int face=0; faceGetFaceVertices(level, face); + Far::ConstIndexArray fverts = refLevel.GetFaceVertices(face); // all refined Catmark faces should be quads assert(fverts.size()==4); @@ -208,7 +210,7 @@ int main(int, char **) { } delete refiner; - delete stencilTables; + delete stencilTable; } //------------------------------------------------------------------------------ diff --git a/tutorials/osd/tutorial_0/osd_tutorial_0.cpp b/tutorials/osd/tutorial_0/osd_tutorial_0.cpp index 94a77040..bddbe337 100644 --- a/tutorials/osd/tutorial_0/osd_tutorial_0.cpp +++ b/tutorials/osd/tutorial_0/osd_tutorial_0.cpp @@ -31,7 +31,7 @@ // #include -#include +#include #include #include @@ -75,22 +75,22 @@ int main(int, char **) { // // Setup phase // - Far::StencilTables const * stencilTables = NULL; + Far::StencilTable const * stencilTable = NULL; { // Setup Context Far::TopologyRefiner const * refiner = createTopologyRefiner(maxlevel); - // Setup a factory to create FarStencilTables (for more details see + // Setup a factory to create FarStencilTable (for more details see // Far tutorials) - Far::StencilTablesFactory::Options options; + Far::StencilTableFactory::Options options; options.generateOffsets=true; options.generateIntermediateLevels=false; - stencilTables = Far::StencilTablesFactory::Create(*refiner, options); + stencilTable = Far::StencilTableFactory::Create(*refiner, options); - nCoarseVerts = refiner->GetNumVertices(0); - nRefinedVerts = stencilTables->GetNumStencils(); + nCoarseVerts = refiner->GetLevel(0).GetNumVertices(); + nRefinedVerts = stencilTable->GetNumStencils(); - // We are done with Far: cleanup tables + // We are done with Far: cleanup table delete refiner; } @@ -113,7 +113,7 @@ int main(int, char **) { // Launch the computation Osd::CpuEvaluator::EvalStencils(vbuffer, srcDesc, vbuffer, dstDesc, - stencilTables); + stencilTable); } { // Visualization with Maya : print a MEL script that generates particles @@ -128,7 +128,7 @@ int main(int, char **) { printf("-c 1;\n"); } - delete stencilTables; + delete stencilTable; delete vbuffer; }