Merge branch 'upstream-dev' into dev

This commit is contained in:
Ignacio Lillo 2015-05-23 00:29:39 -03:00
commit 0a6a47159e
92 changed files with 2877 additions and 2565 deletions

View File

@ -45,11 +45,11 @@ First, *Far* provides the tools to refine subdivision topology
either uniform or sparse, where extraordinary features are automatically either uniform or sparse, where extraordinary features are automatically
isolated (see `feature adaptive subdivision <subdivision_surfaces.html#feature-adaptive-subdivision>`__). isolated (see `feature adaptive subdivision <subdivision_surfaces.html#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 These tables are designed to be static containers for the refined topology
data, after it has been serialized and factorized. This representation is data, after it has been serialized and factorized. This representation is
embodied in the `Far::PatchTables <#far-patchtables>`__ and the embodied in the `Far::PatchTable <#far-patchtable>`__ and the
`Far::StencilTables <#far-patchtables>`__ classes. `Far::StencilTable <#far-patchtable>`__ classes.
*Far* is also a fully featured API. Typically *Far* tabular data is targeted at *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 *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 TopologyRefiner is the building block for many other useful classes in
OpenSubdiv, but its purpose is more specific. It is intended to store the OpenSubdiv, but its purpose is more specific. It is intended to store the
topology of an arbitrarily refined subdivision hierarchy to support the topology of an arbitrarily refined subdivision hierarchy to support the
construction of `stencil tables <#patch-tables>`__, `patch tables construction of `stencil table <#patch-table>`__, `patch table
<#patch-tables>`__, etc. <#patch-table>`__, etc.
Aside from public access to topology, TopologyRefiner has public refinement Aside from public access to topology, TopologyRefiner has public refinement
methods (currently *RefineUniform()* and *RefineAdapative()*) where simple 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 <MESH> and also potentially to both to provide common code independent of <MESH> and also potentially to
protect core code from unwanted specialization. protect core code from unwanted specialization.
Far::PatchTables Far::PatchTable
================ ================
The patch tables are a serialized topology representation. This container is The patch table is a serialized topology representation. This container is
generated using *Far::PatchTablesFactory* from an instance generated using *Far::PatchTableFactory* from an instance
*Far::TopologyRefiner* after a refinement has been applied. The *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 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 dictated by the refinement mode (uniform or adaptive). The patches are then
sorted into arrays based on their types. 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*. *pattern* and *rotation*.
The PatchArray *ArrayRange* provides the indices necessary to track the records 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 Patch Types
*********** ***********
The following are the different patch types that can be represented in the 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 .. include:: under_development.rst
Far::StencilTables Far::StencilTable
================== ==================
The base container for stencil data is the StencilTables class. As with most The base container for stencil data is the StencilTable class. As with most
other Far entities, it has an associated StencilTablesFactory that requires a other Far entities, it has an associated StencilTableFactory that requires a
TopologyRefiner: TopologyRefiner:
Advantages 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 The interpolation calculations for any given vertex can be broken down into
sequences of multiply-add operations applied to the supporting vertices. 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. created by combining the list of control vertices from the 1-ring.
With iterative subdivision, each refinement step is dependent upon the previous 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 .. image:: images/far_stencil0.png
:align: center :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 and efficient method of evaluation of specific locations on the limit of a
subdivision surface, starting from the coarse vertices of the control cage. subdivision surface, starting from the coarse vertices of the control cage.

View File

@ -63,8 +63,8 @@
<li><a href="far_overview.html">Far</a></li> <li><a href="far_overview.html">Far</a></li>
<ul> <ul>
<li><a href="far_overview.html#far-topologyrefiner">Topology Refiner</a></li> <li><a href="far_overview.html#far-topologyrefiner">Topology Refiner</a></li>
<li><a href="far_overview.html#far-patchtables">Patch Tables</a></li> <li><a href="far_overview.html#far-patchtable">Patch Table</a></li>
<li><a href="far_overview.html#far-stenciltables">Stencil Tables</a></li> <li><a href="far_overview.html#far-stenciltable">Stencil Table</a></li>
</ul> </ul>
<li><a href="vtr_overview.html">Vtr</a></li> <li><a href="vtr_overview.html">Vtr</a></li>
<li><a href="sdc_overview.html">Sdc</a></li> <li><a href="sdc_overview.html">Sdc</a></li>

View File

@ -119,7 +119,7 @@ a series of regression tests that compare the methods to each other.
* **Beta Issues** * **Beta Issues**
Face-varying smooth data interpolation is currently only supported in 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.
---- ----

View File

@ -89,17 +89,17 @@ or in your local ``<repository root>/turorials``.
| |far_tut_3| | |far_tut_3|
| |
- | **Tutorial 4** - | **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] <far_tutorial_4.html>`__ factorized stencils to interpolate vertex primvar data buffers. `[code] <far_tutorial_4.html>`__
| |
| **Tutorial 5** | **Tutorial 5**
| This tutorial shows how to create and manipulate both 'vertex' and 'varying' | 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] <far_tutorial_5.html>`__ vertex colors. `[code] <far_tutorial_5.html>`__
| |
| **Tutorial 6** | **Tutorial 6**
| This tutorial shows how to interpolate surface limits at arbitrary | This tutorial shows how to interpolate surface limits at arbitrary
parametric locations using feature adaptive Far::PatchTables. `[code] <far_tutorial_6.html>`__ parametric locations using feature adaptive Far::PatchTable. `[code] <far_tutorial_6.html>`__
| |far_tut_6| | |far_tut_6|
| |
| **Tutorial 7** | **Tutorial 7**

View File

@ -25,7 +25,7 @@
#ifndef OPENSUBDIV_EXAMPLES_COMMON_PATCH_COLORS_H #ifndef OPENSUBDIV_EXAMPLES_COMMON_PATCH_COLORS_H
#define OPENSUBDIV_EXAMPLES_COMMON_PATCH_COLORS_H #define OPENSUBDIV_EXAMPLES_COMMON_PATCH_COLORS_H
#include <far/patchTables.h> #include <far/patchTable.h>
// returns a unique color for each type of feature-adaptive patches // returns a unique color for each type of feature-adaptive patches
float const * getAdaptivePatchColor(OpenSubdiv::Far::PatchDescriptor const & desc); float const * getAdaptivePatchColor(OpenSubdiv::Far::PatchDescriptor const & desc);

View File

@ -236,12 +236,14 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner * refiner,
typedef OpenSubdiv::Far::ConstIndexArray IndexArray; typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
// calc normal vectors // calc normal vectors
int nverts = refiner->GetNumVertices(0), OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
nfaces = refiner->GetNumFaces(0);
int nverts = refBaseLevel.GetNumVertices(),
nfaces = refBaseLevel.GetNumFaces();
for (int face = 0; face < nfaces; ++face) { 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], float const * p0 = &pos[fverts[0]*3],
* p1 = &pos[fverts[1]*3], * p1 = &pos[fverts[1]*3],
@ -704,12 +706,13 @@ createOsdMesh(int level, int kernel) {
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)); OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
// create cage edge index // create cage edge index
int nedges = refiner->GetNumEdges(0); int nedges = refBaseLevel.GetNumEdges();
std::vector<int> edgeIndices(nedges*2); std::vector<int> edgeIndices(nedges*2);
for(int i=0; i<nedges; ++i) { for(int i=0; i<nedges; ++i) {
IndexArray verts = refiner->GetEdgeVertices(0, i); IndexArray verts = refBaseLevel.GetEdgeVertices(i);
edgeIndices[i*2 ]=verts[0]; edgeIndices[i*2 ]=verts[0];
edgeIndices[i*2+1]=verts[1]; edgeIndices[i*2+1]=verts[1];
} }
@ -734,7 +737,7 @@ createOsdMesh(int level, int kernel) {
if (g_kernel == kCPU) { if (g_kernel == kCPU) {
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::CpuEvaluator, Osd::CpuEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -746,7 +749,7 @@ createOsdMesh(int level, int kernel) {
#ifdef OPENSUBDIV_HAS_OPENMP #ifdef OPENSUBDIV_HAS_OPENMP
} else if (kernel == kOPENMP) { } else if (kernel == kOPENMP) {
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::OmpEvaluator, Osd::OmpEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -758,7 +761,7 @@ createOsdMesh(int level, int kernel) {
#ifdef OPENSUBDIV_HAS_TBB #ifdef OPENSUBDIV_HAS_TBB
} else if (kernel == kTBB) { } else if (kernel == kTBB) {
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::TbbEvaluator, Osd::TbbEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -771,7 +774,7 @@ createOsdMesh(int level, int kernel) {
} else if(kernel == kCL) { } else if(kernel == kCL) {
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache; static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer,
Osd::CLStencilTables, Osd::CLStencilTable,
Osd::CLEvaluator, Osd::CLEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
CLD3D11DeviceContext>( CLD3D11DeviceContext>(
@ -785,7 +788,7 @@ createOsdMesh(int level, int kernel) {
#ifdef OPENSUBDIV_HAS_CUDA #ifdef OPENSUBDIV_HAS_CUDA
} else if (g_kernel == kCUDA) { } else if (g_kernel == kCUDA) {
g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer,
Osd::CudaStencilTables, Osd::CudaStencilTable,
Osd::CudaEvaluator, Osd::CudaEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -797,7 +800,7 @@ createOsdMesh(int level, int kernel) {
} else if (g_kernel == kDirectCompute) { } else if (g_kernel == kDirectCompute) {
static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache; static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache;
g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer,
Osd::D3D11StencilTables, Osd::D3D11StencilTable,
Osd::D3D11ComputeEvaluator, Osd::D3D11ComputeEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(

View File

@ -277,22 +277,24 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)); Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
int nedges = refiner->GetNumEdges(0), Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
nverts = refiner->GetNumVertices(0);
int nedges = refBaseLevel.GetNumEdges(),
nverts = refBaseLevel.GetNumVertices();
g_coarseEdges.resize(nedges*2); g_coarseEdges.resize(nedges*2);
g_coarseEdgeSharpness.resize(nedges); g_coarseEdgeSharpness.resize(nedges);
g_coarseVertexSharpness.resize(nverts); g_coarseVertexSharpness.resize(nverts);
for(int i=0; i<nedges; ++i) { for(int i=0; i<nedges; ++i) {
IndexArray verts = refiner->GetEdgeVertices(0, i); IndexArray verts = refBaseLevel.GetEdgeVertices(i);
g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2 ]=verts[0];
g_coarseEdges[i*2+1]=verts[1]; g_coarseEdges[i*2+1]=verts[1];
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
} }
for(int i=0; i<nverts; ++i) { for(int i=0; i<nverts; ++i) {
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i); g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
} }
g_orgPositions=shape->verts; g_orgPositions=shape->verts;
@ -320,7 +322,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
if (g_kernel == kCPU) { if (g_kernel == kCPU) {
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::CpuEvaluator, Osd::CpuEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -332,7 +334,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
#ifdef OPENSUBDIV_HAS_OPENMP #ifdef OPENSUBDIV_HAS_OPENMP
} else if (kernel == kOPENMP) { } else if (kernel == kOPENMP) {
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::OmpEvaluator, Osd::OmpEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -344,7 +346,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
#ifdef OPENSUBDIV_HAS_TBB #ifdef OPENSUBDIV_HAS_TBB
} else if (kernel == kTBB) { } else if (kernel == kTBB) {
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::TbbEvaluator, Osd::TbbEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -357,7 +359,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
} else if(kernel == kCL) { } else if(kernel == kCL) {
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache; static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer,
Osd::CLStencilTables, Osd::CLStencilTable,
Osd::CLEvaluator, Osd::CLEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
CLD3D11DeviceContext>( CLD3D11DeviceContext>(
@ -371,7 +373,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
#ifdef OPENSUBDIV_HAS_CUDA #ifdef OPENSUBDIV_HAS_CUDA
} else if (g_kernel == kCUDA) { } else if (g_kernel == kCUDA) {
g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer,
Osd::CudaStencilTables, Osd::CudaStencilTable,
Osd::CudaEvaluator, Osd::CudaEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -383,7 +385,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
} else if (g_kernel == kDirectCompute) { } else if (g_kernel == kDirectCompute) {
static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache; static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache;
g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer, g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer,
Osd::D3D11StencilTables, Osd::D3D11StencilTable,
Osd::D3D11ComputeEvaluator, Osd::D3D11ComputeEvaluator,
Osd::D3D11PatchTable, Osd::D3D11PatchTable,
ID3D11DeviceContext>( ID3D11DeviceContext>(
@ -403,7 +405,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
if (g_endCap == kEndCapLegacyGregory) { if (g_endCap == kEndCapLegacyGregory) {
g_legacyGregoryPatchTable = g_legacyGregoryPatchTable =
Osd::D3D11LegacyGregoryPatchTable::Create( Osd::D3D11LegacyGregoryPatchTable::Create(
g_mesh->GetFarPatchTables(), g_pd3dDeviceContext); g_mesh->GetFarPatchTable(), g_pd3dDeviceContext);
} }
// compute model bounding // compute model bounding
@ -827,7 +829,7 @@ display() {
g_mesh->GetPatchTable()->GetPatchIndexBuffer(), DXGI_FORMAT_R32_UINT, 0); g_mesh->GetPatchTable()->GetPatchIndexBuffer(), DXGI_FORMAT_R32_UINT, 0);
// patch drawing // patch drawing
int patchCount[12]; // [Type] (see far/patchTables.h) int patchCount[12]; // [Type] (see far/patchTable.h)
int numTotalPatches = 0; int numTotalPatches = 0;
int numDrawCalls = 0; int numDrawCalls = 0;

View File

@ -50,9 +50,9 @@ GLFWmonitor* g_primary=0;
#include <far/gregoryBasis.h> #include <far/gregoryBasis.h>
#include <far/endCapGregoryBasisPatchFactory.h> #include <far/endCapGregoryBasisPatchFactory.h>
#include <far/patchTablesFactory.h> #include <far/patchTableFactory.h>
#include <far/stencilTables.h> #include <far/stencilTable.h>
#include <far/stencilTablesFactory.h> #include <far/stencilTableFactory.h>
#include <common/vtr_utils.h> #include <common/vtr_utils.h>
@ -212,7 +212,7 @@ createVertNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
if (refiner.IsUniform()) { if (refiner.IsUniform()) {
for (int i=0; i<maxlevel; ++i) { for (int i=0; i<maxlevel; ++i) {
firstvert += refiner.GetNumVertices(i); firstvert += refiner.GetLevel(i).GetNumVertices();
} }
} }
@ -225,7 +225,7 @@ createVertNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
} else { } else {
for (int level=0, vert=0; level<=refiner.GetMaxLevel(); ++level) { for (int level=0, vert=0; level<=refiner.GetMaxLevel(); ++level) {
for (int i=0; i<refiner.GetNumVertices(level); ++i, ++vert) { for (int i=0; i<refiner.GetLevel(level).GetNumVertices(); ++i, ++vert) {
snprintf(buf, 16, "%d", i); snprintf(buf, 16, "%d", i);
g_font->Print3D(vertexBuffer[vert].GetPos(), buf, 1); g_font->Print3D(vertexBuffer[vert].GetPos(), buf, 1);
} }
@ -245,16 +245,17 @@ createEdgeNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
firstvert = 0; firstvert = 0;
for (int i=0; i<maxlevel; ++i) { for (int i=0; i<maxlevel; ++i) {
firstvert += refiner.GetNumVertices(i); firstvert += refiner.GetLevel(i).GetNumVertices();
} }
OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel);
static char buf[16]; static char buf[16];
for (int i=0; i<refiner.GetNumEdges(maxlevel); ++i) { for (int i=0; i<refLastLevel.GetNumEdges(); ++i) {
Vertex center(0.0f, 0.0f, 0.0f); Vertex center(0.0f, 0.0f, 0.0f);
OpenSubdiv::Far::ConstIndexArray const verts = OpenSubdiv::Far::ConstIndexArray const verts = refLastLevel.GetEdgeVertices(i);
refiner.GetEdgeVertices(maxlevel, i);
assert(verts.size()==2); assert(verts.size()==2);
center.AddWithWeight(vertexBuffer[firstvert+verts[0]], 0.5f); center.AddWithWeight(vertexBuffer[firstvert+verts[0]], 0.5f);
@ -266,7 +267,7 @@ createEdgeNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
} }
if (sharpness) { if (sharpness) {
float sharpness = refiner.GetEdgeSharpness(maxlevel, i); float sharpness = refLastLevel.GetEdgeSharpness(i);
if (sharpness>0.0f) { if (sharpness>0.0f) {
snprintf(buf, 16, "%g", sharpness); snprintf(buf, 16, "%g", sharpness);
g_font->Print3D(center.GetPos(), buf, std::min(8,(int)sharpness+4)); g_font->Print3D(center.GetPos(), buf, std::min(8,(int)sharpness+4));
@ -289,15 +290,16 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
firstvert = 0; firstvert = 0;
for (int i=0; i<maxlevel; ++i) { for (int i=0; i<maxlevel; ++i) {
firstvert += refiner.GetNumVertices(i); firstvert += refiner.GetLevel(i).GetNumVertices();
} }
for (int face=0; face<refiner.GetNumFaces(maxlevel); ++face) { OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel);
for (int face=0; face<refLastLevel.GetNumFaces(); ++face) {
Vertex center(0.0f, 0.0f, 0.0f); Vertex center(0.0f, 0.0f, 0.0f);
OpenSubdiv::Far::ConstIndexArray const verts = OpenSubdiv::Far::ConstIndexArray const verts = refLastLevel.GetFaceVertices(face);
refiner.GetFaceVertices(maxlevel, face);
float weight = 1.0f / (float)verts.size(); float weight = 1.0f / (float)verts.size();
@ -310,19 +312,20 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
} }
} else { } else {
int maxlevel = refiner.GetMaxLevel(), int maxlevel = refiner.GetMaxLevel(),
// patch = refiner.GetNumFaces(0), // patch = refiner.GetLevel(0).GetNumFaces(),
firstvert = refiner.GetNumVertices(0); firstvert = refiner.GetLevel(0).GetNumVertices();
for (int level=1; level<=maxlevel; ++level) { for (int level=1; level<=maxlevel; ++level) {
int nfaces = refiner.GetNumFaces(level); OpenSubdiv::Far::TopologyLevel const & refLevel = refiner.GetLevel(level);
int nfaces = refLevel.GetNumFaces();
for (int face=0; face<nfaces; ++face /*, ++patch */) { for (int face=0; face<nfaces; ++face /*, ++patch */) {
Vertex center(0.0f, 0.0f, 0.0f); Vertex center(0.0f, 0.0f, 0.0f);
OpenSubdiv::Far::ConstIndexArray const verts = OpenSubdiv::Far::ConstIndexArray const verts = refLevel.GetFaceVertices(face);
refiner.GetFaceVertices(level, face);
float weight = 1.0f / (float)verts.size(); float weight = 1.0f / (float)verts.size();
@ -332,7 +335,7 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
snprintf(buf, 16, "%d", face); snprintf(buf, 16, "%d", face);
g_font->Print3D(center.GetPos(), buf, 2); g_font->Print3D(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 // generate display vert IDs for the selected Far patch
static void static void
createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables, createPatchNumbers(OpenSubdiv::Far::PatchTable const & patchTable,
std::vector<Vertex> const & vertexBuffer) { std::vector<Vertex> const & vertexBuffer) {
if (not g_currentPatch) if (not g_currentPatch)
@ -350,8 +353,8 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
patchArray = -1; patchArray = -1;
// Find PatchArray containing our patch // Find PatchArray containing our patch
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
int npatches = patchTables.GetNumPatches(array); int npatches = patchTable.GetNumPatches(array);
if (patchID >= npatches) { if (patchID >= npatches) {
patchID -= npatches; patchID -= npatches;
} else { } else {
@ -363,10 +366,10 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
return; return;
} }
g_currentPatchDesc = patchTables.GetPatchArrayDescriptor(patchArray); g_currentPatchDesc = patchTable.GetPatchArrayDescriptor(patchArray);
OpenSubdiv::Far::ConstIndexArray const cvs = OpenSubdiv::Far::ConstIndexArray const cvs =
patchTables.GetPatchVertices(patchArray, patchID); patchTable.GetPatchVertices(patchArray, patchID);
static char buf[16]; static char buf[16];
for (int i=0; i<cvs.size(); ++i) { for (int i=0; i<cvs.size(); ++i) {
@ -378,7 +381,7 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// generate display vert IDs for the selected Far FVar patch // generate display vert IDs for the selected Far FVar patch
static void static void
createFVarPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables, createFVarPatchNumbers(OpenSubdiv::Far::PatchTable const & patchTable,
std::vector<Vertex> const & fvarBuffer) { std::vector<Vertex> const & fvarBuffer) {
static int channel = 0; static int channel = 0;
@ -386,20 +389,20 @@ createFVarPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
int patch = g_currentPatch-1; int patch = g_currentPatch-1;
static char buf[16]; static char buf[16];
if (patch>=0 and patch<patchTables.GetNumPatchesTotal()) { if (patch>=0 and patch<patchTable.GetNumPatchesTotal()) {
OpenSubdiv::Far::PatchTables::PatchHandle handle; OpenSubdiv::Far::PatchTable::PatchHandle handle;
handle.patchIndex = patch; handle.patchIndex = patch;
OpenSubdiv::Far::ConstIndexArray const cvs = OpenSubdiv::Far::ConstIndexArray const cvs =
patchTables.GetFVarPatchValues(channel, handle); patchTable.GetFVarPatchValues(channel, handle);
for (int i=0; i<cvs.size(); ++i) { for (int i=0; i<cvs.size(); ++i) {
snprintf(buf, 16, "%d", i); snprintf(buf, 16, "%d", i);
g_font->Print3D(fvarBuffer[cvs[i]].GetPos(), buf, 2); g_font->Print3D(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 static void
createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner, createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
OpenSubdiv::Far::PatchTables const & patchTables, OpenSubdiv::Far::PatchTable const & patchTable,
std::vector<Vertex> const & fvarBuffer) { std::vector<Vertex> const & fvarBuffer) {
assert(not fvarBuffer.empty()); assert(not fvarBuffer.empty());
@ -420,14 +423,14 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
if (g_FarDrawFVarVerts) { if (g_FarDrawFVarVerts) {
GLMesh::Options options; GLMesh::Options options;
options.vertColorMode = GLMesh::VERTCOLOR_BY_LEVEL; 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) { if (g_FarDrawFVarPatches) {
// generate uniform tessellation for patches // generate uniform tessellation for patches
int tessFactor = g_FarDrawFVarPatchTess, int tessFactor = g_FarDrawFVarPatchTess,
npatches = patchTables.GetNumPatchesTotal(), npatches = patchTable.GetNumPatchesTotal(),
nvertsperpatch = (tessFactor) * (tessFactor), nvertsperpatch = (tessFactor) * (tessFactor),
nverts = npatches * nvertsperpatch; nverts = npatches * nvertsperpatch;
@ -439,7 +442,7 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
std::vector<Vertex> verts(nverts); std::vector<Vertex> verts(nverts);
memset(&verts[0], 0, verts.size()*sizeof(Vertex)); memset(&verts[0], 0, verts.size()*sizeof(Vertex));
OpenSubdiv::Far::PatchTables::PatchHandle handle; OpenSubdiv::Far::PatchTable::PatchHandle handle;
Vertex * vert = &verts[0]; Vertex * vert = &verts[0];
for (int patch=0; patch<npatches; ++patch) { for (int patch=0; patch<npatches; ++patch) {
@ -447,14 +450,14 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
for (int j=0; j<tessFactor; ++j, ++vert) { for (int j=0; j<tessFactor; ++j, ++vert) {
handle.patchIndex = patch; handle.patchIndex = patch;
// To be replaced with EvaluateBasis() for the appropriate channel: // To be replaced with EvaluateBasis() for the appropriate channel:
//patchTables.EvaluateFaceVarying(channel, handle, uvs[i], uvs[j], fvarBuffer, *vert); //patchTable.EvaluateFaceVarying(channel, handle, uvs[i], uvs[j], fvarBuffer, *vert);
} }
} }
} }
GLMesh::Options options; GLMesh::Options options;
options.edgeColorMode = GLMesh::EDGECOLOR_BY_PATCHTYPE; options.edgeColorMode = GLMesh::EDGECOLOR_BY_PATCHTYPE;
fvarWire.InitializeFVar(options, refiner, &patchTables, channel, tessFactor, (float *)(&verts[0])); fvarWire.InitializeFVar(options, refiner, &patchTable, channel, tessFactor, (float *)(&verts[0]));
} }
} }
@ -464,17 +467,17 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
static GLMesh gregoryWire; static GLMesh gregoryWire;
static void static void
createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables, createGregoryBasis(OpenSubdiv::Far::PatchTable const & patchTable,
std::vector<Vertex> const & vertexBuffer) { std::vector<Vertex> const & vertexBuffer) {
typedef OpenSubdiv::Far::PatchDescriptor PatchDescriptor; typedef OpenSubdiv::Far::PatchDescriptor PatchDescriptor;
int npatches = 0; int npatches = 0;
int patchArray = 0; int patchArray = 0;
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
if (patchTables.GetPatchArrayDescriptor(array).GetType()== if (patchTable.GetPatchArrayDescriptor(array).GetType()==
PatchDescriptor::GREGORY_BASIS) { PatchDescriptor::GREGORY_BASIS) {
npatches = patchTables.GetNumPatches(array); npatches = patchTable.GetNumPatches(array);
patchArray = array; patchArray = array;
break; break;
} }
@ -496,7 +499,7 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
* indices = &edgeindices[patch * 40]; * indices = &edgeindices[patch * 40];
OpenSubdiv::Far::ConstIndexArray const cvs = OpenSubdiv::Far::ConstIndexArray const cvs =
patchTables.GetPatchVertices(patchArray, patch); patchTable.GetPatchVertices(patchArray, patch);
for (int i=0; i<20; ++i) { for (int i=0; i<20; ++i) {
vpe[i] = 2; vpe[i] = 2;
@ -536,7 +539,7 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// generate display IDs for Far faces // generate display IDs for Far faces
static void static void
createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables, createPtexNumbers(OpenSubdiv::Far::PatchTable const & patchTable,
std::vector<Vertex> const & vertexBuffer) { std::vector<Vertex> const & vertexBuffer) {
typedef OpenSubdiv::Far::PatchDescriptor Descriptor; typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
@ -546,15 +549,15 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
static int regular[4] = {5, 6, 9, 10}, static int regular[4] = {5, 6, 9, 10},
gregory[4] = {0, 1, 2, 3}; 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 = OpenSubdiv::Far::ConstIndexArray const cvs =
patchTables.GetPatchVertices(array, patch); patchTable.GetPatchVertices(array, patch);
int * remap = 0; int * remap = 0;
switch (patchTables.GetPatchArrayDescriptor(array).GetType()) { switch (patchTable.GetPatchArrayDescriptor(array).GetType()) {
case Descriptor::REGULAR: remap = regular; break; case Descriptor::REGULAR: remap = regular; break;
case Descriptor::GREGORY: case Descriptor::GREGORY:
case Descriptor::GREGORY_BOUNDARY: case Descriptor::GREGORY_BOUNDARY:
@ -568,7 +571,7 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
center.AddWithWeight(vertexBuffer[cvs[remap[k]]], 0.25f); 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); g_font->Print3D(center.GetPos(), buf, 1);
} }
} }
@ -606,35 +609,35 @@ createFarGLMesh(Shape * shape, int maxlevel) {
int numTotalVerts = refiner->GetNumVerticesTotal(); int numTotalVerts = refiner->GetNumVerticesTotal();
// //
// Patch tables // Patch table
// //
std::vector<Vertex> fvarBuffer; std::vector<Vertex> fvarBuffer;
Far::PatchTables * patchTables = 0; Far::PatchTable * patchTable = 0;
bool createFVarWire = g_FarDrawFVarPatches or g_FarDrawFVarVerts; bool createFVarWire = g_FarDrawFVarPatches or g_FarDrawFVarVerts;
if (g_Adaptive) { if (g_Adaptive) {
Far::PatchTablesFactory::Options options; Far::PatchTableFactory::Options options;
options.generateFVarTables = createFVarWire; options.generateFVarTables = createFVarWire;
options.shareEndCapPatchPoints = false; options.shareEndCapPatchPoints = false;
patchTables = patchTable =
Far::PatchTablesFactory::Create(*refiner, options); Far::PatchTableFactory::Create(*refiner, options);
// increase vertex buffer for the additional endcap verts // increase vertex buffer for the additional endcap verts
if (patchTables->GetEndCapVertexStencilTables()) { if (patchTable->GetEndCapVertexStencilTable()) {
numTotalVerts += patchTables->GetEndCapVertexStencilTables()->GetNumStencils(); numTotalVerts += patchTable->GetEndCapVertexStencilTable()->GetNumStencils();
} }
g_numPatches = patchTables->GetNumPatchesTotal(); g_numPatches = patchTable->GetNumPatchesTotal();
g_maxValence = patchTables->GetMaxValence(); g_maxValence = patchTable->GetMaxValence();
if (createFVarWire) { if (createFVarWire) {
// interpolate fvar values // interpolate fvar values
//Far::FVarPatchTables const * fvarTables = //Far::FVarPatchTable const * fvarTable =
// patchTables->GetFVarPatchTables(); // patchTable->GetFVarPatchTable();
//assert(fvarTables); //assert(fvarTable);
int channel = 0; int channel = 0;
@ -642,7 +645,7 @@ createFarGLMesh(Shape * shape, int maxlevel) {
fvarBuffer.resize(refiner->GetNumFVarValuesTotal(channel), 0); fvarBuffer.resize(refiner->GetNumFVarValuesTotal(channel), 0);
Vertex * values = &fvarBuffer[0]; Vertex * values = &fvarBuffer[0];
int nCoarseValues = refiner->GetNumFVarValues(0); int nCoarseValues = refiner->GetLevel(0).GetNumFVarValues(channel);
for (int i=0; i<nCoarseValues; ++i) { for (int i=0; i<nCoarseValues; ++i) {
float const * ptr = &shape->uvs[i*2]; float const * ptr = &shape->uvs[i*2];
@ -672,29 +675,29 @@ createFarGLMesh(Shape * shape, int maxlevel) {
// //
// Stencil interpolation // Stencil interpolation
// //
Far::StencilTables const * stencilTables = 0; Far::StencilTable const * stencilTable = 0;
Far::StencilTablesFactory::Options options; Far::StencilTableFactory::Options options;
options.generateOffsets=true; options.generateOffsets=true;
options.generateIntermediateLevels=true; options.generateIntermediateLevels=true;
stencilTables = Far::StencilTablesFactory::Create(*refiner, options); stencilTable = Far::StencilTableFactory::Create(*refiner, options);
// append endpatch stencils if needed // append endpatch stencils if needed
if (patchTables and patchTables->GetEndCapVertexStencilTables()) { if (patchTable and patchTable->GetEndCapVertexStencilTable()) {
if (Far::StencilTables const * stencilTablesWithEndCap = if (Far::StencilTable const * stencilTableWithEndCap =
Far::StencilTablesFactory::AppendEndCapStencilTables( Far::StencilTableFactory::AppendEndCapStencilTable(
*refiner, stencilTables, *refiner, stencilTable,
patchTables->GetEndCapVertexStencilTables())) { patchTable->GetEndCapVertexStencilTable())) {
delete stencilTables; delete stencilTable;
stencilTables = stencilTablesWithEndCap; stencilTable = stencilTableWithEndCap;
} }
} }
// //
// apply stencils // apply stencils
// //
stencilTables->UpdateValues(verts, verts + ncoarseverts); stencilTable->UpdateValues(verts, verts + ncoarseverts);
delete stencilTables; delete stencilTable;
} else { } else {
// //
// TopologyRefiner interpolation // TopologyRefiner interpolation
@ -722,21 +725,21 @@ createFarGLMesh(Shape * shape, int maxlevel) {
createFaceNumbers(*refiner, vertexBuffer); createFaceNumbers(*refiner, vertexBuffer);
} }
if (g_FarDrawPtexIDs and patchTables) { if (g_FarDrawPtexIDs and patchTable) {
createPtexNumbers(*patchTables, vertexBuffer); createPtexNumbers(*patchTable, vertexBuffer);
} }
if (g_Adaptive) { if (g_Adaptive) {
createPatchNumbers(*patchTables, vertexBuffer); createPatchNumbers(*patchTable, vertexBuffer);
} }
if (g_Adaptive and g_FarDrawGregogyBasis) { if (g_Adaptive and g_FarDrawGregogyBasis) {
createGregoryBasis(*patchTables, vertexBuffer); createGregoryBasis(*patchTable, vertexBuffer);
} }
if (g_Adaptive and createFVarWire) { if (g_Adaptive and createFVarWire) {
createFVarPatches(*refiner, *patchTables, fvarBuffer); createFVarPatches(*refiner, *patchTable, fvarBuffer);
createFVarPatchNumbers(*patchTables, fvarBuffer); createFVarPatchNumbers(*patchTable, fvarBuffer);
} }
createEdgeNumbers(*refiner, vertexBuffer, g_FarDrawEdgeIDs!=0, g_FarDrawEdgeSharpness!=0); 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.edgeColorMode=g_Adaptive ? GLMesh::EDGECOLOR_BY_PATCHTYPE : GLMesh::EDGECOLOR_BY_SHARPNESS;
options.faceColorMode=g_Adaptive ? GLMesh::FACECOLOR_BY_PATCHTYPE :GLMesh::FACECOLOR_SOLID; 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) { if (g_Adaptive) {
g_far_glmesh.SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); g_far_glmesh.SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f);
} else { } else {
@ -759,7 +762,7 @@ createFarGLMesh(Shape * shape, int maxlevel) {
g_far_glmesh.InitializeDeviceBuffers(); g_far_glmesh.InitializeDeviceBuffers();
delete refiner; delete refiner;
delete patchTables; delete patchTable;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -243,10 +243,10 @@ GLMesh::Initialize(Options /* options */,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
GLMesh::Initialize(Options options, TopologyRefiner const & refiner, GLMesh::Initialize(Options options, TopologyRefiner const & refiner,
PatchTables const * patchTables, float const * vertexData) { PatchTable const * patchTable, float const * vertexData) {
if (patchTables) { if (patchTable) {
initializeBuffers(options, refiner, *patchTables, vertexData); initializeBuffers(options, refiner, *patchTable, vertexData);
} else { } else {
initializeBuffers(options, refiner, vertexData); initializeBuffers(options, refiner, vertexData);
} }
@ -265,15 +265,18 @@ GLMesh::initializeBuffers(Options options,
typedef OpenSubdiv::Far::ConstIndexArray IndexArray; typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
int maxlevel = refiner.GetMaxLevel(), int maxlevel = refiner.GetMaxLevel();
nverts = refiner.GetNumVertices(maxlevel),
nedges = refiner.GetNumEdges(maxlevel), OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel);
nfaces = refiner.GetNumFaces(maxlevel),
int nverts = refLastLevel.GetNumVertices(),
nedges = refLastLevel.GetNumEdges(),
nfaces = refLastLevel.GetNumFaces(),
firstvert = 0; firstvert = 0;
for (int i=0; i<maxlevel; ++i) { for (int i=0; i<maxlevel; ++i) {
firstvert += refiner.GetNumVertices(i); firstvert += refiner.GetLevel(i).GetNumVertices();
} }
float const * vertData = &vertexData[firstvert*3]; float const * vertData = &vertexData[firstvert*3];
@ -287,31 +290,33 @@ GLMesh::initializeBuffers(Options options,
// set colors // set colors
if (options.vertColorMode==VERTCOLOR_BY_LEVEL) { if (options.vertColorMode==VERTCOLOR_BY_LEVEL) {
for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) { for (int level=0, ofs=3; level<=maxlevel; ++level) {
for (int vert=0; vert<refiner.GetNumVertices(level); ++vert, ofs+=6) { for (int vert=0; vert<refiner.GetLevel(level).GetNumVertices(); ++vert, ofs+=6) {
setColorByLevel(level, &vbo[ofs]); setColorByLevel(level, &vbo[ofs]);
} }
} }
} else if (options.vertColorMode==VERTCOLOR_BY_SHARPNESS) { } else if (options.vertColorMode==VERTCOLOR_BY_SHARPNESS) {
for (int vert=0, ofs=3; vert<refiner.GetNumVertices(maxlevel); ++vert, ofs+=6) { for (int vert=0, ofs=3; vert<refLastLevel.GetNumVertices(); ++vert, ofs+=6) {
setColorBySharpness(refiner.GetVertexSharpness(maxlevel, vert), &vbo[ofs]); setColorBySharpness(refLastLevel.GetVertexSharpness(vert), &vbo[ofs]);
} }
} else if (options.vertColorMode==VERTCOLOR_BY_PARENT_TYPE) { } else if (options.vertColorMode==VERTCOLOR_BY_PARENT_TYPE) {
int ofs=3; int ofs=3;
if (maxlevel>0) { if (maxlevel>0) {
for (int vert=0; vert<refiner.GetNumFaces(maxlevel-1); ++vert, ofs+=6) { OpenSubdiv::Far::TopologyLevel const & refPrevLevel = refiner.GetLevel(maxlevel-1);
for (int vert=0; vert<refPrevLevel.GetNumFaces(); ++vert, ofs+=6) {
memcpy(&vbo[ofs], g_parentTypeColors[1], sizeof(float)*3); memcpy(&vbo[ofs], g_parentTypeColors[1], sizeof(float)*3);
} }
for (int vert=0; vert<refiner.GetNumEdges(maxlevel-1); ++vert, ofs+=6) { for (int vert=0; vert<refPrevLevel.GetNumEdges(); ++vert, ofs+=6) {
memcpy(&vbo[ofs], g_parentTypeColors[2], sizeof(float)*3); memcpy(&vbo[ofs], g_parentTypeColors[2], sizeof(float)*3);
} }
for (int vert=0; vert<refiner.GetNumVertices(maxlevel-1); ++vert, ofs+=6) { for (int vert=0; vert<refPrevLevel.GetNumVertices(); ++vert, ofs+=6) {
memcpy(&vbo[ofs], g_parentTypeColors[3], sizeof(float)*3); memcpy(&vbo[ofs], g_parentTypeColors[3], sizeof(float)*3);
} }
} else { } else {
for (int vert=0; vert<refiner.GetNumVertices(maxlevel); ++vert, ofs+=6) { for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert, ofs+=6) {
memcpy(&vbo[ofs], g_parentTypeColors[0], sizeof(float)*3); memcpy(&vbo[ofs], g_parentTypeColors[0], sizeof(float)*3);
} }
} }
@ -337,7 +342,7 @@ GLMesh::initializeBuffers(Options options,
eao[edge*2 ] = edge*2; eao[edge*2 ] = edge*2;
eao[edge*2+1] = edge*2+1; eao[edge*2+1] = edge*2+1;
IndexArray const verts = refiner.GetEdgeVertices(maxlevel, edge); IndexArray const verts = refLastLevel.GetEdgeVertices(edge);
float * v0 = &vbo[edge*2*6], float * v0 = &vbo[edge*2*6],
* v1 = v0+6; * v1 = v0+6;
@ -353,7 +358,7 @@ GLMesh::initializeBuffers(Options options,
setColorByLevel(maxlevel, v1+3); setColorByLevel(maxlevel, v1+3);
} else if (options.edgeColorMode==EDGECOLOR_BY_SHARPNESS) { } else if (options.edgeColorMode==EDGECOLOR_BY_SHARPNESS) {
float sharpness = refiner.GetEdgeSharpness(maxlevel, edge); float sharpness = refLastLevel.GetEdgeSharpness(edge);
setColorBySharpness(sharpness, v0+3); setColorBySharpness(sharpness, v0+3);
setColorBySharpness(sharpness, v1+3); setColorBySharpness(sharpness, v1+3);
} else { } else {
@ -372,7 +377,7 @@ GLMesh::initializeBuffers(Options options,
memcpy(&vbo[0], vertData, nverts*sizeof(float)*3); memcpy(&vbo[0], vertData, nverts*sizeof(float)*3);
int nfaceverts = refiner.GetNumFaceVertices(maxlevel); int nfaceverts = refLastLevel.GetNumFaceVertices();
std::vector<int> & eao = _eao[COMP_FACE]; std::vector<int> & eao = _eao[COMP_FACE];
eao.resize(nfaceverts); eao.resize(nfaceverts);
@ -381,7 +386,7 @@ GLMesh::initializeBuffers(Options options,
for (int face=0, ofs=0; face<nfaces; ++face) { for (int face=0, ofs=0; face<nfaces; ++face) {
IndexArray fverts = refiner.GetFaceVertices(maxlevel, face); IndexArray fverts = refLastLevel.GetFaceVertices(face);
for (int vert=0; vert<fverts.size(); ++vert) { for (int vert=0; vert<fverts.size(); ++vert) {
eao[ofs++] = fverts[vert]; eao[ofs++] = fverts[vert];
} }
@ -408,7 +413,7 @@ setEdge(std::vector<float> & vbo, int edge, float const * vertData, int v0, int
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner, 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); int nverts = refiner.GetNumFVarValuesTotal(channel);
@ -421,7 +426,7 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner,
if (options.vertColorMode==VERTCOLOR_BY_LEVEL) { if (options.vertColorMode==VERTCOLOR_BY_LEVEL) {
for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) { for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) {
for (int vert=0; vert<refiner.GetNumFVarValues(level); ++vert, ofs+=6) { for (int vert=0; vert<refiner.GetLevel(level).GetNumFVarValues(channel); ++vert, ofs+=6) {
assert(ofs<(int)vbo.size()); assert(ofs<(int)vbo.size());
setColorByLevel(level, &vbo[ofs]); setColorByLevel(level, &vbo[ofs]);
} }
@ -437,7 +442,7 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner,
if (tessFactor>0) { if (tessFactor>0) {
// edge color component ------------------------------ // edge color component ------------------------------
int npatches = patchTables->GetNumPatchesTotal(), int npatches = patchTable->GetNumPatchesTotal(),
nvertsperpatch = (tessFactor) * (tessFactor), nvertsperpatch = (tessFactor) * (tessFactor),
nedgesperpatch = (tessFactor-1) * (tessFactor*2+tessFactor-1), nedgesperpatch = (tessFactor-1) * (tessFactor*2+tessFactor-1),
//nverts = npatches * nvertsperpatch, //nverts = npatches * nvertsperpatch,
@ -475,14 +480,14 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner,
*ptr++ = tessFactor * (tessFactor-1) + i+1; *ptr++ = tessFactor * (tessFactor-1) + i+1;
} }
OpenSubdiv::Far::PatchTables::PatchHandle handle; OpenSubdiv::Far::PatchTable::PatchHandle handle;
for (int patch=0, offset=0; patch<npatches; ++patch) { for (int patch=0, offset=0; patch<npatches; ++patch) {
if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) { if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) {
handle.patchIndex = patch; handle.patchIndex = patch;
OpenSubdiv::Far::PatchDescriptor::Type type = OpenSubdiv::Far::PatchDescriptor::Type type =
patchTables->GetFVarPatchType(channel, handle); patchTable->GetFVarPatchType(channel, handle);
if (OpenSubdiv::Far::PatchDescriptor::IsAdaptive(type)) { if (OpenSubdiv::Far::PatchDescriptor::IsAdaptive(type)) {
color = getAdaptivePatchColor( color = getAdaptivePatchColor(
@ -591,7 +596,7 @@ getRingSize(OpenSubdiv::Far::PatchDescriptor desc) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner, GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
PatchTables const & patchTables, float const * vertexData) { PatchTable const & patchTable, float const * vertexData) {
int nverts = refiner.GetNumVerticesTotal(); int nverts = refiner.GetNumVerticesTotal();
@ -604,7 +609,7 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
if (options.vertColorMode==VERTCOLOR_BY_LEVEL) { if (options.vertColorMode==VERTCOLOR_BY_LEVEL) {
for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) { for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) {
for (int vert=0; vert<refiner.GetNumVertices(level); ++vert, ofs+=6) { for (int vert=0; vert<refiner.GetLevel(level).GetNumVertices(); ++vert, ofs+=6) {
assert(ofs<(int)vbo.size()); assert(ofs<(int)vbo.size());
setColorByLevel(level, &vbo[ofs]); setColorByLevel(level, &vbo[ofs]);
} }
@ -623,11 +628,11 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
int nedges = 0; int nedges = 0;
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) { for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
int ncvs = getRingSize(patchTables.GetPatchArrayDescriptor(array)); int ncvs = getRingSize(patchTable.GetPatchArrayDescriptor(array));
nedges += patchTables.GetNumPatches(array) * getNumEdges(ncvs); nedges += patchTable.GetNumPatches(array) * getNumEdges(ncvs);
} }
std::vector<float> & vbo = _vbo[COMP_EDGE]; std::vector<float> & vbo = _vbo[COMP_EDGE];
vbo.resize(nedges * 2 * 6); vbo.resize(nedges * 2 * 6);
@ -641,10 +646,10 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
float const * color=solidColor; 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 = OpenSubdiv::Far::PatchDescriptor desc =
patchTables.GetPatchArrayDescriptor(array); patchTable.GetPatchArrayDescriptor(array);
if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) { if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) {
color = getAdaptivePatchColor(desc); color = getAdaptivePatchColor(desc);
@ -652,10 +657,10 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
int ncvs = getRingSize(desc); int ncvs = getRingSize(desc);
for (int patch=0; patch<patchTables.GetNumPatches(array); ++patch) { for (int patch=0; patch<patchTable.GetNumPatches(array); ++patch) {
OpenSubdiv::Far::ConstIndexArray const cvs = OpenSubdiv::Far::ConstIndexArray const cvs =
patchTables.GetPatchVertices(array, patch); patchTable.GetPatchVertices(array, patch);
int const * edgeList=getEdgeList(ncvs); int const * edgeList=getEdgeList(ncvs);
@ -674,7 +679,7 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
{ // face color component ------------------------------ { // face color component ------------------------------
int nfaces = patchTables.GetNumPatchesTotal(); int nfaces = patchTable.GetNumPatchesTotal();
std::vector<float> & vbo = _vbo[COMP_FACE]; std::vector<float> & vbo = _vbo[COMP_FACE];
vbo.resize(nverts*3); vbo.resize(nverts*3);
@ -686,17 +691,17 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
_faceColors.resize(nfaces*4, 1.0f); _faceColors.resize(nfaces*4, 1.0f);
// default to solid color // 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 = OpenSubdiv::Far::PatchDescriptor desc =
patchTables.GetPatchArrayDescriptor(array); patchTable.GetPatchArrayDescriptor(array);
//int ncvs = getRingSize(desc); //int ncvs = getRingSize(desc);
for (int patch=0; patch<patchTables.GetNumPatches(array); ++patch, ++face) { for (int patch=0; patch<patchTable.GetNumPatches(array); ++patch, ++face) {
OpenSubdiv::Far::ConstIndexArray const cvs = OpenSubdiv::Far::ConstIndexArray const cvs =
patchTables.GetPatchVertices(array, patch); patchTable.GetPatchVertices(array, patch);
if (desc.GetType()==Descriptor::REGULAR) { if (desc.GetType()==Descriptor::REGULAR) {
eao[face*4 ] = cvs[ 5]; eao[face*4 ] = cvs[ 5];

View File

@ -27,7 +27,7 @@
#include <common/vtr_utils.h> #include <common/vtr_utils.h>
#include <common/hbr_utils.h> #include <common/hbr_utils.h>
#include <far/patchTables.h> #include <far/patchTable.h>
#include "../common/glUtils.h" #include "../common/glUtils.h"
@ -193,13 +193,13 @@ public:
// Far initialization // Far initialization
typedef OpenSubdiv::Far::TopologyRefiner TopologyRefiner; typedef OpenSubdiv::Far::TopologyRefiner TopologyRefiner;
typedef OpenSubdiv::Far::PatchTables PatchTables; typedef OpenSubdiv::Far::PatchTable PatchTable;
void Initialize(Options options, TopologyRefiner const & refiner, 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, 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(); void InitializeDeviceBuffers();
@ -229,7 +229,7 @@ private:
float const * vertexData); float const * vertexData);
void initializeBuffers(Options options, TopologyRefiner const & refiner, void initializeBuffers(Options options, TopologyRefiner const & refiner,
PatchTables const & patchTables, float const * vertexData); PatchTable const & patchTable, float const * vertexData);
void clearBuffers(); void clearBuffers();

View File

@ -50,8 +50,8 @@ GLFWmonitor* g_primary=0;
#include <far/gregoryBasis.h> #include <far/gregoryBasis.h>
#include <far/endCapGregoryBasisPatchFactory.h> #include <far/endCapGregoryBasisPatchFactory.h>
#include <far/topologyRefiner.h> #include <far/topologyRefiner.h>
#include <far/stencilTablesFactory.h> #include <far/stencilTableFactory.h>
#include <far/patchTablesFactory.h> #include <far/patchTableFactory.h>
#include <far/patchMap.h> #include <far/patchMap.h>
#include <far/error.h> #include <far/error.h>
@ -60,6 +60,7 @@ GLFWmonitor* g_primary=0;
#include "../common/stopwatch.h" #include "../common/stopwatch.h"
#include "../common/simple_math.h" #include "../common/simple_math.h"
#include "../common/glHud.h" #include "../common/glHud.h"
#include "../common/glUtils.h"
#include "init_shapes.h" #include "init_shapes.h"
#include "particles.h" #include "particles.h"
@ -71,10 +72,6 @@ GLFWmonitor* g_primary=0;
#include <sstream> #include <sstream>
#include <stdlib.h> #include <stdlib.h>
#ifdef OPENSUBDIV_HAS_OPENMP
#include <omp.h>
#endif
using namespace OpenSubdiv; using namespace OpenSubdiv;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -91,9 +88,11 @@ std::vector<float> g_coarseEdgeSharpness;
std::vector<float> g_coarseVertexSharpness; std::vector<float> g_coarseVertexSharpness;
enum DrawMode { kRANDOM=0, enum DrawMode { kRANDOM=0,
kUV=1, kUV,
kVARYING=2, kVARYING,
kFACEVARYING=3 }; kNORMAL,
kSHADE,
kFACEVARYING };
int g_running = 1, int g_running = 1,
g_width = 1024, g_width = 1024,
@ -146,6 +145,18 @@ GLuint g_cageEdgeVAO = 0,
GLhud g_hud; 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 static void
createRandomColors(int nverts, int stride, float * colors) { createRandomColors(int nverts, int stride, float * colors) {
@ -167,22 +178,24 @@ createCoarseMesh(OpenSubdiv::Far::TopologyRefiner const & refiner) {
typedef OpenSubdiv::Far::ConstIndexArray IndexArray; typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
int nedges = refiner.GetNumEdges(0), OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
nverts = refiner.GetNumVertices(0);
int nedges = refBaseLevel.GetNumEdges(),
nverts = refBaseLevel.GetNumVertices();
g_coarseEdges.resize(nedges*2); g_coarseEdges.resize(nedges*2);
g_coarseEdgeSharpness.resize(nedges); g_coarseEdgeSharpness.resize(nedges);
g_coarseVertexSharpness.resize(nverts); g_coarseVertexSharpness.resize(nverts);
for(int i=0; i<nedges; ++i) { for(int i=0; i<nedges; ++i) {
IndexArray verts = refiner.GetEdgeVertices(0, i); IndexArray verts = refBaseLevel.GetEdgeVertices(i);
g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2 ]=verts[0];
g_coarseEdges[i*2+1]=verts[1]; g_coarseEdges[i*2+1]=verts[1];
g_coarseEdgeSharpness[i]=refiner.GetEdgeSharpness(0, i); g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
} }
for(int i=0; i<nverts; ++i) { for(int i=0; i<nverts; ++i) {
g_coarseVertexSharpness[i]=refiner.GetVertexSharpness(0, i); g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
} }
// assign a randomly generated color for each vertex ofthe mesh // assign a randomly generated color for each vertex ofthe mesh
@ -193,26 +206,28 @@ createCoarseMesh(OpenSubdiv::Far::TopologyRefiner const & refiner) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Far::TopologyRefiner * g_topologyRefiner = 0; Far::TopologyRefiner * g_topologyRefiner = 0;
Osd::CpuVertexBuffer * g_vertexData = 0, Far::StencilTable const * g_vertexStencils = NULL;
* g_varyingData = 0; Far::StencilTable const * g_varyingStencils = NULL;
Far::StencilTables const * g_vertexStencils = NULL; Far::PatchTable const * g_patchTable = NULL;
Far::StencilTables const * g_varyingStencils = NULL;
Far::PatchTables const * g_patchTables = NULL;
Far::PatchMap const * g_patchMap = NULL; Far::PatchMap const * g_patchMap = NULL;
Osd::PatchCoordArray g_patchCoords; std::vector<Osd::PatchCoord> g_patchCoords;
Osd::VertexBufferDescriptor g_idesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 3 ), Osd::VertexBufferDescriptor g_idesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 3),
g_odesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 6 ), g_odesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 6),
g_vdesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 6 ), g_vdesc(/*offset*/ 3, /*legnth*/ 3, /*stride*/ 6),
g_fvidesc( /*offset*/ 0, /*legnth*/ 2, /*stride*/ 2 ), g_duDesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 6),
g_fvodesc( /*offset*/ 3, /*legnth*/ 2, /*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, // output vertex data (limit locations)
* g_dQs=0, Osd::CpuGLVertexBuffer * g_outVertexData = NULL;
* g_dQt=0; Osd::CpuGLVertexBuffer * g_outDerivatives = NULL;
STParticles * g_particles=0; STParticles * g_particles=0;
@ -245,7 +260,7 @@ updateGeom() {
if (! g_topologyRefiner) return; if (! g_topologyRefiner) return;
// note that for patch eval we need coarse+refined combined buffer. // 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::CpuEvaluator::EvalStencils(g_vertexData,
Osd::VertexBufferDescriptor(0, 3, 3), Osd::VertexBufferDescriptor(0, 3, 3),
g_vertexData, g_vertexData,
@ -280,7 +295,7 @@ updateGeom() {
g_patchCoords.clear(); g_patchCoords.clear();
for (int i = 0; i < g_particles->GetNumParticles(); ++i) { for (int i = 0; i < g_particles->GetNumParticles(); ++i) {
STParticles::Position const &position = g_particles->GetPositions()[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); g_patchMap->FindPatch(position.ptexIndex, position.s, position.t);
if (handle) { if (handle) {
g_patchCoords.push_back(Osd::PatchCoord( g_patchCoords.push_back(Osd::PatchCoord(
@ -289,20 +304,44 @@ updateGeom() {
} }
// Evaluate the positions of the samples on the limit surface // Evaluate the positions of the samples on the limit surface
g_nsamplesFound = Osd::CpuEvaluator::EvalPatches(g_vertexData, g_idesc, if (g_drawMode == kNORMAL || g_drawMode == kSHADE) {
g_Q, g_odesc, // evaluate positions and derivatives
g_patchCoords, g_nsamplesFound = Osd::CpuEvaluator::EvalPatches(
g_patchTables, NULL); g_vertexData, g_idesc,
g_outVertexData, g_odesc,
// varying g_outDerivatives, g_duDesc,
if (g_drawMode == kVARYING) { g_outDerivatives, g_dvDesc,
Osd::CpuEvaluator::EvalPatches(g_varyingData, g_idesc, (int)g_patchCoords.size(),
g_Q, g_vdesc, &g_patchCoords[0],
g_patchCoords, g_patchTable, NULL);
g_patchTables, 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(); s.Stop();
@ -349,46 +388,46 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
Far::TopologyRefiner::AdaptiveOptions options(level); Far::TopologyRefiner::AdaptiveOptions options(level);
g_topologyRefiner->RefineAdaptive(options); 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 // vertices after they have been re-posed (both for vertex & varying
// interpolation) // interpolation)
Far::StencilTablesFactory::Options soptions; Far::StencilTableFactory::Options soptions;
soptions.generateOffsets=true; soptions.generateOffsets=true;
soptions.generateIntermediateLevels=true; soptions.generateIntermediateLevels=true;
Far::StencilTables const * vertexStencils = Far::StencilTable const * vertexStencils =
Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions); Far::StencilTableFactory::Create(*g_topologyRefiner, soptions);
soptions.interpolationMode = Far::StencilTablesFactory::INTERPOLATE_VARYING; soptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_VARYING;
Far::StencilTables const * varyingStencils = Far::StencilTable const * varyingStencils =
Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions); Far::StencilTableFactory::Create(*g_topologyRefiner, soptions);
// Generate bi-cubic patch tables for the limit surface // Generate bi-cubic patch table for the limit surface
Far::PatchTablesFactory::Options poptions; Far::PatchTableFactory::Options poptions;
poptions.SetEndCapType( poptions.SetEndCapType(
Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS); Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
Far::PatchTables const * patchTables = Far::PatchTable const * patchTable =
Far::PatchTablesFactory::Create(*g_topologyRefiner, poptions); Far::PatchTableFactory::Create(*g_topologyRefiner, poptions);
// append endcap stencils // append endcap stencils
if (Far::StencilTables const *endCapVertexStencilTables = if (Far::StencilTable const *endCapVertexStencilTable =
patchTables->GetEndCapVertexStencilTables()) { patchTable->GetEndCapVertexStencilTable()) {
Far::StencilTables const *tables = Far::StencilTable const *table =
Far::StencilTablesFactory::AppendEndCapStencilTables( Far::StencilTableFactory::AppendEndCapStencilTable(
*g_topologyRefiner, *g_topologyRefiner,
vertexStencils, endCapVertexStencilTables); vertexStencils, endCapVertexStencilTable);
delete vertexStencils; delete vertexStencils;
vertexStencils = tables; vertexStencils = table;
} }
if (Far::StencilTables const *endCapVaryingStencilTables = if (Far::StencilTable const *endCapVaryingStencilTable =
patchTables->GetEndCapVaryingStencilTables()) { patchTable->GetEndCapVaryingStencilTable()) {
Far::StencilTables const *tables = Far::StencilTable const *table =
Far::StencilTablesFactory::AppendEndCapStencilTables( Far::StencilTableFactory::AppendEndCapStencilTable(
*g_topologyRefiner, *g_topologyRefiner,
varyingStencils, endCapVaryingStencilTables); varyingStencils, endCapVaryingStencilTable);
delete varyingStencils; delete varyingStencils;
varyingStencils = tables; varyingStencils = table;
} }
// total number of vertices = coarse verts + refined verts + gregory basis verts // 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; if (g_varyingStencils) delete g_varyingStencils;
g_varyingStencils = varyingStencils; g_varyingStencils = varyingStencils;
if (g_patchTables) delete g_patchTables; if (g_patchTable) delete g_patchTable;
g_patchTables = patchTables; g_patchTable = patchTable;
// Create a far patch map // Create a far patch map
if (g_patchMap) delete g_patchMap; 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 { // 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) // Create output buffers for the limit samples (position & tangents)
delete g_Q; delete g_outVertexData;
g_Q = Osd::CpuGLVertexBuffer::Create(6, g_nparticles); g_outVertexData = Osd::CpuGLVertexBuffer::Create(6, g_nparticles);
memset( g_Q->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float)); memset(g_outVertexData->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float));
if (g_drawMode==kRANDOM) { if (g_drawMode==kRANDOM) {
createRandomColors(g_nparticles, 6, g_Q->BindCpuBuffer()+3); createRandomColors(g_nparticles, 6, g_outVertexData->BindCpuBuffer()+3);
} }
delete g_dQs; delete g_outDerivatives;
g_dQs = Osd::CpuGLVertexBuffer::Create(3,g_nparticles); g_outDerivatives = Osd::CpuGLVertexBuffer::Create(6, g_nparticles);
memset( g_dQs->BindCpuBuffer(), 0, g_nparticles*3*sizeof(float)); memset(g_outDerivatives->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float));
delete g_dQt;
g_dQt = Osd::CpuGLVertexBuffer::Create(3,g_nparticles);
memset( g_dQt->BindCpuBuffer(), 0, g_nparticles*3*sizeof(float));
} }
updateGeom(); 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 static void
checkGLErrors(std::string const & where = "") { 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 static bool
linkDefaultProgram() { linkDefaultProgram() {
@ -497,31 +503,47 @@ linkDefaultProgram() {
GLSL_VERSION_DEFINE GLSL_VERSION_DEFINE
"in vec3 position;\n" "in vec3 position;\n"
"in vec3 color;\n" "in vec3 color;\n"
"in vec3 tangentU;\n"
"in vec3 tangentV;\n"
"out vec4 fragColor;\n" "out vec4 fragColor;\n"
"uniform mat4 ModelViewProjectionMatrix;\n" "out vec3 normal;\n"
"uniform mat4 ModelViewMatrix;\n"
"uniform mat4 ProjectionMatrix;\n"
"void main() {\n" "void main() {\n"
" fragColor = vec4(color, 1);\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" " vec4(position, 1);\n"
"}\n"; "}\n";
static const char *fsSrc = static const char *fsSrc =
GLSL_VERSION_DEFINE GLSL_VERSION_DEFINE
"in vec4 fragColor;\n" "in vec4 fragColor;\n"
"in vec3 normal;\n"
"uniform int DrawMode;\n"
"out vec4 color;\n" "out vec4 color;\n"
"void main() {\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"; "}\n";
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vsSrc); GLuint vertexShader = GLUtils::CompileShader(GL_VERTEX_SHADER, vsSrc);
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fsSrc); GLuint fragmentShader = GLUtils::CompileShader(GL_FRAGMENT_SHADER, fsSrc);
glAttachShader(program, vertexShader); glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader); glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "position"); glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "color"); glBindAttribLocation(program, 1, "color");
glBindAttribLocation(program, 2, "tangentU");
glBindAttribLocation(program, 3, "tangentV");
glBindFragDataLocation(program, 0, "color"); glBindFragDataLocation(program, 0, "color");
glLinkProgram(program); glLinkProgram(program);
@ -539,10 +561,16 @@ linkDefaultProgram() {
} }
g_defaultProgram.program = program; g_defaultProgram.program = program;
g_defaultProgram.uniformModelViewProjectionMatrix = g_defaultProgram.uniformModelViewMatrix =
glGetUniformLocation(program, "ModelViewProjectionMatrix"); glGetUniformLocation(program, "ModelViewMatrix");
g_defaultProgram.uniformProjectionMatrix =
glGetUniformLocation(program, "ProjectionMatrix");
g_defaultProgram.uniformDrawMode =
glGetUniformLocation(program, "DrawMode");
g_defaultProgram.attrPosition = glGetAttribLocation(program, "position"); g_defaultProgram.attrPosition = glGetAttribLocation(program, "position");
g_defaultProgram.attrColor = glGetAttribLocation(program, "color"); g_defaultProgram.attrColor = glGetAttribLocation(program, "color");
g_defaultProgram.attrTangentU = glGetAttribLocation(program, "tangentU");
g_defaultProgram.attrTangentV = glGetAttribLocation(program, "tangentV");
return true; return true;
} }
@ -562,8 +590,11 @@ static void
drawCageEdges() { drawCageEdges() {
glUseProgram(g_defaultProgram.program); glUseProgram(g_defaultProgram.program);
glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix,
1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); 1, GL_FALSE, g_transformData.ModelViewMatrix);
glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix,
1, GL_FALSE, g_transformData.ProjectionMatrix);
glUniform1i(g_defaultProgram.uniformDrawMode, 0);
std::vector<float> vbo; std::vector<float> vbo;
vbo.reserve(g_coarseEdges.size() * 6); vbo.reserve(g_coarseEdges.size() * 6);
@ -588,6 +619,8 @@ drawCageEdges() {
glEnableVertexAttribArray(g_defaultProgram.attrPosition); glEnableVertexAttribArray(g_defaultProgram.attrPosition);
glEnableVertexAttribArray(g_defaultProgram.attrColor); glEnableVertexAttribArray(g_defaultProgram.attrColor);
glDisableVertexAttribArray(g_defaultProgram.attrTangentU);
glDisableVertexAttribArray(g_defaultProgram.attrTangentV);
glVertexAttribPointer(g_defaultProgram.attrPosition, glVertexAttribPointer(g_defaultProgram.attrPosition,
3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
glVertexAttribPointer(g_defaultProgram.attrColor, glVertexAttribPointer(g_defaultProgram.attrColor,
@ -604,8 +637,11 @@ static void
drawCageVertices() { drawCageVertices() {
glUseProgram(g_defaultProgram.program); glUseProgram(g_defaultProgram.program);
glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix,
1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); 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; int numPoints = (int)g_positions.size()/3;
std::vector<float> vbo; std::vector<float> vbo;
@ -642,6 +678,8 @@ drawCageVertices() {
glEnableVertexAttribArray(g_defaultProgram.attrPosition); glEnableVertexAttribArray(g_defaultProgram.attrPosition);
glEnableVertexAttribArray(g_defaultProgram.attrColor); glEnableVertexAttribArray(g_defaultProgram.attrColor);
glDisableVertexAttribArray(g_defaultProgram.attrTangentU);
glDisableVertexAttribArray(g_defaultProgram.attrTangentV);
glVertexAttribPointer(g_defaultProgram.attrPosition, glVertexAttribPointer(g_defaultProgram.attrPosition,
3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
glVertexAttribPointer(g_defaultProgram.attrColor, glVertexAttribPointer(g_defaultProgram.attrColor,
@ -658,19 +696,43 @@ drawCageVertices() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void static void
drawSamples() { drawSamples() {
glUseProgram(g_defaultProgram.program); glUseProgram(g_defaultProgram.program);
glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix,
1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); 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); 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); glPointSize(2.0f);
glDrawArrays(GL_POINTS, 0, g_nparticles); glDrawArrays(GL_POINTS, 0, g_nparticles);
glPointSize(1.0f); glPointSize(1.0f);
glDisableVertexAttribArray(g_defaultProgram.attrPosition);
glDisableVertexAttribArray(g_defaultProgram.attrColor);
glDisableVertexAttribArray(g_defaultProgram.attrTangentU);
glDisableVertexAttribArray(g_defaultProgram.attrTangentV);
glBindVertexArray(0); glBindVertexArray(0);
glUseProgram(0); glUseProgram(0);
@ -728,7 +790,8 @@ display() {
g_fpsTimer.Start(); g_fpsTimer.Start();
g_hud.DrawString(10, -150, "Particle Speed ([) (]): %.1f", g_particles->GetSpeed()); 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, -100, "Compute : %.3f ms", g_computeTime);
g_hud.DrawString(10, -80, "Eval : %.3f ms", g_evalTime * 1000.f); g_hud.DrawString(10, -80, "Eval : %.3f ms", g_evalTime * 1000.f);
g_hud.DrawString(10, -60, "GPU Draw : %.3f ms", drawGpuTime); 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, "Random", kRANDOM, g_drawMode==kRANDOM);
g_hud.AddPullDownButton(shading_pulldown, "(u,v)", kUV, g_drawMode==kUV); 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, "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); g_hud.AddPullDownButton(shading_pulldown, "FaceVarying", kFACEVARYING, g_drawMode==kFACEVARYING);
for (int i = 1; i < 11; ++i) { for (int i = 1; i < 11; ++i) {

View File

@ -70,14 +70,15 @@ STParticles::STParticles(Refiner const & refiner, int nparticles, bool centered)
{ // initialize topology adjacency { // initialize topology adjacency
_adjacency.resize(nptexfaces); _adjacency.resize(nptexfaces);
int nfaces = refiner.GetNumFaces(0), OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
int nfaces = refBaseLevel.GetNumFaces(),
adjfaces[4], adjfaces[4],
adjedges[4]; adjedges[4];
for (int face=0, ptexface=0; face<nfaces; ++face) { for (int face=0, ptexface=0; face<nfaces; ++face) {
OpenSubdiv::Far::ConstIndexArray fverts = OpenSubdiv::Far::ConstIndexArray fverts = refBaseLevel.GetFaceVertices(face);
refiner.GetFaceVertices(0, face);
if (fverts.size()==4) { if (fverts.size()==4) {
ptexIndices.GetAdjacency(refiner, face, 0, adjfaces, adjedges); ptexIndices.GetAdjacency(refiner, face, 0, adjfaces, adjedges);

View File

@ -167,11 +167,11 @@ struct FVarData
glDeleteTextures(1, &textureBuffer); glDeleteTextures(1, &textureBuffer);
textureBuffer = 0; textureBuffer = 0;
} }
void Create(OpenSubdiv::Far::PatchTables const *patchTables, void Create(OpenSubdiv::Far::PatchTable const *patchTable,
int fvarWidth, std::vector<float> const & fvarSrcData) { int fvarWidth, std::vector<float> const & fvarSrcData) {
Release(); Release();
OpenSubdiv::Far::ConstIndexArray indices = OpenSubdiv::Far::ConstIndexArray indices =
patchTables->GetFVarPatchesValues(0); patchTable->GetFVarPatchesValues(0);
// expand fvardata to per-patch array // expand fvardata to per-patch array
std::vector<float> data; std::vector<float> data;
@ -280,13 +280,15 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner const & refiner,
typedef OpenSubdiv::Far::ConstIndexArray IndexArray; typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
// calc normal vectors // calc normal vectors
int nverts = (int)pos.size()/3; int nverts = (int)pos.size()/3;
int nfaces = refiner.GetNumFaces(0); int nfaces = refBaseLevel.GetNumFaces();
for (int face = 0; face < nfaces; ++face) { for (int face = 0; face < nfaces; ++face) {
IndexArray fverts = refiner.GetFaceVertices(0, face); IndexArray fverts = refBaseLevel.GetFaceVertices(face);
assert(fverts.size()>=2); assert(fverts.size()>=2);
@ -366,22 +368,23 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark)
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)); OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
int nedges = refiner->GetNumEdges(0), OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
nverts = refiner->GetNumVertices(0); int nedges = refBaseLevel.GetNumEdges(),
nverts = refBaseLevel.GetNumVertices();
g_coarseEdges.resize(nedges*2); g_coarseEdges.resize(nedges*2);
g_coarseEdgeSharpness.resize(nedges); g_coarseEdgeSharpness.resize(nedges);
g_coarseVertexSharpness.resize(nverts); g_coarseVertexSharpness.resize(nverts);
for(int i=0; i<nedges; ++i) { for(int i=0; i<nedges; ++i) {
IndexArray verts = refiner->GetEdgeVertices(0, i); IndexArray verts = refBaseLevel.GetEdgeVertices(i);
g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2 ]=verts[0];
g_coarseEdges[i*2+1]=verts[1]; g_coarseEdges[i*2+1]=verts[1];
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
} }
for(int i=0; i<nverts; ++i) { for(int i=0; i<nverts; ++i) {
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i); g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
} }
g_orgPositions=shape->verts; g_orgPositions=shape->verts;
@ -404,7 +407,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark)
delete g_mesh; delete g_mesh;
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
OpenSubdiv::Far::StencilTables, OpenSubdiv::Far::StencilTable,
OpenSubdiv::Osd::CpuEvaluator, OpenSubdiv::Osd::CpuEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, refiner,
@ -417,7 +420,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark)
InterpolateFVarData(*refiner, *shape, fvarData); InterpolateFVarData(*refiner, *shape, fvarData);
// set fvardata to texture buffer // set fvardata to texture buffer
g_fvarData.Create(g_mesh->GetFarPatchTables(), g_fvarData.Create(g_mesh->GetFarPatchTable(),
shape->GetFVarWidth(), fvarData); shape->GetFVarWidth(), fvarData);
delete shape; delete shape;

View File

@ -232,7 +232,7 @@ createOsdMesh(std::string const &kernel,
{ {
if (kernel == "CPU") { if (kernel == "CPU") {
return new Osd::Mesh<Osd::CpuGLVertexBuffer, return new Osd::Mesh<Osd::CpuGLVertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::CpuEvaluator, Osd::CpuEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -242,7 +242,7 @@ createOsdMesh(std::string const &kernel,
#ifdef OPENSUBDIV_HAS_OPENMP #ifdef OPENSUBDIV_HAS_OPENMP
} else if (kernel == "OPENMP") { } else if (kernel == "OPENMP") {
return new Osd::Mesh<Osd::CpuGLVertexBuffer, return new Osd::Mesh<Osd::CpuGLVertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::OmpEvaluator, Osd::OmpEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -253,7 +253,7 @@ createOsdMesh(std::string const &kernel,
#ifdef OPENSUBDIV_HAS_TBB #ifdef OPENSUBDIV_HAS_TBB
} else if (kernel == "TBB") { } else if (kernel == "TBB") {
return new Osd::Mesh<Osd::CpuGLVertexBuffer, return new Osd::Mesh<Osd::CpuGLVertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::TbbEvaluator, Osd::TbbEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -264,7 +264,7 @@ createOsdMesh(std::string const &kernel,
#ifdef OPENSUBDIV_HAS_OPENCL #ifdef OPENSUBDIV_HAS_OPENCL
} else if(kernel == "CL") { } else if(kernel == "CL") {
return new Osd::Mesh<Osd::CLGLVertexBuffer, return new Osd::Mesh<Osd::CLGLVertexBuffer,
Osd::CLStencilTables, Osd::CLStencilTable,
Osd::CLEvaluator, Osd::CLEvaluator,
Osd::GLPatchTable, Osd::GLPatchTable,
CLDeviceContext>( CLDeviceContext>(
@ -278,7 +278,7 @@ createOsdMesh(std::string const &kernel,
#ifdef OPENSUBDIV_HAS_CUDA #ifdef OPENSUBDIV_HAS_CUDA
} else if(kernel == "CUDA") { } else if(kernel == "CUDA") {
return new Osd::Mesh<Osd::CudaGLVertexBuffer, return new Osd::Mesh<Osd::CudaGLVertexBuffer,
Osd::CudaStencilTables, Osd::CudaStencilTable,
Osd::CudaEvaluator, Osd::CudaEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -289,7 +289,7 @@ createOsdMesh(std::string const &kernel,
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
} else if(kernel == "XFB") { } else if(kernel == "XFB") {
return new Osd::Mesh<Osd::GLVertexBuffer, return new Osd::Mesh<Osd::GLVertexBuffer,
Osd::GLStencilTablesTBO, Osd::GLStencilTableTBO,
Osd::GLXFBEvaluator, Osd::GLXFBEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -300,7 +300,7 @@ createOsdMesh(std::string const &kernel,
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
} else if(kernel == "GLSL") { } else if(kernel == "GLSL") {
return new Osd::Mesh<Osd::GLVertexBuffer, return new Osd::Mesh<Osd::GLVertexBuffer,
Osd::GLStencilTablesSSBO, Osd::GLStencilTableSSBO,
Osd::GLComputeEvaluator, Osd::GLComputeEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,

View File

@ -238,7 +238,7 @@ createOsdMesh() {
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive); bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
OpenSubdiv::Far::StencilTables, OpenSubdiv::Far::StencilTable,
OpenSubdiv::Osd::CpuEvaluator, OpenSubdiv::Osd::CpuEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, 3, 0, g_level, bits); refiner, 3, 0, g_level, bits);

View File

@ -322,13 +322,15 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner * refiner,
typedef OpenSubdiv::Far::ConstIndexArray IndexArray; typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
// calc normal vectors // calc normal vectors
int nverts = refiner->GetNumVertices(0), int nverts = refBaseLevel.GetNumVertices(),
nfaces = refiner->GetNumFaces(0); nfaces = refBaseLevel.GetNumFaces();
for (int face = 0; face < nfaces; ++face) { 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], float const * p0 = &pos[fverts[0]*3],
* p1 = &pos[fverts[1]*3], * p1 = &pos[fverts[1]*3],
@ -907,10 +909,12 @@ createOsdMesh(int level, int kernel) {
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
// create cage edge index // create cage edge index
int nedges = refiner->GetNumEdges(0); OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
int nedges = refBaseLevel.GetNumEdges();
std::vector<int> edgeIndices(nedges*2); std::vector<int> edgeIndices(nedges*2);
for(int i=0; i<nedges; ++i) { for(int i=0; i<nedges; ++i) {
IndexArray verts = refiner->GetEdgeVertices(0, i); IndexArray verts = refBaseLevel.GetEdgeVertices(i);
edgeIndices[i*2 ]=verts[0]; edgeIndices[i*2 ]=verts[0];
edgeIndices[i*2+1]=verts[1]; edgeIndices[i*2+1]=verts[1];
} }
@ -935,7 +939,7 @@ createOsdMesh(int level, int kernel) {
if (kernel == kCPU) { if (kernel == kCPU) {
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
OpenSubdiv::Far::StencilTables, OpenSubdiv::Far::StencilTable,
OpenSubdiv::Osd::CpuEvaluator, OpenSubdiv::Osd::CpuEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, refiner,
@ -945,7 +949,7 @@ createOsdMesh(int level, int kernel) {
#ifdef OPENSUBDIV_HAS_OPENMP #ifdef OPENSUBDIV_HAS_OPENMP
} else if (kernel == kOPENMP) { } else if (kernel == kOPENMP) {
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
OpenSubdiv::Far::StencilTables, OpenSubdiv::Far::StencilTable,
OpenSubdiv::Osd::OmpEvaluator, OpenSubdiv::Osd::OmpEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, refiner,
@ -956,7 +960,7 @@ createOsdMesh(int level, int kernel) {
#ifdef OPENSUBDIV_HAS_TBB #ifdef OPENSUBDIV_HAS_TBB
} else if (kernel == kTBB) { } else if (kernel == kTBB) {
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
OpenSubdiv::Far::StencilTables, OpenSubdiv::Far::StencilTable,
OpenSubdiv::Osd::TbbEvaluator, OpenSubdiv::Osd::TbbEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, refiner,
@ -968,7 +972,7 @@ createOsdMesh(int level, int kernel) {
} else if (kernel == kCL) { } else if (kernel == kCL) {
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::CLEvaluator> clEvaluatorCache; static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::CLEvaluator> clEvaluatorCache;
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CLGLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CLGLVertexBuffer,
OpenSubdiv::Osd::CLStencilTables, OpenSubdiv::Osd::CLStencilTable,
OpenSubdiv::Osd::CLEvaluator, OpenSubdiv::Osd::CLEvaluator,
OpenSubdiv::Osd::GLPatchTable, OpenSubdiv::Osd::GLPatchTable,
CLDeviceContext>( CLDeviceContext>(
@ -982,7 +986,7 @@ createOsdMesh(int level, int kernel) {
#ifdef OPENSUBDIV_HAS_CUDA #ifdef OPENSUBDIV_HAS_CUDA
} else if (kernel == kCUDA) { } else if (kernel == kCUDA) {
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CudaGLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CudaGLVertexBuffer,
OpenSubdiv::Osd::CudaStencilTables, OpenSubdiv::Osd::CudaStencilTable,
OpenSubdiv::Osd::CudaEvaluator, OpenSubdiv::Osd::CudaEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, refiner,
@ -994,7 +998,7 @@ createOsdMesh(int level, int kernel) {
} else if (kernel == kGLSL) { } else if (kernel == kGLSL) {
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLXFBEvaluator> glXFBEvaluatorCache; static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLXFBEvaluator> glXFBEvaluatorCache;
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
OpenSubdiv::Osd::GLStencilTablesTBO, OpenSubdiv::Osd::GLStencilTableTBO,
OpenSubdiv::Osd::GLXFBEvaluator, OpenSubdiv::Osd::GLXFBEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, refiner,
@ -1007,7 +1011,7 @@ createOsdMesh(int level, int kernel) {
} else if (kernel == kGLSLCompute) { } else if (kernel == kGLSLCompute) {
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLComputeEvaluator> glComputeEvaluatorCache; static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLComputeEvaluator> glComputeEvaluatorCache;
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer, g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
OpenSubdiv::Osd::GLStencilTablesSSBO, OpenSubdiv::Osd::GLStencilTableSSBO,
OpenSubdiv::Osd::GLComputeEvaluator, OpenSubdiv::Osd::GLComputeEvaluator,
OpenSubdiv::Osd::GLPatchTable>( OpenSubdiv::Osd::GLPatchTable>(
refiner, refiner,

View File

@ -43,7 +43,7 @@ GLFWwindow* g_window=0;
GLFWmonitor* g_primary=0; GLFWmonitor* g_primary=0;
#include <far/error.h> #include <far/error.h>
#include <far/stencilTables.h> #include <far/stencilTable.h>
#include <far/ptexIndices.h> #include <far/ptexIndices.h>
#include <osd/mesh.h> #include <osd/mesh.h>
@ -891,31 +891,31 @@ rebuildTopology() {
if (g_kernel == kCPU) { if (g_kernel == kCPU) {
g_scene = new Scene<Osd::CpuEvaluator, g_scene = new Scene<Osd::CpuEvaluator,
Osd::CpuGLVertexBuffer, Osd::CpuGLVertexBuffer,
Far::StencilTables>(g_options); Far::StencilTable>(g_options);
#ifdef OPENSUBDIV_HAS_OPENMP #ifdef OPENSUBDIV_HAS_OPENMP
} else if (g_kernel == kOPENMP) { } else if (g_kernel == kOPENMP) {
g_scene = new Scene<Osd::OmpEvaluator, g_scene = new Scene<Osd::OmpEvaluator,
Osd::CpuGLVertexBuffer, Osd::CpuGLVertexBuffer,
Far::StencilTables>(g_options); Far::StencilTable>(g_options);
#endif #endif
#ifdef OPENSUBDIV_HAS_TBB #ifdef OPENSUBDIV_HAS_TBB
} else if (g_kernel == kTBB) { } else if (g_kernel == kTBB) {
g_scene = new Scene<Osd::TbbEvaluator, g_scene = new Scene<Osd::TbbEvaluator,
Osd::CpuGLVertexBuffer, Osd::CpuGLVertexBuffer,
Far::StencilTables>(g_options); Far::StencilTable>(g_options);
#endif #endif
#ifdef OPENSUBDIV_HAS_CUDA #ifdef OPENSUBDIV_HAS_CUDA
} else if (g_kernel == kCUDA) { } else if (g_kernel == kCUDA) {
g_scene = new Scene<Osd::CudaEvaluator, g_scene = new Scene<Osd::CudaEvaluator,
Osd::CudaGLVertexBuffer, Osd::CudaGLVertexBuffer,
Osd::CudaStencilTables>(g_options); Osd::CudaStencilTable>(g_options);
#endif #endif
#ifdef OPENSUBDIV_HAS_OPENCL #ifdef OPENSUBDIV_HAS_OPENCL
} else if (g_kernel == kCL) { } else if (g_kernel == kCL) {
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache; static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
g_scene = new Scene<Osd::CLEvaluator, g_scene = new Scene<Osd::CLEvaluator,
Osd::CLGLVertexBuffer, Osd::CLGLVertexBuffer,
Osd::CLStencilTables, Osd::CLStencilTable,
CLDeviceContext>(g_options, &clEvaluatorCache, CLDeviceContext>(g_options, &clEvaluatorCache,
&g_clDeviceContext); &g_clDeviceContext);
#endif #endif
@ -924,14 +924,14 @@ rebuildTopology() {
static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache; static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
g_scene = new Scene<Osd::GLXFBEvaluator, g_scene = new Scene<Osd::GLXFBEvaluator,
Osd::GLVertexBuffer, Osd::GLVertexBuffer,
Osd::GLStencilTablesTBO>(g_options, &glXFBEvaluatorCache); Osd::GLStencilTableTBO>(g_options, &glXFBEvaluatorCache);
#endif #endif
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
} else if (g_kernel == kGLSLCompute) { } else if (g_kernel == kGLSLCompute) {
static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache; static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
g_scene = new Scene<Osd::GLComputeEvaluator, g_scene = new Scene<Osd::GLComputeEvaluator,
Osd::GLVertexBuffer, Osd::GLVertexBuffer,
Osd::GLStencilTablesSSBO>(g_options, &glComputeEvaluatorCache); Osd::GLStencilTableSSBO>(g_options, &glComputeEvaluatorCache);
#endif #endif
} }

View File

@ -29,17 +29,17 @@
template <class EVALUATOR, template <class EVALUATOR,
class VERTEX_BUFFER, class VERTEX_BUFFER,
class STENCIL_TABLES, class STENCIL_TABLE,
class DEVICE_CONTEXT=void> class DEVICE_CONTEXT=void>
class MeshRefiner { class MeshRefiner {
public: public:
typedef EVALUATOR Evaluator; typedef EVALUATOR Evaluator;
typedef STENCIL_TABLES StencilTables; typedef STENCIL_TABLE StencilTable;
typedef DEVICE_CONTEXT DeviceContext; typedef DEVICE_CONTEXT DeviceContext;
typedef OpenSubdiv::Osd::EvaluatorCacheT<Evaluator> EvaluatorCache; typedef OpenSubdiv::Osd::EvaluatorCacheT<Evaluator> EvaluatorCache;
MeshRefiner(OpenSubdiv::Far::StencilTables const * vertexStencils, //XXX: takes ownership MeshRefiner(OpenSubdiv::Far::StencilTable const * vertexStencils, //XXX: takes ownership
OpenSubdiv::Far::StencilTables const * varyingStencils, OpenSubdiv::Far::StencilTable const * varyingStencils,
int numControlVertices, int numControlVertices,
EvaluatorCache * evaluatorCache = NULL, EvaluatorCache * evaluatorCache = NULL,
DeviceContext * deviceContext = NULL) DeviceContext * deviceContext = NULL)
@ -49,9 +49,9 @@ public:
_numControlVertices = numControlVertices; _numControlVertices = numControlVertices;
_numVertices = numControlVertices + vertexStencils->GetNumStencils(); _numVertices = numControlVertices + vertexStencils->GetNumStencils();
_vertexStencils = OpenSubdiv::Osd::convertToCompatibleStencilTables<StencilTables>( _vertexStencils = OpenSubdiv::Osd::convertToCompatibleStencilTable<StencilTable>(
vertexStencils, deviceContext); vertexStencils, deviceContext);
_varyingStencils = OpenSubdiv::Osd::convertToCompatibleStencilTables<StencilTables>( _varyingStencils = OpenSubdiv::Osd::convertToCompatibleStencilTable<StencilTable>(
varyingStencils, deviceContext); varyingStencils, deviceContext);
} }
@ -137,8 +137,8 @@ private:
int _numVertices; int _numVertices;
int _numControlVertices; int _numControlVertices;
StencilTables const *_vertexStencils; StencilTable const *_vertexStencils;
StencilTables const *_varyingStencils; StencilTable const *_varyingStencils;
EvaluatorCache * _evaluatorCache; EvaluatorCache * _evaluatorCache;
DeviceContext *_deviceContext; DeviceContext *_deviceContext;
}; };

View File

@ -91,8 +91,8 @@ public:
} }
virtual size_t createMeshRefiner( virtual size_t createMeshRefiner(
OpenSubdiv::Far::StencilTables const * vertexStencils, OpenSubdiv::Far::StencilTable const * vertexStencils,
OpenSubdiv::Far::StencilTables const * varyingStencils, OpenSubdiv::Far::StencilTable const * varyingStencils,
int numControlVertices) { int numControlVertices) {
MeshRefinerType *meshRefiner = MeshRefinerType *meshRefiner =

View File

@ -24,8 +24,8 @@
#include <limits> #include <limits>
#include <common/vtr_utils.h> #include <common/vtr_utils.h>
#include <far/patchTablesFactory.h> #include <far/patchTableFactory.h>
#include <far/stencilTablesFactory.h> #include <far/stencilTableFactory.h>
#include "sceneBase.h" #include "sceneBase.h"
using namespace OpenSubdiv; using namespace OpenSubdiv;
@ -47,7 +47,7 @@ SceneBase::~SceneBase() {
void void
SceneBase::AddTopology(Shape const *shape, int level, bool varying) { 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); int numVerts = createStencilTable(shape, level, varying, &patchTable);
// centering rest position // centering rest position
@ -92,7 +92,7 @@ SceneBase::AddTopology(Shape const *shape, int level, bool varying) {
int int
SceneBase::createStencilTable(Shape const *shape, int level, bool varying, SceneBase::createStencilTable(Shape const *shape, int level, bool varying,
OpenSubdiv::Far::PatchTables const **patchTablesOut) { OpenSubdiv::Far::PatchTable const **patchTableOut) {
Far::TopologyRefiner * refiner = 0; Far::TopologyRefiner * refiner = 0;
{ {
@ -115,61 +115,61 @@ SceneBase::createStencilTable(Shape const *shape, int level, bool varying,
refiner->RefineUniform(options); 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.generateOffsets = true;
options.generateIntermediateLevels = _options.adaptive; options.generateIntermediateLevels = _options.adaptive;
vertexStencils = Far::StencilTablesFactory::Create(*refiner, options); vertexStencils = Far::StencilTableFactory::Create(*refiner, options);
if (varying) { if (varying) {
varyingStencils = Far::StencilTablesFactory::Create(*refiner, options); varyingStencils = Far::StencilTableFactory::Create(*refiner, options);
} }
assert(vertexStencils); 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) { if (_options.endCap == kEndCapBSplineBasis) {
poptions.SetEndCapType( poptions.SetEndCapType(
Far::PatchTablesFactory::Options::ENDCAP_BSPLINE_BASIS); Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
} else { } else {
poptions.SetEndCapType( 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 // append gregory vertices into stencils
{ {
if (Far::StencilTables const *vertexStencilsWithEndCap = if (Far::StencilTable const *vertexStencilsWithEndCap =
Far::StencilTablesFactory::AppendEndCapStencilTables( Far::StencilTableFactory::AppendEndCapStencilTable(
*refiner, *refiner,
vertexStencils, vertexStencils,
patchTables->GetEndCapVertexStencilTables())) { patchTable->GetEndCapVertexStencilTable())) {
delete vertexStencils; delete vertexStencils;
vertexStencils = vertexStencilsWithEndCap; vertexStencils = vertexStencilsWithEndCap;
} }
if (varyingStencils) { if (varyingStencils) {
if (Far::StencilTables const *varyingStencilsWithEndCap = if (Far::StencilTable const *varyingStencilsWithEndCap =
Far::StencilTablesFactory::AppendEndCapStencilTables( Far::StencilTableFactory::AppendEndCapStencilTable(
*refiner, *refiner,
varyingStencils, varyingStencils,
patchTables->GetEndCapVaryingStencilTables())) { patchTable->GetEndCapVaryingStencilTable())) {
delete varyingStencils; delete varyingStencils;
varyingStencils = varyingStencilsWithEndCap; varyingStencils = varyingStencilsWithEndCap;
} }
} }
} }
int numControlVertices = refiner->GetNumVertices(0); int numControlVertices = refiner->GetLevel(0).GetNumVertices();
_stencilTableSize = createMeshRefiner(vertexStencils, varyingStencils, _stencilTableSize = createMeshRefiner(vertexStencils, varyingStencils,
numControlVertices); numControlVertices);
// note: refiner takes ownerships of vertexStencils/ varyingStencils, patchTables // note: refiner takes ownerships of vertexStencils/ varyingStencils, patchTable
delete refiner; delete refiner;
return numControlVertices + vertexStencils->GetNumStencils(); return numControlVertices + vertexStencils->GetNumStencils();
@ -214,9 +214,9 @@ SceneBase::CreateIndexBuffer() {
int numTopologies = (int)_topologies.size(); int numTopologies = (int)_topologies.size();
for (int i = 0; i < numTopologies; ++i) { 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(); _topologies[i].patchArrays.clear();
@ -224,21 +224,21 @@ SceneBase::CreateIndexBuffer() {
for (int j = 0; j < nPatchArrays; ++j) { for (int j = 0; j < nPatchArrays; ++j) {
SceneBase::PatchArray patchArray; SceneBase::PatchArray patchArray;
patchArray.desc = patchTables->GetPatchArrayDescriptor(j); patchArray.desc = patchTable->GetPatchArrayDescriptor(j);
patchArray.numPatches = patchTables->GetNumPatches(j); patchArray.numPatches = patchTable->GetNumPatches(j);
patchArray.indexOffset = (int)buffer.size(); patchArray.indexOffset = (int)buffer.size();
patchArray.primitiveIDOffset = (int)ppBuffer.size()/3; patchArray.primitiveIDOffset = (int)ppBuffer.size()/3;
_topologies[i].patchArrays.push_back(patchArray); _topologies[i].patchArrays.push_back(patchArray);
// indices // indices
Far::ConstIndexArray indices = patchTables->GetPatchArrayVertices(j); Far::ConstIndexArray indices = patchTable->GetPatchArrayVertices(j);
for (int k = 0; k < indices.size(); ++k) { for (int k = 0; k < indices.size(); ++k) {
buffer.push_back(indices[k]); buffer.push_back(indices[k]);
} }
// patchParams // patchParams
Far::ConstPatchParamArray patchParams = patchTables->GetPatchParams(j); Far::ConstPatchParamArray patchParams = patchTable->GetPatchParams(j);
// XXX: needs sharpness interface for patcharray or put sharpness into patchParam. // XXX: needs sharpness interface for patcharray or put sharpness into patchParam.
for (int k = 0; k < patchParams.size(); ++k) { for (int k = 0; k < patchParams.size(); ++k) {
float sharpness = 0.0; float sharpness = 0.0;
@ -248,26 +248,26 @@ SceneBase::CreateIndexBuffer() {
} }
} }
#if 0 #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. // use GetPatchParams(patchArray) instead as above.
// patch param (all in one) // patch param (all in one)
Far::PatchParamTable const &patchParamTables = Far::PatchParamTable const &patchParamTable =
patchTables->GetPatchParamTable(); patchTable->GetPatchParamTable();
std::vector<int> const &sharpnessIndexTable = std::vector<int> const &sharpnessIndexTable =
patchTables->GetSharpnessIndexTable(); patchTable->GetSharpnessIndexTable();
std::vector<float> const &sharpnessValues = std::vector<float> const &sharpnessValues =
patchTables->GetSharpnessValues(); patchTable->GetSharpnessValues();
int npatches = (int)patchParamTables.size(); int npatches = (int)patchParamTable.size();
for (int i = 0; i < npatches; ++i) { for (int i = 0; i < npatches; ++i) {
float sharpness = 0.0; float sharpness = 0.0;
if (i < (int)sharpnessIndexTable.size()) { if (i < (int)sharpnessIndexTable.size()) {
sharpness = sharpnessIndexTable[i] >= 0 ? sharpness = sharpnessIndexTable[i] >= 0 ?
sharpnessValues[sharpnessIndexTable[i]] : 0.0f; sharpnessValues[sharpnessIndexTable[i]] : 0.0f;
} }
ppBuffer.push_back(patchParamTables[i].faceIndex); ppBuffer.push_back(patchParamTable[i].faceIndex);
ppBuffer.push_back(patchParamTables[i].bitField.field); ppBuffer.push_back(patchParamTable[i].bitField.field);
ppBuffer.push_back(*((unsigned int *)&sharpness)); ppBuffer.push_back(*((unsigned int *)&sharpness));
} }
#endif #endif

View File

@ -26,7 +26,7 @@
#define OPENSUBDIV_EXAMPLES_GL_SHARE_TOPOLOGY_SCENE_BASE_H #define OPENSUBDIV_EXAMPLES_GL_SHARE_TOPOLOGY_SCENE_BASE_H
#include <far/patchDescriptor.h> #include <far/patchDescriptor.h>
#include <far/patchTables.h> #include <far/patchTable.h>
#include <osd/vertexDescriptor.h> #include <osd/vertexDescriptor.h>
#include <osd/opengl.h> #include <osd/opengl.h>
@ -135,20 +135,20 @@ public:
protected: protected:
int createStencilTable(Shape const *shape, int level, bool varying, int createStencilTable(Shape const *shape, int level, bool varying,
OpenSubdiv::Far::PatchTables const **patchTableOut); OpenSubdiv::Far::PatchTable const **patchTableOut);
void buildBatches(); void buildBatches();
virtual size_t createMeshRefiner( virtual size_t createMeshRefiner(
OpenSubdiv::Far::StencilTables const * vertexStencils, OpenSubdiv::Far::StencilTable const * vertexStencils,
OpenSubdiv::Far::StencilTables const * varyingStencils, OpenSubdiv::Far::StencilTable const * varyingStencils,
int numControlVertices) = 0; int numControlVertices) = 0;
Options _options; Options _options;
std::vector<Object> _objects; std::vector<Object> _objects;
std::vector<Topology> _topologies; std::vector<Topology> _topologies;
std::vector<OpenSubdiv::Far::PatchTables const *> _patchTables; std::vector<OpenSubdiv::Far::PatchTable const *> _patchTables;
GLuint _indexBuffer; GLuint _indexBuffer;
GLuint _patchParamTexture; GLuint _patchParamTexture;
BatchVector _batches; BatchVector _batches;

View File

@ -48,9 +48,9 @@ GLFWmonitor* g_primary=0;
#include "../common/glUtils.h" #include "../common/glUtils.h"
#include "../common/glHud.h" #include "../common/glHud.h"
#include <far/patchTablesFactory.h> #include <far/patchTableFactory.h>
#include <far/ptexIndices.h> #include <far/ptexIndices.h>
#include <far/stencilTablesFactory.h> #include <far/stencilTableFactory.h>
#include <osd/cpuGLVertexBuffer.h> #include <osd/cpuGLVertexBuffer.h>
#include <osd/cpuVertexBuffer.h> #include <osd/cpuVertexBuffer.h>
@ -136,7 +136,7 @@ GLhud g_hud;
int g_currentShape = 0; int g_currentShape = 0;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Far::LimitStencilTables const * g_controlStencils; Far::LimitStencilTable const * g_controlStencils;
// Control vertex positions (P(xyz)) // Control vertex positions (P(xyz))
Osd::CpuVertexBuffer * g_controlValues=0; Osd::CpuVertexBuffer * g_controlValues=0;
@ -271,7 +271,7 @@ static void
createMesh(ShapeDesc const & shapeDesc, int level) { createMesh(ShapeDesc const & shapeDesc, int level) {
typedef Far::ConstIndexArray IndexArray; 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); Shape const * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme);
@ -284,22 +284,24 @@ createMesh(ShapeDesc const & shapeDesc, int level) {
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)); OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
int nedges = refiner->GetNumEdges(0), OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
nverts = refiner->GetNumVertices(0);
int nedges = refBaseLevel.GetNumEdges(),
nverts = refBaseLevel.GetNumVertices();
g_coarseEdges.resize(nedges*2); g_coarseEdges.resize(nedges*2);
g_coarseEdgeSharpness.resize(nedges); g_coarseEdgeSharpness.resize(nedges);
g_coarseVertexSharpness.resize(nverts); g_coarseVertexSharpness.resize(nverts);
for(int i=0; i<nedges; ++i) { for(int i=0; i<nedges; ++i) {
IndexArray verts = refiner->GetEdgeVertices(0, i); IndexArray verts = refBaseLevel.GetEdgeVertices(i);
g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2 ]=verts[0];
g_coarseEdges[i*2+1]=verts[1]; g_coarseEdges[i*2+1]=verts[1];
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
} }
for(int i=0; i<nverts; ++i) { for(int i=0; i<nverts; ++i) {
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i); g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
} }
g_orgPositions=shape->verts; g_orgPositions=shape->verts;
@ -338,7 +340,7 @@ createMesh(ShapeDesc const & shapeDesc, int level) {
} }
delete g_controlStencils; delete g_controlStencils;
g_controlStencils = Far::LimitStencilTablesFactory::Create(*refiner, locs); g_controlStencils = Far::LimitStencilTableFactory::Create(*refiner, locs);
delete [] u; delete [] u;
delete [] v; delete [] v;

View File

@ -283,11 +283,11 @@ struct FVarData
glDeleteTextures(1, &textureBuffer); glDeleteTextures(1, &textureBuffer);
textureBuffer = 0; textureBuffer = 0;
} }
void Create(OpenSubdiv::Far::PatchTables const *patchTables, void Create(OpenSubdiv::Far::PatchTable const *patchTable,
int fvarWidth, std::vector<float> const & fvarSrcData) { int fvarWidth, std::vector<float> const & fvarSrcData) {
Release(); Release();
OpenSubdiv::Far::ConstIndexArray indices = OpenSubdiv::Far::ConstIndexArray indices =
patchTables->GetFVarPatchesValues(0); patchTable->GetFVarPatchesValues(0);
// expand fvardata to per-patch array // expand fvardata to per-patch array
std::vector<float> data; std::vector<float> data;
@ -555,22 +555,24 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)); Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
// save coarse topology (used for coarse mesh drawing) // save coarse topology (used for coarse mesh drawing)
int nedges = refiner->GetNumEdges(0), OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
nverts = refiner->GetNumVertices(0);
int nedges = refBaseLevel.GetNumEdges(),
nverts = refBaseLevel.GetNumVertices();
g_coarseEdges.resize(nedges*2); g_coarseEdges.resize(nedges*2);
g_coarseEdgeSharpness.resize(nedges); g_coarseEdgeSharpness.resize(nedges);
g_coarseVertexSharpness.resize(nverts); g_coarseVertexSharpness.resize(nverts);
for(int i=0; i<nedges; ++i) { for(int i=0; i<nedges; ++i) {
IndexArray verts = refiner->GetEdgeVertices(0, i); IndexArray verts = refBaseLevel.GetEdgeVertices(i);
g_coarseEdges[i*2 ]=verts[0]; g_coarseEdges[i*2 ]=verts[0];
g_coarseEdges[i*2+1]=verts[1]; g_coarseEdges[i*2+1]=verts[1];
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i); g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
} }
for(int i=0; i<nverts; ++i) { for(int i=0; i<nverts; ++i) {
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i); g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
} }
g_orgPositions=shape->verts; g_orgPositions=shape->verts;
@ -602,7 +604,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
if (kernel == kCPU) { if (kernel == kCPU) {
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::CpuEvaluator, Osd::CpuEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -612,7 +614,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
#ifdef OPENSUBDIV_HAS_OPENMP #ifdef OPENSUBDIV_HAS_OPENMP
} else if (kernel == kOPENMP) { } else if (kernel == kOPENMP) {
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::OmpEvaluator, Osd::OmpEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -623,7 +625,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
#ifdef OPENSUBDIV_HAS_TBB #ifdef OPENSUBDIV_HAS_TBB
} else if (kernel == kTBB) { } else if (kernel == kTBB) {
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer, g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
Far::StencilTables, Far::StencilTable,
Osd::TbbEvaluator, Osd::TbbEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -636,7 +638,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
// CLKernel // CLKernel
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache; static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
g_mesh = new Osd::Mesh<Osd::CLGLVertexBuffer, g_mesh = new Osd::Mesh<Osd::CLGLVertexBuffer,
Osd::CLStencilTables, Osd::CLStencilTable,
Osd::CLEvaluator, Osd::CLEvaluator,
Osd::GLPatchTable, Osd::GLPatchTable,
CLDeviceContext>( CLDeviceContext>(
@ -650,7 +652,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
#ifdef OPENSUBDIV_HAS_CUDA #ifdef OPENSUBDIV_HAS_CUDA
} else if(kernel == kCUDA) { } else if(kernel == kCUDA) {
g_mesh = new Osd::Mesh<Osd::CudaGLVertexBuffer, g_mesh = new Osd::Mesh<Osd::CudaGLVertexBuffer,
Osd::CudaStencilTables, Osd::CudaStencilTable,
Osd::CudaEvaluator, Osd::CudaEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -662,7 +664,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
} else if(kernel == kGLSL) { } else if(kernel == kGLSL) {
static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache; static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer, g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
Osd::GLStencilTablesTBO, Osd::GLStencilTableTBO,
Osd::GLXFBEvaluator, Osd::GLXFBEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -675,7 +677,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
} else if(kernel == kGLSLCompute) { } else if(kernel == kGLSLCompute) {
static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache; static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer, g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
Osd::GLStencilTablesSSBO, Osd::GLStencilTableSSBO,
Osd::GLComputeEvaluator, Osd::GLComputeEvaluator,
Osd::GLPatchTable>( Osd::GLPatchTable>(
refiner, refiner,
@ -697,7 +699,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
InterpolateFVarData(*refiner, *shape, fvarData); InterpolateFVarData(*refiner, *shape, fvarData);
// set fvardata to texture buffer // set fvardata to texture buffer
g_fvarData.Create(g_mesh->GetFarPatchTables(), g_fvarData.Create(g_mesh->GetFarPatchTable(),
shape->GetFVarWidth(), fvarData); shape->GetFVarWidth(), fvarData);
} }
@ -706,7 +708,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
g_legacyGregoryPatchTable = NULL; g_legacyGregoryPatchTable = NULL;
if (g_endCap == kEndCapLegacyGregory) { if (g_endCap == kEndCapLegacyGregory) {
g_legacyGregoryPatchTable = g_legacyGregoryPatchTable =
Osd::GLLegacyGregoryPatchTable::Create(g_mesh->GetFarPatchTables()); Osd::GLLegacyGregoryPatchTable::Create(g_mesh->GetFarPatchTable());
} }
if (not doAnim) { if (not doAnim) {
@ -1320,7 +1322,7 @@ display() {
g_mesh->GetPatchTable()->GetPatchArrays(); g_mesh->GetPatchTable()->GetPatchArrays();
// patch drawing // patch drawing
int patchCount[13]; // [Type] (see far/patchTables.h) int patchCount[13]; // [Type] (see far/patchTable.h)
int numTotalPatches = 0; int numTotalPatches = 0;
int numDrawCalls = 0; int numDrawCalls = 0;
memset(patchCount, 0, sizeof(patchCount)); memset(patchCount, 0, sizeof(patchCount));

View File

@ -77,6 +77,12 @@ static std::vector<ShapeDesc> g_defaultShapes;
#include <shapes/catmark_hole_test4.h> #include <shapes/catmark_hole_test4.h>
#include <shapes/catmark_lefthanded.h> #include <shapes/catmark_lefthanded.h>
#include <shapes/catmark_righthanded.h> #include <shapes/catmark_righthanded.h>
#include <shapes/catmark_pole8.h>
#include <shapes/catmark_pole64.h>
#include <shapes/catmark_pole360.h>
#include <shapes/catmark_nonman_quadpole8.h>
#include <shapes/catmark_nonman_quadpole64.h>
#include <shapes/catmark_nonman_quadpole360.h>
#include <shapes/catmark_pawn.h> #include <shapes/catmark_pawn.h>
#include <shapes/catmark_pyramid_creases0.h> #include <shapes/catmark_pyramid_creases0.h>
#include <shapes/catmark_pyramid_creases1.h> #include <shapes/catmark_pyramid_creases1.h>
@ -106,6 +112,9 @@ static std::vector<ShapeDesc> g_defaultShapes;
#include <shapes/loop_triangle_edgeonly.h> #include <shapes/loop_triangle_edgeonly.h>
#include <shapes/loop_chaikin0.h> #include <shapes/loop_chaikin0.h>
#include <shapes/loop_chaikin1.h> #include <shapes/loop_chaikin1.h>
#include <shapes/loop_pole8.h>
#include <shapes/loop_pole64.h>
#include <shapes/loop_pole360.h>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void initShapes() { 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_hole_test4", catmark_hole_test4, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/ ) ); 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_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_creases0", catmark_pyramid_creases0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) ); g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, 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_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) );
g_defaultShapes.push_back( ShapeDesc("loop_chaikin0", loop_chaikin0, 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_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 ) );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -112,6 +112,9 @@ OSD_USER_VARYING_ATTRIBUTE_DECLARE
out block { out block {
OutputVertex v; OutputVertex v;
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness;
#endif
OSD_USER_VARYING_DECLARE OSD_USER_VARYING_DECLARE
} outpt; } outpt;
@ -119,6 +122,9 @@ void main()
{ {
outpt.v.position = ModelViewMatrix * position; outpt.v.position = ModelViewMatrix * position;
outpt.v.patchCoord = vec4(0); outpt.v.patchCoord = vec4(0);
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
outpt.sharpness = 0;
#endif
OSD_USER_VARYING_PER_VERTEX(); OSD_USER_VARYING_PER_VERTEX();
} }

View File

@ -61,7 +61,7 @@
// OpenSubdiv includes // OpenSubdiv includes
#include <far/topologyRefinerFactory.h> #include <far/topologyRefinerFactory.h>
#include <far/stencilTablesFactory.h> #include <far/stencilTableFactory.h>
#include <osd/mesh.h> #include <osd/mesh.h>
#include <osd/cpuVertexBuffer.h> #include <osd/cpuVertexBuffer.h>
@ -523,8 +523,12 @@ convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner,
typedef OpenSubdiv::Far::ConstIndexArray IndexArray; typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
int maxlevel = refiner.GetMaxLevel(), int maxlevel = refiner.GetMaxLevel();
nfaces = refiner.GetNumFaces(maxlevel);
OpenSubdiv::Far::TopologyLevel const & refLastLevel
= refiner.GetLevel(maxlevel);
int nfaces = refLastLevel.GetNumFaces();
// Init Maya Data // Init Maya Data
@ -537,18 +541,18 @@ convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner,
// -- Face Connects // -- Face Connects
MIntArray faceConnects(nfaces*4); MIntArray faceConnects(nfaces*4);
for (int face=0, idx=0; face < nfaces; ++face) { 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) { for (int vert=0; vert < fverts.size(); ++vert) {
faceConnects[idx++] = fverts[vert]; faceConnects[idx++] = fverts[vert];
} }
} }
// -- Points // -- Points
MFloatPointArray points(refiner.GetNumVertices(maxlevel)); MFloatPointArray points(refLastLevel.GetNumVertices());
Vertex const * v = &vertexBuffer.at(0); Vertex const * v = &vertexBuffer.at(0);
for (int level=1; level<=maxlevel; ++level) { for (int level=1; level<=maxlevel; ++level) {
int nverts = refiner.GetNumVertices(level); int nverts = refiner.GetLevel(level).GetNumVertices();
if (level==maxlevel) { if (level==maxlevel) {
for (int vert=0; vert < nverts; ++vert, ++v) { for (int vert=0; vert < nverts; ++vert, ++v) {
points.set(vert, v->position[0], v->position[1], v->position[2]); 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<Vertex const *>(inMeshFn.getRawPoints(&status)); reinterpret_cast<Vertex const *>(inMeshFn.getRawPoints(&status));
std::vector<Vertex> refinedVerts( std::vector<Vertex> refinedVerts(
refiner->GetNumVerticesTotal() - refiner->GetNumVertices(0)); refiner->GetNumVerticesTotal() - refiner->GetLevel(0).GetNumVertices());
refiner->Interpolate(controlVerts, &refinedVerts.at(0)); 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) // Propagate objectGroups from inMesh to outMesh (for per-facet shading, etc)
status = createSmoothMesh_objectGroups(inMeshFn, inMeshDat, status = createSmoothMesh_objectGroups(inMeshFn, inMeshDat,
newMeshData, subdivisionLevel, refiner->GetNumFaces(subdivisionLevel)); newMeshData, subdivisionLevel, refiner->GetLevel(subdivisionLevel).GetNumFaces());
// Write to output plug // Write to output plug
MDataHandle outMeshH = data.outputValue(a_output, &status); MDataHandle outMeshH = data.outputValue(a_output, &status);

View File

@ -33,16 +33,17 @@ set(SOURCE_FILES
patchBasis.cpp patchBasis.cpp
patchDescriptor.cpp patchDescriptor.cpp
patchMap.cpp patchMap.cpp
patchTables.cpp patchTable.cpp
patchTablesFactory.cpp patchTableFactory.cpp
ptexIndices.cpp ptexIndices.cpp
stencilTablesFactory.cpp stencilTableFactory.cpp
stencilBuilder.cpp
topologyRefiner.cpp topologyRefiner.cpp
topologyRefinerFactory.cpp topologyRefinerFactory.cpp
) )
set(PRIVATE_HEADER_FILES set(PRIVATE_HEADER_FILES
protoStencil.h stencilBuilder.h
) )
set(PUBLIC_HEADER_FILES set(PUBLIC_HEADER_FILES
@ -55,11 +56,11 @@ set(PUBLIC_HEADER_FILES
patchDescriptor.h patchDescriptor.h
patchParam.h patchParam.h
patchMap.h patchMap.h
patchTables.h patchTable.h
patchTablesFactory.h patchTableFactory.h
ptexIndices.h ptexIndices.h
stencilTables.h stencilTable.h
stencilTablesFactory.h stencilTableFactory.h
topologyLevel.h topologyLevel.h
topologyRefiner.h topologyRefiner.h
topologyRefinerFactory.h topologyRefinerFactory.h

View File

@ -25,7 +25,7 @@
#include "../far/gregoryBasis.h" #include "../far/gregoryBasis.h"
#include "../far/endCapBSplineBasisPatchFactory.h" #include "../far/endCapBSplineBasisPatchFactory.h"
#include "../far/error.h" #include "../far/error.h"
#include "../far/stencilTablesFactory.h" #include "../far/stencilTableFactory.h"
#include "../far/topologyRefiner.h" #include "../far/topologyRefiner.h"
#include <cassert> #include <cassert>

View File

@ -25,9 +25,8 @@
#ifndef OPENSUBDIV3_FAR_END_CAP_BSPLINE_BASIS_PATCH_FACTORY_H #ifndef OPENSUBDIV3_FAR_END_CAP_BSPLINE_BASIS_PATCH_FACTORY_H
#define 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/gregoryBasis.h"
#include "../far/protoStencil.h"
#include "../vtr/level.h" #include "../vtr/level.h"
namespace OpenSubdiv { namespace OpenSubdiv {
@ -39,7 +38,7 @@ class TopologyRefiner;
/// \brief A BSpline endcap factory /// \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 /// will be replaced with SdcSchemeWorker for mask coefficients
/// and Vtr::Level for topology traversal. /// and Vtr::Level for topology traversal.
/// ///
@ -70,19 +69,19 @@ public:
ConstIndexArray GetPatchPoints( ConstIndexArray GetPatchPoints(
Vtr::Level const * level, Index faceIndex); 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. /// subdivision level.
/// ///
StencilTables* CreateVertexStencilTables() const { StencilTable* CreateVertexStencilTable() const {
return GregoryBasis::CreateStencilTables(_vertexStencils); 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 /// This table is used as a convenient way to get varying primvars
/// populated on end patch points along with positions. /// populated on end patch points along with positions.
/// ///
StencilTables* CreateVaryingStencilTables() const { StencilTable* CreateVaryingStencilTable() const {
return GregoryBasis::CreateStencilTables(_varyingStencils); return GregoryBasis::CreateStencilTable(_varyingStencils);
} }
private: private:

View File

@ -25,7 +25,7 @@
#include "../far/gregoryBasis.h" #include "../far/gregoryBasis.h"
#include "../far/endCapGregoryBasisPatchFactory.h" #include "../far/endCapGregoryBasisPatchFactory.h"
#include "../far/error.h" #include "../far/error.h"
#include "../far/stencilTablesFactory.h" #include "../far/stencilTableFactory.h"
#include "../far/topologyRefiner.h" #include "../far/topologyRefiner.h"
#include <cassert> #include <cassert>
@ -37,21 +37,8 @@ namespace OPENSUBDIV_VERSION {
namespace Far { 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( EndCapGregoryBasisPatchFactory::EndCapGregoryBasisPatchFactory(
TopologyRefiner const & refiner, bool shareBoundaryVertices) : TopologyRefiner const & refiner, bool shareBoundaryVertices) :
@ -62,12 +49,6 @@ EndCapGregoryBasisPatchFactory::EndCapGregoryBasisPatchFactory(
assert(not refiner.IsUniform()); assert(not refiner.IsUniform());
} }
int
EndCapGregoryBasisPatchFactory::GetMaxValence() {
return GregoryBasis::MAX_VALENCE;
}
// //
// Stateless EndCapGregoryBasisPatchFactory // Stateless EndCapGregoryBasisPatchFactory
// //
@ -78,10 +59,6 @@ EndCapGregoryBasisPatchFactory::Create(TopologyRefiner const & refiner,
// Gregory patches are end-caps: they only exist on max-level // Gregory patches are end-caps: they only exist on max-level
Vtr::Level const & level = refiner.getLevel(refiner.GetMaxLevel()); Vtr::Level const & level = refiner.getLevel(refiner.GetMaxLevel());
if (not checkMaxValence(level)) {
return 0;
}
GregoryBasis::ProtoBasis basis(level, faceIndex, fvarChannel); GregoryBasis::ProtoBasis basis(level, faceIndex, fvarChannel);
GregoryBasis * result = new GregoryBasis; GregoryBasis * result = new GregoryBasis;
basis.Copy(result); basis.Copy(result);
@ -97,10 +74,6 @@ EndCapGregoryBasisPatchFactory::addPatchBasis(Index faceIndex,
// Gregory patches only exist on the hight // Gregory patches only exist on the hight
Vtr::Level const & level = _refiner->getLevel(_refiner->GetMaxLevel()); 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 // Gather the CVs that influence the Gregory patch and their relative
// weights in a basis // weights in a basis
GregoryBasis::ProtoBasis basis(level, faceIndex); GregoryBasis::ProtoBasis basis(level, faceIndex);
@ -139,7 +112,7 @@ EndCapGregoryBasisPatchFactory::addPatchBasis(Index faceIndex,
ConstIndexArray ConstIndexArray
EndCapGregoryBasisPatchFactory::GetPatchPoints( EndCapGregoryBasisPatchFactory::GetPatchPoints(
Vtr::Level const * level, Index faceIndex, Vtr::Level const * level, Index faceIndex,
PatchTablesFactory::PatchFaceTag const * levelPatchTags) PatchTableFactory::PatchFaceTag const * levelPatchTags)
{ {
// allocate indices (awkward) // allocate indices (awkward)
// assert(Vtr::INDEX_INVALID==0xFFFFFFFF); // assert(Vtr::INDEX_INVALID==0xFFFFFFFF);

View File

@ -25,7 +25,7 @@
#ifndef OPENSUBDIV3_FAR_END_CAP_GREGORY_BASIS_PATCH_FACTORY_H #ifndef OPENSUBDIV3_FAR_END_CAP_GREGORY_BASIS_PATCH_FACTORY_H
#define 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 "../far/gregoryBasis.h"
#include "../vtr/level.h" #include "../vtr/level.h"
@ -38,7 +38,7 @@ class TopologyRefiner;
/// \brief A specialized factory to gather Gregory basis control vertices /// \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 /// will be replaced with SdcSchemeWorker for mask coefficients
/// and Vtr::Level for topology traversal. /// and Vtr::Level for topology traversal.
/// ///
@ -62,10 +62,6 @@ public:
static GregoryBasis const * Create(TopologyRefiner const & refiner, static GregoryBasis const * Create(TopologyRefiner const & refiner,
Index faceIndex, int fvarChannel=-1); 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: public:
/// ///
@ -98,21 +94,21 @@ public:
/// ///
ConstIndexArray GetPatchPoints( ConstIndexArray GetPatchPoints(
Vtr::Level const * level, Index faceIndex, 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. /// subdivision level.
/// ///
StencilTables* CreateVertexStencilTables() const { StencilTable* CreateVertexStencilTable() const {
return GregoryBasis::CreateStencilTables(_vertexStencils); 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 /// This table is used as a convenient way to get varying primvars
/// populated on end patch points along with positions. /// populated on end patch points along with positions.
/// ///
StencilTables* CreateVaryingStencilTables() const { StencilTable* CreateVaryingStencilTable() const {
return GregoryBasis::CreateStencilTables(_varyingStencils); return GregoryBasis::CreateStencilTable(_varyingStencils);
} }
private: private:

View File

@ -24,7 +24,7 @@
#include "../far/error.h" #include "../far/error.h"
#include "../far/endCapLegacyGregoryPatchFactory.h" #include "../far/endCapLegacyGregoryPatchFactory.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
#include "../far/topologyRefiner.h" #include "../far/topologyRefiner.h"
#include "../vtr/level.h" #include "../vtr/level.h"
@ -41,10 +41,10 @@ EndCapLegacyGregoryPatchFactory::EndCapLegacyGregoryPatchFactory(
ConstIndexArray ConstIndexArray
EndCapLegacyGregoryPatchFactory::GetPatchPoints( EndCapLegacyGregoryPatchFactory::GetPatchPoints(
Vtr::Level const * level, Index faceIndex, Vtr::Level const * level, Index faceIndex,
PatchTablesFactory::PatchFaceTag const * levelPatchTags, PatchTableFactory::PatchFaceTag const * levelPatchTags,
int levelVertOffset) { int levelVertOffset) {
PatchTablesFactory::PatchFaceTag patchTag = levelPatchTags[faceIndex]; PatchTableFactory::PatchFaceTag patchTag = levelPatchTags[faceIndex];
// Gregory Regular Patch (4 CVs + quad-offsets / valence tables) // Gregory Regular Patch (4 CVs + quad-offsets / valence tables)
Vtr::ConstIndexArray faceVerts = level->getFaceVertices(faceIndex); Vtr::ConstIndexArray faceVerts = level->getFaceVertices(faceIndex);
@ -102,8 +102,8 @@ static void getQuadOffsets(
void void
EndCapLegacyGregoryPatchFactory::Finalize( EndCapLegacyGregoryPatchFactory::Finalize(
int maxValence, int maxValence,
PatchTables::QuadOffsetsTable *quadOffsetsTable, PatchTable::QuadOffsetsTable *quadOffsetsTable,
PatchTables::VertexValenceTable *vertexValenceTable) PatchTable::VertexValenceTable *vertexValenceTable)
{ {
// populate quad offsets // populate quad offsets
@ -116,18 +116,18 @@ EndCapLegacyGregoryPatchFactory::Finalize(
quadOffsetsTable->resize(numTotalGregoryPatches*4); quadOffsetsTable->resize(numTotalGregoryPatches*4);
if (numTotalGregoryPatches > 0) { if (numTotalGregoryPatches > 0) {
PatchTables::QuadOffsetsTable::value_type *p = PatchTable::QuadOffsetsTable::value_type *p =
&((*quadOffsetsTable)[0]); &((*quadOffsetsTable)[0]);
for (size_t i = 0; i < numGregoryPatches; ++i) { for (size_t i = 0; i < numGregoryPatches; ++i) {
getQuadOffsets(level, _gregoryFaceIndices[i], p); getQuadOffsets(level, _gregoryFaceIndices[i], p);
p += 4; p += 4;
} }
for (size_t i = 0; i < numGregoryBoundaryPatches; ++i) { for (size_t i = 0; i < numGregoryBoundaryPatches; ++i) {
getQuadOffsets(level, _gregoryBoundaryFaceIndices[i], p); getQuadOffsets(level, _gregoryBoundaryFaceIndices[i], p);
p += 4; p += 4;
} }
} }
// populate vertex valences // populate vertex valences
// //
@ -144,7 +144,7 @@ EndCapLegacyGregoryPatchFactory::Finalize(
// //
const int SizePerVertex = 2*maxValence + 1; const int SizePerVertex = 2*maxValence + 1;
PatchTables::VertexValenceTable & vTable = (*vertexValenceTable); PatchTable::VertexValenceTable & vTable = (*vertexValenceTable);
vTable.resize(_refiner.GetNumVerticesTotal() * SizePerVertex); vTable.resize(_refiner.GetNumVerticesTotal() * SizePerVertex);
int vOffset = 0; int vOffset = 0;

View File

@ -25,19 +25,19 @@
#ifndef OPENSUBDIV3_FAR_END_CAP_LEGACY_GREGORY_PATCH_FACTORY_H #ifndef OPENSUBDIV3_FAR_END_CAP_LEGACY_GREGORY_PATCH_FACTORY_H
#define 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 {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
class PatchTables; class PatchTable;
class TopologyRefiner; class TopologyRefiner;
namespace Far { namespace Far {
/// \brief This factory generates legacy (OpenSubdiv 2.x) gregory patches. /// \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. /// will be deprecated at some point.
/// ///
class EndCapLegacyGregoryPatchFactory { class EndCapLegacyGregoryPatchFactory {
@ -58,12 +58,12 @@ public:
/// @param levelVertOffset relative offset of patch vertex indices /// @param levelVertOffset relative offset of patch vertex indices
/// ///
ConstIndexArray GetPatchPoints(Vtr::Level const * level, Index faceIndex, ConstIndexArray GetPatchPoints(Vtr::Level const * level, Index faceIndex,
PatchTablesFactory::PatchFaceTag const * levelPatchTags, PatchTableFactory::PatchFaceTag const * levelPatchTags,
int levelVertOffset); int levelVertOffset);
void Finalize(int maxValence, void Finalize(int maxValence,
PatchTables::QuadOffsetsTable *quadOffsetsTable, PatchTable::QuadOffsetsTable *quadOffsetsTable,
PatchTables::VertexValenceTable *vertexValenceTable); PatchTable::VertexValenceTable *vertexValenceTable);
private: private:

View File

@ -24,7 +24,7 @@
#include "../far/gregoryBasis.h" #include "../far/gregoryBasis.h"
#include "../far/error.h" #include "../far/error.h"
#include "../far/stencilTablesFactory.h" #include "../far/stencilTableFactory.h"
#include "../far/topologyRefiner.h" #include "../far/topologyRefiner.h"
#include "../vtr/stackBuffer.h" #include "../vtr/stackBuffer.h"
@ -129,10 +129,10 @@ inline float csf(Index n, Index j) {
} }
} }
GregoryBasis::ProtoBasis::ProtoBasis( inline float computeCoefficient(int valence) {
Vtr::Level const & level, Index faceIndex, int fvarChannel) { // precomputed coefficient table up to valence 29
static float efTable[] = {
static float ef[MAX_VALENCE-3] = { 0, 0, 0,
0.812816f, 0.500000f, 0.363644f, 0.287514f, 0.812816f, 0.500000f, 0.363644f, 0.287514f,
0.238688f, 0.204544f, 0.179229f, 0.159657f, 0.238688f, 0.204544f, 0.179229f, 0.159657f,
0.144042f, 0.131276f, 0.120632f, 0.111614f, 0.144042f, 0.131276f, 0.120632f, 0.111614f,
@ -141,6 +141,16 @@ GregoryBasis::ProtoBasis::ProtoBasis(
0.0669851f, 0.0641504f, 0.0615475f, 0.0591488f, 0.0669851f, 0.0641504f, 0.0615475f, 0.0591488f,
0.0569311f, 0.0548745f, 0.0529621f 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) ? Vtr::ConstIndexArray facePoints = (fvarChannel<0) ?
level.getFaceVertices(faceIndex) : level.getFaceVertices(faceIndex) :
@ -248,8 +258,9 @@ GregoryBasis::ProtoBasis::ProtoBasis(
e1[vid] += e * csf(ivalence-3, 2*i+1); e1[vid] += e * csf(ivalence-3, 2*i+1);
} }
e0[vid] *= ef[ivalence-3]; float ef = computeCoefficient(ivalence);
e1[vid] *= ef[ivalence-3]; e0[vid] *= ef;
e1[vid] *= ef;
if (valence<0) { if (valence<0) {
@ -381,8 +392,8 @@ GregoryBasis::ProtoBasis::ProtoBasis(
} }
/*static*/ /*static*/
StencilTables * StencilTable *
GregoryBasis::CreateStencilTables(PointsVector const &stencils) { GregoryBasis::CreateStencilTable(PointsVector const &stencils) {
int nStencils = (int)stencils.size(); int nStencils = (int)stencils.size();
if (nStencils == 0) return NULL; if (nStencils == 0) return NULL;
@ -393,15 +404,15 @@ GregoryBasis::CreateStencilTables(PointsVector const &stencils) {
} }
// allocate destination // allocate destination
StencilTables *stencilTables = new StencilTables(); StencilTable *stencilTable = new StencilTable();
// XXX: do we need numControlVertices in stencilTables? // XXX: do we need numControlVertices in stencilTable?
stencilTables->_numControlVertices = 0; stencilTable->_numControlVertices = 0;
stencilTables->resize(nStencils, nElements); stencilTable->resize(nStencils, nElements);
int * sizes = &stencilTables->_sizes[0]; int * sizes = &stencilTable->_sizes[0];
Index * indices = &stencilTables->_indices[0]; Index * indices = &stencilTable->_indices[0];
float * weights = &stencilTables->_weights[0]; float * weights = &stencilTable->_weights[0];
for (int i = 0; i < nStencils; ++i) { for (int i = 0; i < nStencils; ++i) {
GregoryBasis::Point const &src = stencils[i]; GregoryBasis::Point const &src = stencils[i];
@ -415,9 +426,9 @@ GregoryBasis::CreateStencilTables(PointsVector const &stencils) {
weights += size; weights += size;
++sizes; ++sizes;
} }
stencilTables->generateOffsets(); stencilTable->generateOffsets();
return stencilTables; return stencilTable;
} }
} // end namespace Far } // end namespace Far

View File

@ -25,8 +25,9 @@
#ifndef OPENSUBDIV3_FAR_GREGORY_BASIS_H #ifndef OPENSUBDIV3_FAR_GREGORY_BASIS_H
#define OPENSUBDIV3_FAR_GREGORY_BASIS_H #define OPENSUBDIV3_FAR_GREGORY_BASIS_H
#include "../far/protoStencil.h"
#include "../vtr/level.h" #include "../vtr/level.h"
#include "../far/types.h"
#include "../far/stencilTable.h"
#include <cstring> #include <cstring>
namespace OpenSubdiv { namespace OpenSubdiv {
@ -59,7 +60,7 @@ public:
template <class T, class U> template <class T, class U>
void Evaluate(T const & controlValues, U values[20]) const { 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); float const * weights = &_weights.at(0);
for (int i=0; i<20; ++i) { 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 // Basis point
// //
@ -88,13 +79,19 @@ public:
// //
class Point { class Point {
public: 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; _size = 1;
_indices[0] = idx; _indices.push_back(idx);
_weights[0] = weight; _weights.push_back(weight);
} }
Point(Point const & other) { Point(Point const & other) {
@ -105,24 +102,24 @@ public:
return _size; return _size;
} }
Index const * GetIndices() const { Vtr::Index const * GetIndices() const {
return _indices; return &_indices[0];
} }
float const * GetWeights() const { float const * GetWeights() const {
return _weights; return &_weights[0];
} }
Point & operator = (Point const & other) { Point & operator = (Point const & other) {
_size = other._size; _size = other._size;
memcpy(_indices, other._indices, other._size*sizeof(Index)); _indices = other._indices;
memcpy(_weights, other._weights, other._size*sizeof(float)); _weights = other._weights;
return *this; return *this;
} }
Point & operator += (Point const & other) { Point & operator += (Point const & other) {
for (int i=0; i<other._size; ++i) { for (int i=0; i<other._size; ++i) {
Index idx = findIndex(other._indices[i]); Vtr::Index idx = findIndex(other._indices[i]);
_weights[idx] += other._weights[i]; _weights[idx] += other._weights[i];
} }
return *this; return *this;
@ -130,7 +127,7 @@ public:
Point & operator -= (Point const & other) { Point & operator -= (Point const & other) {
for (int i=0; i<other._size; ++i) { for (int i=0; i<other._size; ++i) {
Index idx = findIndex(other._indices[i]); Vtr::Index idx = findIndex(other._indices[i]);
_weights[idx] -= other._weights[i]; _weights[idx] -= other._weights[i];
} }
return *this; return *this;
@ -163,15 +160,15 @@ public:
Point p(*this); return p-=other; Point p(*this); return p-=other;
} }
void OffsetIndices(Index offset) { void OffsetIndices(Vtr::Index offset) {
for (int i=0; i<_size; ++i) { for (int i=0; i<_size; ++i) {
_indices[i] += offset; _indices[i] += offset;
} }
} }
void Copy(int ** size, Index ** indices, float ** weights) const { void Copy(int ** size, Vtr::Index ** indices, float ** weights) const {
memcpy(*indices, _indices, _size*sizeof(Index)); memcpy(*indices, &_indices[0], _size*sizeof(Vtr::Index));
memcpy(*weights, _weights, _size*sizeof(float)); memcpy(*weights, &_weights[0], _size*sizeof(float));
**size = _size; **size = _size;
*indices += _size; *indices += _size;
*weights += _size; *weights += _size;
@ -180,24 +177,21 @@ public:
private: private:
int findIndex(Index idx) { int findIndex(Vtr::Index idx) {
for (int i=0; i<_size; ++i) { for (int i=0; i<_size; ++i) {
if (_indices[i]==idx) { if (_indices[i]==idx) {
return i; return i;
} }
} }
_indices[_size]=idx; _indices.push_back(idx);
_weights[_size]=0.0f; _weights.push_back(0.0f);
++_size; ++_size;
return _size-1; return _size-1;
} }
int _size; int _size;
// XXXX this would really be better with VLA where we only allocate std::vector<Vtr::Index> _indices;
// space based on the max vertex valence in the mesh, not the absolute std::vector<float> _weights;
// maximum supported by the closed-form tangents table.
Index _indices[MAX_ELEMS];
float _weights[MAX_ELEMS];
}; };
// //
@ -208,11 +202,11 @@ public:
// //
struct ProtoBasis { 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; 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; void Copy(GregoryBasis* dest) const;
// Control Vertices based on : // Control Vertices based on :
@ -248,13 +242,13 @@ public:
typedef std::vector<GregoryBasis::Point> PointsVector; typedef std::vector<GregoryBasis::Point> PointsVector;
static StencilTables *CreateStencilTables(PointsVector const &stencils); static StencilTable *CreateStencilTable(PointsVector const &stencils);
private: private:
int _sizes[20]; int _sizes[20];
std::vector<Index> _indices; std::vector<Vtr::Index> _indices;
std::vector<float> _weights; std::vector<float> _weights;
}; };

View File

@ -30,8 +30,8 @@ namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
// Constructor // Constructor
PatchMap::PatchMap( PatchTables const & patchTables ) { PatchMap::PatchMap( PatchTable const & patchTable ) {
initialize( patchTables ); initialize( patchTable );
} }
// sets all the children to point to the patch of index patchIdx // 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 void
PatchMap::initialize( PatchTables const & patchTables ) { PatchMap::initialize( PatchTable const & patchTable ) {
int nfaces = 0, int nfaces = 0,
narrays = (int)patchTables.GetNumPatchArrays(), narrays = (int)patchTable.GetNumPatchArrays(),
npatches = (int)patchTables.GetNumPatchesTotal(); npatches = (int)patchTable.GetNumPatchesTotal();
if (not narrays or not npatches) if (not narrays or not npatches)
return; return;
@ -77,11 +77,11 @@ PatchMap::initialize( PatchTables const & patchTables ) {
for (int parray=0, current=0; parray<narrays; ++parray) { for (int parray=0, current=0; parray<narrays; ++parray) {
ConstPatchParamArray params = patchTables.GetPatchParams(parray); ConstPatchParamArray params = patchTable.GetPatchParams(parray);
int ringsize = patchTables.GetPatchArrayDescriptor(parray).GetNumControlVertices(); int ringsize = patchTable.GetPatchArrayDescriptor(parray).GetNumControlVertices();
for (Index j=0; j < patchTables.GetNumPatches(parray); ++j) { for (Index j=0; j < patchTable.GetNumPatches(parray); ++j) {
Handle & h = _handles[current]; Handle & h = _handles[current];
@ -107,9 +107,9 @@ PatchMap::initialize( PatchTables const & patchTables ) {
// populate the quadtree from the FarPatchArrays sub-patches // populate the quadtree from the FarPatchArrays sub-patches
for (Index parray=0, handleIndex=0; parray<narrays; ++parray) { for (Index parray=0, handleIndex=0; parray<narrays; ++parray) {
ConstPatchParamArray params = patchTables.GetPatchParams(parray); ConstPatchParamArray params = patchTable.GetPatchParams(parray);
for (int i=0; i < patchTables.GetNumPatches(parray); ++i, ++handleIndex) { for (int i=0; i < patchTable.GetNumPatches(parray); ++i, ++handleIndex) {
PatchParam::BitField bits = params[i].bitField; PatchParam::BitField bits = params[i].bitField;

View File

@ -27,7 +27,7 @@
#include "../version.h" #include "../version.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
#include <cassert> #include <cassert>
@ -38,7 +38,7 @@ namespace Far {
/// \brief An quadtree-based map connecting coarse faces to their sub-patches /// \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 /// surface of a mesh, sorted by their topological type. These arrays break the
/// connection between coarse faces and their sub-patches. /// connection between coarse faces and their sub-patches.
/// ///
@ -49,13 +49,13 @@ namespace Far {
class PatchMap { class PatchMap {
public: public:
typedef PatchTables::PatchHandle Handle; typedef PatchTable::PatchHandle Handle;
/// \brief Constructor /// \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). /// \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 /// Note : the faceid corresponds to quadrangulated face indices (ie. quads
@ -74,7 +74,7 @@ public:
private: private:
inline void initialize( PatchTables const & patchTables ); inline void initialize( PatchTable const & patchTable );
// Quadtree node with 4 children // Quadtree node with 4 children
struct QuadNode { struct QuadNode {

View File

@ -22,7 +22,7 @@
// language governing permissions and limitations under the Apache License. // language governing permissions and limitations under the Apache License.
// //
#include "../far/patchTables.h" #include "../far/patchTable.h"
#include "../far/patchBasis.h" #include "../far/patchBasis.h"
#include <cstring> #include <cstring>
@ -33,15 +33,15 @@ namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
PatchTables::PatchTables(int maxvalence) : PatchTable::PatchTable(int maxvalence) :
_maxValence(maxvalence), _maxValence(maxvalence),
_vertexStencilTables(NULL), _vertexStencilTable(NULL),
_varyingStencilTables(NULL) { _varyingStencilTable(NULL) {
} }
// Copy constructor // Copy constructor
// XXXX manuelk we need to eliminate this constructor (C++11 smart pointers) // 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), _maxValence(src._maxValence),
_numPtexFaces(src._numPtexFaces), _numPtexFaces(src._numPtexFaces),
_patchArrays(src._patchArrays), _patchArrays(src._patchArrays),
@ -49,29 +49,29 @@ PatchTables::PatchTables(PatchTables const & src) :
_paramTable(src._paramTable), _paramTable(src._paramTable),
_quadOffsetsTable(src._quadOffsetsTable), _quadOffsetsTable(src._quadOffsetsTable),
_vertexValenceTable(src._vertexValenceTable), _vertexValenceTable(src._vertexValenceTable),
_vertexStencilTables(NULL), _vertexStencilTable(NULL),
_varyingStencilTables(NULL), _varyingStencilTable(NULL),
_fvarChannels(src._fvarChannels), _fvarChannels(src._fvarChannels),
_sharpnessIndices(src._sharpnessIndices), _sharpnessIndices(src._sharpnessIndices),
_sharpnessValues(src._sharpnessValues) { _sharpnessValues(src._sharpnessValues) {
if (src._vertexStencilTables) { if (src._vertexStencilTable) {
_vertexStencilTables = new StencilTables(*src._vertexStencilTables); _vertexStencilTable = new StencilTable(*src._vertexStencilTable);
} }
if (src._varyingStencilTables) { if (src._varyingStencilTable) {
_varyingStencilTables = new StencilTables(*src._varyingStencilTables); _varyingStencilTable = new StencilTable(*src._varyingStencilTable);
} }
} }
PatchTables::~PatchTables() { PatchTable::~PatchTable() {
delete _vertexStencilTables; delete _vertexStencilTable;
delete _varyingStencilTables; delete _varyingStencilTable;
} }
// //
// PatchArrays // PatchArrays
// //
struct PatchTables::PatchArray { struct PatchTable::PatchArray {
PatchArray(PatchDescriptor d, int np, Index v, Index p, Index qo) : PatchArray(PatchDescriptor d, int np, Index v, Index p, Index qo) :
desc(d), numPatches(np), vertIndex(v), desc(d), numPatches(np), vertIndex(v),
@ -91,24 +91,24 @@ struct PatchTables::PatchArray {
// debug helper // debug helper
void void
PatchTables::PatchArray::print() const { PatchTable::PatchArray::print() const {
desc.print(); desc.print();
printf(" numPatches=%d vertIndex=%d patchIndex=%d " printf(" numPatches=%d vertIndex=%d patchIndex=%d "
"quadOffsetIndex=%d\n", numPatches, vertIndex, patchIndex, "quadOffsetIndex=%d\n", numPatches, vertIndex, patchIndex,
quadOffsetIndex); quadOffsetIndex);
} }
inline PatchTables::PatchArray & inline PatchTable::PatchArray &
PatchTables::getPatchArray(Index arrayIndex) { PatchTable::getPatchArray(Index arrayIndex) {
assert(arrayIndex<(Index)GetNumPatchArrays()); assert(arrayIndex<(Index)GetNumPatchArrays());
return _patchArrays[arrayIndex]; return _patchArrays[arrayIndex];
} }
inline PatchTables::PatchArray const & inline PatchTable::PatchArray const &
PatchTables::getPatchArray(Index arrayIndex) const { PatchTable::getPatchArray(Index arrayIndex) const {
assert(arrayIndex<(Index)GetNumPatchArrays()); assert(arrayIndex<(Index)GetNumPatchArrays());
return _patchArrays[arrayIndex]; return _patchArrays[arrayIndex];
} }
void void
PatchTables::reservePatchArrays(int numPatchArrays) { PatchTable::reservePatchArrays(int numPatchArrays) {
_patchArrays.reserve(numPatchArrays); _patchArrays.reserve(numPatchArrays);
} }
@ -117,16 +117,16 @@ PatchTables::reservePatchArrays(int numPatchArrays) {
// //
// Stores a record for each patch in the primitive : // 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 // 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 // can therefore be quickly accessed by using the patch primitive ID as
// index into patchValueOffsets to locate the face-varying control vertex // index into patchValueOffsets to locate the face-varying control vertex
// indices. // indices.
// //
// - Face-varying channels can have a different interpolation modes // - 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. // for face-varying patches.
// //
// - No transition patterns means vertex indices of face-varying patches can // - 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 // similar to single-crease to resolve this condition without requiring
// isolation if possible // isolation if possible
// //
struct PatchTables::FVarPatchChannel { struct PatchTable::FVarPatchChannel {
// Channel interpolation mode // Channel interpolation mode
Sdc::Options::FVarLinearInterpolation interpolation; Sdc::Options::FVarLinearInterpolation interpolation;
@ -157,22 +157,22 @@ struct PatchTables::FVarPatchChannel {
std::vector<Index> patchValues; // point values for each patch std::vector<Index> patchValues; // point values for each patch
}; };
inline PatchTables::FVarPatchChannel & inline PatchTable::FVarPatchChannel &
PatchTables::getFVarPatchChannel(int channel) { PatchTable::getFVarPatchChannel(int channel) {
assert(channel<(int)_fvarChannels.size()); assert(channel<(int)_fvarChannels.size());
return _fvarChannels[channel]; return _fvarChannels[channel];
} }
inline PatchTables::FVarPatchChannel const & inline PatchTable::FVarPatchChannel const &
PatchTables::getFVarPatchChannel(int channel) const { PatchTable::getFVarPatchChannel(int channel) const {
assert(channel<(int)_fvarChannels.size()); assert(channel<(int)_fvarChannels.size());
return _fvarChannels[channel]; return _fvarChannels[channel];
} }
void void
PatchTables::allocateFVarPatchChannels(int numChannels) { PatchTable::allocateFVarPatchChannels(int numChannels) {
_fvarChannels.resize(numChannels); _fvarChannels.resize(numChannels);
} }
void void
PatchTables::allocateChannelValues(int channel, PatchTable::allocateChannelValues(int channel,
int numPatches, int numVerticesTotal) { int numPatches, int numVerticesTotal) {
FVarPatchChannel & c = getFVarPatchChannel(channel); FVarPatchChannel & c = getFVarPatchChannel(channel);
@ -192,22 +192,22 @@ PatchTables::allocateChannelValues(int channel,
} }
} }
void void
PatchTables::setFVarPatchChannelLinearInterpolation(int channel, PatchTable::setFVarPatchChannelLinearInterpolation(int channel,
Sdc::Options::FVarLinearInterpolation interpolation) { Sdc::Options::FVarLinearInterpolation interpolation) {
FVarPatchChannel & c = getFVarPatchChannel(channel); FVarPatchChannel & c = getFVarPatchChannel(channel);
c.interpolation = interpolation; c.interpolation = interpolation;
} }
void void
PatchTables::setFVarPatchChannelPatchesType(int channel, PatchDescriptor::Type type) { PatchTable::setFVarPatchChannelPatchesType(int channel, PatchDescriptor::Type type) {
FVarPatchChannel & c = getFVarPatchChannel(channel); FVarPatchChannel & c = getFVarPatchChannel(channel);
c.patchesType = type; c.patchesType = type;
} }
void void
PatchTables::setBicubicFVarPatchChannelValues(int channel, int patchSize, PatchTable::setBicubicFVarPatchChannelValues(int channel, int patchSize,
std::vector<Index> const & values) { std::vector<Index> const & values) {
// This method populates the sparse array of values held in the patch // 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. // the second traversal of an adaptive TopologyRefiner.
// It is assumed that the patch types have been stored in the channel's // It is assumed that the patch types have been stored in the channel's
// 'patchTypes' vector during the first traversal. // 'patchTypes' vector during the first traversal.
@ -245,7 +245,7 @@ PatchTables::setBicubicFVarPatchChannelValues(int channel, int patchSize,
} }
// //
// PatchTables // PatchTable
// //
inline int inline int
@ -254,7 +254,7 @@ getPatchSize(PatchDescriptor desc) {
} }
void void
PatchTables::pushPatchArray(PatchDescriptor desc, int npatches, PatchTable::pushPatchArray(PatchDescriptor desc, int npatches,
Index * vidx, Index * pidx, Index * qoidx) { Index * vidx, Index * pidx, Index * qoidx) {
if (npatches>0) { if (npatches>0) {
@ -271,52 +271,52 @@ PatchTables::pushPatchArray(PatchDescriptor desc, int npatches,
} }
int int
PatchTables::getPatchIndex(int arrayIndex, int patchIndex) const { PatchTable::getPatchIndex(int arrayIndex, int patchIndex) const {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
assert(patchIndex<pa.numPatches); assert(patchIndex<pa.numPatches);
return pa.patchIndex + patchIndex; return pa.patchIndex + patchIndex;
} }
Index * Index *
PatchTables::getSharpnessIndices(int arrayIndex) { PatchTable::getSharpnessIndices(int arrayIndex) {
return &_sharpnessIndices[getPatchArray(arrayIndex).patchIndex]; return &_sharpnessIndices[getPatchArray(arrayIndex).patchIndex];
} }
float * float *
PatchTables::getSharpnessValues(int arrayIndex) { PatchTable::getSharpnessValues(int arrayIndex) {
return &_sharpnessValues[getPatchArray(arrayIndex).patchIndex]; return &_sharpnessValues[getPatchArray(arrayIndex).patchIndex];
} }
PatchDescriptor PatchDescriptor
PatchTables::GetPatchDescriptor(PatchHandle const & handle) const { PatchTable::GetPatchDescriptor(PatchHandle const & handle) const {
return getPatchArray(handle.arrayIndex).desc; return getPatchArray(handle.arrayIndex).desc;
} }
PatchDescriptor PatchDescriptor
PatchTables::GetPatchArrayDescriptor(int arrayIndex) const { PatchTable::GetPatchArrayDescriptor(int arrayIndex) const {
return getPatchArray(arrayIndex).desc; return getPatchArray(arrayIndex).desc;
} }
int int
PatchTables::GetNumPatchArrays() const { PatchTable::GetNumPatchArrays() const {
return (int)_patchArrays.size(); return (int)_patchArrays.size();
} }
int int
PatchTables::GetNumPatches(int arrayIndex) const { PatchTable::GetNumPatches(int arrayIndex) const {
return getPatchArray(arrayIndex).numPatches; return getPatchArray(arrayIndex).numPatches;
} }
int int
PatchTables::GetNumPatchesTotal() const { PatchTable::GetNumPatchesTotal() const {
// there is one PatchParam record for each patch in the mesh // there is one PatchParam record for each patch in the mesh
return (int)_paramTable.size(); return (int)_paramTable.size();
} }
int int
PatchTables::GetNumControlVertices(int arrayIndex) const { PatchTable::GetNumControlVertices(int arrayIndex) const {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
return pa.numPatches * getPatchSize(pa.desc); return pa.numPatches * getPatchSize(pa.desc);
} }
Index Index
PatchTables::findPatchArray(PatchDescriptor desc) { PatchTable::findPatchArray(PatchDescriptor desc) {
for (int i=0; i<(int)_patchArrays.size(); ++i) { for (int i=0; i<(int)_patchArrays.size(); ++i) {
if (_patchArrays[i].desc==desc) if (_patchArrays[i].desc==desc)
return i; return i;
@ -324,14 +324,14 @@ PatchTables::findPatchArray(PatchDescriptor desc) {
return Vtr::INDEX_INVALID; return Vtr::INDEX_INVALID;
} }
IndexArray IndexArray
PatchTables::getPatchArrayVertices(int arrayIndex) { PatchTable::getPatchArrayVertices(int arrayIndex) {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
int size = getPatchSize(pa.desc); int size = getPatchSize(pa.desc);
assert(pa.vertIndex<(Index)_patchVerts.size()); assert(pa.vertIndex<(Index)_patchVerts.size());
return IndexArray(&_patchVerts[pa.vertIndex], pa.numPatches * size); return IndexArray(&_patchVerts[pa.vertIndex], pa.numPatches * size);
} }
ConstIndexArray ConstIndexArray
PatchTables::GetPatchArrayVertices(int arrayIndex) const { PatchTable::GetPatchArrayVertices(int arrayIndex) const {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
int size = getPatchSize(pa.desc); int size = getPatchSize(pa.desc);
assert(pa.vertIndex<(Index)_patchVerts.size()); assert(pa.vertIndex<(Index)_patchVerts.size());
@ -339,13 +339,13 @@ PatchTables::GetPatchArrayVertices(int arrayIndex) const {
} }
ConstIndexArray ConstIndexArray
PatchTables::GetPatchVertices(PatchHandle const & handle) const { PatchTable::GetPatchVertices(PatchHandle const & handle) const {
PatchArray const & pa = getPatchArray(handle.arrayIndex); PatchArray const & pa = getPatchArray(handle.arrayIndex);
Index vert = pa.vertIndex + handle.vertIndex; Index vert = pa.vertIndex + handle.vertIndex;
return ConstIndexArray(&_patchVerts[vert], getPatchSize(pa.desc)); return ConstIndexArray(&_patchVerts[vert], getPatchSize(pa.desc));
} }
ConstIndexArray ConstIndexArray
PatchTables::GetPatchVertices(int arrayIndex, int patchIndex) const { PatchTable::GetPatchVertices(int arrayIndex, int patchIndex) const {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
int size = getPatchSize(pa.desc); int size = getPatchSize(pa.desc);
assert((pa.vertIndex + patchIndex*size)<(Index)_patchVerts.size()); assert((pa.vertIndex + patchIndex*size)<(Index)_patchVerts.size());
@ -353,29 +353,29 @@ PatchTables::GetPatchVertices(int arrayIndex, int patchIndex) const {
} }
PatchParam PatchParam
PatchTables::GetPatchParam(PatchHandle const & handle) const { PatchTable::GetPatchParam(PatchHandle const & handle) const {
assert(handle.patchIndex < (Index)_paramTable.size()); assert(handle.patchIndex < (Index)_paramTable.size());
return _paramTable[handle.patchIndex]; return _paramTable[handle.patchIndex];
} }
PatchParam PatchParam
PatchTables::GetPatchParam(int arrayIndex, int patchIndex) const { PatchTable::GetPatchParam(int arrayIndex, int patchIndex) const {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
assert((pa.patchIndex + patchIndex) < (int)_paramTable.size()); assert((pa.patchIndex + patchIndex) < (int)_paramTable.size());
return _paramTable[pa.patchIndex + patchIndex]; return _paramTable[pa.patchIndex + patchIndex];
} }
PatchParamArray PatchParamArray
PatchTables::getPatchParams(int arrayIndex) { PatchTable::getPatchParams(int arrayIndex) {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
return PatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches); return PatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches);
} }
ConstPatchParamArray const ConstPatchParamArray const
PatchTables::GetPatchParams(int arrayIndex) const { PatchTable::GetPatchParams(int arrayIndex) const {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
return ConstPatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches); return ConstPatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches);
} }
float float
PatchTables::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const { PatchTable::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const {
assert((handle.patchIndex) < (int)_sharpnessIndices.size()); assert((handle.patchIndex) < (int)_sharpnessIndices.size());
Index index = _sharpnessIndices[handle.patchIndex]; Index index = _sharpnessIndices[handle.patchIndex];
if (index == Vtr::INDEX_INVALID) { if (index == Vtr::INDEX_INVALID) {
@ -385,7 +385,7 @@ PatchTables::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) cons
return _sharpnessValues[index]; return _sharpnessValues[index];
} }
float float
PatchTables::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex) const { PatchTable::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex) const {
PatchArray const & pa = getPatchArray(arrayIndex); PatchArray const & pa = getPatchArray(arrayIndex);
assert((pa.patchIndex + patchIndex) < (int)_sharpnessIndices.size()); assert((pa.patchIndex + patchIndex) < (int)_sharpnessIndices.size());
Index index = _sharpnessIndices[pa.patchIndex + patchIndex]; Index index = _sharpnessIndices[pa.patchIndex + patchIndex];
@ -396,13 +396,13 @@ PatchTables::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex)
return _sharpnessValues[index]; return _sharpnessValues[index];
} }
PatchTables::ConstQuadOffsetsArray PatchTable::ConstQuadOffsetsArray
PatchTables::GetPatchQuadOffsets(PatchHandle const & handle) const { PatchTable::GetPatchQuadOffsets(PatchHandle const & handle) const {
PatchArray const & pa = getPatchArray(handle.arrayIndex); PatchArray const & pa = getPatchArray(handle.arrayIndex);
return Vtr::ConstArray<unsigned int>(&_quadOffsetsTable[pa.quadOffsetIndex + handle.vertIndex], 4); return Vtr::ConstArray<unsigned int>(&_quadOffsetsTable[pa.quadOffsetIndex + handle.vertIndex], 4);
} }
bool bool
PatchTables::IsFeatureAdaptive() const { PatchTable::IsFeatureAdaptive() const {
// XXX: // XXX:
// revisit this function, since we'll add uniform cubic patches later. // revisit this function, since we'll add uniform cubic patches later.
@ -418,22 +418,22 @@ PatchTables::IsFeatureAdaptive() const {
} }
int int
PatchTables::GetNumFVarChannels() const { PatchTable::GetNumFVarChannels() const {
return (int)_fvarChannels.size(); return (int)_fvarChannels.size();
} }
Sdc::Options::FVarLinearInterpolation Sdc::Options::FVarLinearInterpolation
PatchTables::GetFVarChannelLinearInterpolation(int channel) const { PatchTable::GetFVarChannelLinearInterpolation(int channel) const {
FVarPatchChannel const & c = getFVarPatchChannel(channel); FVarPatchChannel const & c = getFVarPatchChannel(channel);
return c.interpolation; return c.interpolation;
} }
Vtr::Array<PatchDescriptor::Type> Vtr::Array<PatchDescriptor::Type>
PatchTables::getFVarPatchTypes(int channel) { PatchTable::getFVarPatchTypes(int channel) {
FVarPatchChannel & c = getFVarPatchChannel(channel); FVarPatchChannel & c = getFVarPatchChannel(channel);
return Vtr::Array<PatchDescriptor::Type>(&c.patchTypes[0], return Vtr::Array<PatchDescriptor::Type>(&c.patchTypes[0],
(int)c.patchTypes.size()); (int)c.patchTypes.size());
} }
Vtr::ConstArray<PatchDescriptor::Type> Vtr::ConstArray<PatchDescriptor::Type>
PatchTables::GetFVarPatchTypes(int channel) const { PatchTable::GetFVarPatchTypes(int channel) const {
FVarPatchChannel const & c = getFVarPatchChannel(channel); FVarPatchChannel const & c = getFVarPatchChannel(channel);
if (c.patchesType!=PatchDescriptor::NON_PATCH) { if (c.patchesType!=PatchDescriptor::NON_PATCH) {
return Vtr::ConstArray<PatchDescriptor::Type>(&c.patchesType, 1); return Vtr::ConstArray<PatchDescriptor::Type>(&c.patchesType, 1);
@ -443,17 +443,17 @@ PatchTables::GetFVarPatchTypes(int channel) const {
} }
} }
ConstIndexArray ConstIndexArray
PatchTables::GetFVarPatchesValues(int channel) const { PatchTable::GetFVarPatchesValues(int channel) const {
FVarPatchChannel const & c = getFVarPatchChannel(channel); FVarPatchChannel const & c = getFVarPatchChannel(channel);
return ConstIndexArray(&c.patchValues[0], (int)c.patchValues.size()); return ConstIndexArray(&c.patchValues[0], (int)c.patchValues.size());
} }
IndexArray IndexArray
PatchTables::getFVarPatchesValues(int channel) { PatchTable::getFVarPatchesValues(int channel) {
FVarPatchChannel & c = getFVarPatchChannel(channel); FVarPatchChannel & c = getFVarPatchChannel(channel);
return IndexArray(&c.patchValues[0], (int)c.patchValues.size()); return IndexArray(&c.patchValues[0], (int)c.patchValues.size());
} }
PatchDescriptor::Type PatchDescriptor::Type
PatchTables::getFVarPatchType(int channel, int patch) const { PatchTable::getFVarPatchType(int channel, int patch) const {
FVarPatchChannel const & c = getFVarPatchChannel(channel); FVarPatchChannel const & c = getFVarPatchChannel(channel);
PatchDescriptor::Type type; PatchDescriptor::Type type;
if (c.patchesType!=PatchDescriptor::NON_PATCH) { if (c.patchesType!=PatchDescriptor::NON_PATCH) {
@ -466,15 +466,15 @@ PatchTables::getFVarPatchType(int channel, int patch) const {
return type; return type;
} }
PatchDescriptor::Type PatchDescriptor::Type
PatchTables::GetFVarPatchType(int channel, PatchHandle const & handle) const { PatchTable::GetFVarPatchType(int channel, PatchHandle const & handle) const {
return getFVarPatchType(channel, handle.patchIndex); return getFVarPatchType(channel, handle.patchIndex);
} }
PatchDescriptor::Type 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)); return getFVarPatchType(channel, getPatchIndex(arrayIndex, patchIndex));
} }
ConstIndexArray ConstIndexArray
PatchTables::getFVarPatchValues(int channel, int patch) const { PatchTable::getFVarPatchValues(int channel, int patch) const {
FVarPatchChannel const & c = getFVarPatchChannel(channel); FVarPatchChannel const & c = getFVarPatchChannel(channel);
@ -489,17 +489,17 @@ PatchTables::getFVarPatchValues(int channel, int patch) const {
} }
} }
ConstIndexArray ConstIndexArray
PatchTables::GetFVarPatchValues(int channel, PatchHandle const & handle) const { PatchTable::GetFVarPatchValues(int channel, PatchHandle const & handle) const {
return getFVarPatchValues(channel, handle.patchIndex); return getFVarPatchValues(channel, handle.patchIndex);
} }
ConstIndexArray 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)); return getFVarPatchValues(channel, getPatchIndex(arrayIndex, patchIndex));
} }
void void
PatchTables::print() const { PatchTable::print() const {
printf("patchTables (0x%p)\n", this); printf("patchTable (0x%p)\n", this);
printf(" numPatches = %d\n", GetNumPatchesTotal()); printf(" numPatches = %d\n", GetNumPatchesTotal());
for (int i=0; i<GetNumPatchArrays(); ++i) { for (int i=0; i<GetNumPatchArrays(); ++i) {
printf(" patchArray %d:\n", i); printf(" patchArray %d:\n", i);
@ -512,7 +512,7 @@ PatchTables::print() const {
// Evaluate basis functions for position and first derivatives at (s,t): // Evaluate basis functions for position and first derivatives at (s,t):
// //
void void
PatchTables::EvaluateBasis(PatchHandle const & handle, float s, float t, PatchTable::EvaluateBasis(PatchHandle const & handle, float s, float t,
float wP[], float wDs[], float wDt[]) const { float wP[], float wDs[], float wDt[]) const {
PatchDescriptor::Type patchType = GetPatchArrayDescriptor(handle.arrayIndex).GetType(); PatchDescriptor::Type patchType = GetPatchArrayDescriptor(handle.arrayIndex).GetType();

View File

@ -22,14 +22,14 @@
// language governing permissions and limitations under the Apache License. // language governing permissions and limitations under the Apache License.
// //
#ifndef OPENSUBDIV3_FAR_PATCH_TABLES_H #ifndef OPENSUBDIV3_FAR_PATCH_TABLE_H
#define OPENSUBDIV3_FAR_PATCH_TABLES_H #define OPENSUBDIV3_FAR_PATCH_TABLE_H
#include "../version.h" #include "../version.h"
#include "../far/patchDescriptor.h" #include "../far/patchDescriptor.h"
#include "../far/patchParam.h" #include "../far/patchParam.h"
#include "../far/stencilTables.h" #include "../far/stencilTable.h"
#include "../sdc/options.h" #include "../sdc/options.h"
@ -46,26 +46,26 @@ namespace Far {
/// \brief Container for arrays of parametric patches /// \brief Container for arrays of parametric patches
/// ///
/// PatchTables contain topology and parametric information about the patches /// PatchTable contain topology and parametric information about the patches
/// generated by the Refinement process. Patches in the tables are sorted into /// generated by the Refinement process. Patches in the table are sorted into
/// arrays based on their PatchDescriptor Type. /// arrays based on their PatchDescriptor Type.
/// ///
/// Note : PatchTables can be accessed either using a PatchHandle or a /// Note : PatchTable can be accessed either using a PatchHandle or a
/// combination of array and patch indices. /// combination of array and patch indices.
/// ///
/// XXXX manuelk we should add a PatchIterator that can dereference into /// XXXX manuelk we should add a PatchIterator that can dereference into
/// a PatchHandle for fast linear traversal of the tables /// a PatchHandle for fast linear traversal of the table
/// ///
class PatchTables { class PatchTable {
public: public:
/// \brief Handle that can be used as unique patch identifier within PatchTables /// \brief Handle that can be used as unique patch identifier within PatchTable
class PatchHandle { class PatchHandle {
// XXXX manuelk members will eventually be made private // XXXX manuelk members will eventually be made private
public: public:
friend class PatchTables; friend class PatchTable;
friend class PatchMap; friend class PatchMap;
Index arrayIndex, // Array index of the patch Index arrayIndex, // Array index of the patch
@ -76,20 +76,20 @@ public:
public: public:
/// \brief Copy constructor /// \brief Copy constructor
PatchTables(PatchTables const & src); PatchTable(PatchTable const & src);
/// \brief Destructor /// \brief Destructor
~PatchTables(); ~PatchTable();
/// \brief True if the patches are of feature adaptive types /// \brief True if the patches are of feature adaptive types
bool IsFeatureAdaptive() const; bool IsFeatureAdaptive() const;
/// \brief Returns the total number of control vertex indices in the tables /// \brief Returns the total number of control vertex indices in the table
int GetNumControlVerticesTotal() const { int GetNumControlVerticesTotal() const {
return (int)_patchVerts.size(); return (int)_patchVerts.size();
} }
/// \brief Returns the total number of patches stored in the tables /// \brief Returns the total number of patches stored in the table
int GetNumPatchesTotal() const; int GetNumPatchesTotal() const;
/// \brief Returns max vertex valence /// \brief Returns max vertex valence
@ -172,16 +172,16 @@ public:
return _vertexValenceTable; return _vertexValenceTable;
} }
/// \brief Returns the basis conversion stencil tables to get endcap patch points. /// \brief Returns the basis conversion stencil table to get endcap patch points.
/// This stencil is relative to the max level refined vertices. /// This stencil is relative to the max level refined vertices.
StencilTables const *GetEndCapVertexStencilTables() const { StencilTable const *GetEndCapVertexStencilTable() const {
return _vertexStencilTables; return _vertexStencilTable;
} }
/// \brief Returns the varying stencil tables for the endcap patches /// \brief Returns the varying stencil table for the endcap patches
/// which has same ordering as the endcap vertex stencil tables. /// which has same ordering as the endcap vertex stencil table.
StencilTables const *GetEndCapVaryingStencilTables() const { StencilTable const *GetEndCapVaryingStencilTable() const {
return _varyingStencilTables; return _varyingStencilTable;
} }
//@} //@}
@ -304,10 +304,10 @@ public:
protected: protected:
friend class PatchTablesFactory; friend class PatchTableFactory;
// Factory constructor // Factory constructor
PatchTables(int maxvalence); PatchTable(int maxvalence);
Index getPatchIndex(int array, int patch) const; Index getPatchIndex(int array, int patch) const;
@ -386,8 +386,8 @@ private:
// //
QuadOffsetsTable _quadOffsetsTable; // Quad offsets (for Gregory patches) QuadOffsetsTable _quadOffsetsTable; // Quad offsets (for Gregory patches)
VertexValenceTable _vertexValenceTable; // Vertex valence table (for Gregory patches) VertexValenceTable _vertexValenceTable; // Vertex valence table (for Gregory patches)
StencilTables const * _vertexStencilTables; // endcap basis conversion stencils StencilTable const * _vertexStencilTable; // endcap basis conversion stencils
StencilTables const * _varyingStencilTables; // endcap varying stencils (for convenience) StencilTable const * _varyingStencilTable; // endcap varying stencils (for convenience)
// //
// Face-varying data // Face-varying data
@ -410,4 +410,4 @@ using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv } // end namespace OpenSubdiv
#endif /* OPENSUBDIV3_FAR_PATCH_TABLES */ #endif /* OPENSUBDIV3_FAR_PATCH_TABLE */

View File

@ -21,7 +21,7 @@
// KIND, either express or implied. See the Apache License for the specific // KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License. // language governing permissions and limitations under the Apache License.
// //
#include "../far/patchTablesFactory.h" #include "../far/patchTableFactory.h"
#include "../far/error.h" #include "../far/error.h"
#include "../far/ptexIndices.h" #include "../far/ptexIndices.h"
#include "../far/topologyRefiner.h" #include "../far/topologyRefiner.h"
@ -91,12 +91,12 @@ typedef PatchTypes<Far::Index **> PatchFVarPointers;
namespace Far { namespace Far {
void void
PatchTablesFactory::PatchFaceTag::clear() { PatchTableFactory::PatchFaceTag::clear() {
std::memset(this, 0, sizeof(*this)); std::memset(this, 0, sizeof(*this));
} }
void 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 // 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 // where the boundary/corner occurs and whether boundary or corner -- so using a
@ -134,7 +134,7 @@ PatchTablesFactory::PatchFaceTag::assignBoundaryPropertiesFromEdgeMask(int bound
} }
void 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 // 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 // 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 // The patch vertices for boundary and corner patches
// are assigned index values even though indices will // are assigned index values even though indices will
// be undefined along boundary and corner edges. // 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 // as indices for drawing, it is convenient for invalid
// indices to be replaced with known good values, such // indices to be replaced with known good values, such
// as the first un-permuted index, which is the index // as the first un-permuted index, which is the index
@ -217,7 +217,7 @@ class FVarChannelCursor {
public: public:
FVarChannelCursor(TopologyRefiner const & refiner, FVarChannelCursor(TopologyRefiner const & refiner,
PatchTablesFactory::Options options) { PatchTableFactory::Options options) {
if (options.generateFVarTables) { if (options.generateFVarTables) {
// If client-code does not select specific channels, default to all // If client-code does not select specific channels, default to all
// the channels in the refiner. // the channels in the refiner.
@ -278,13 +278,13 @@ private:
// Adaptive Context // Adaptive Context
// //
// Helper class aggregating transient contextual data structures during the // 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. // the function prototypes of high-level private methods in the factory.
// This helps keeping the factory class stateless. // This helps keeping the factory class stateless.
// //
// Note : struct members are not re-entrant nor are they intended to be ! // Note : struct members are not re-entrant nor are they intended to be !
// //
struct PatchTablesFactory::AdaptiveContext { struct PatchTableFactory::AdaptiveContext {
public: public:
AdaptiveContext(TopologyRefiner const & refiner, Options options); AdaptiveContext(TopologyRefiner const & refiner, Options options);
@ -293,8 +293,8 @@ public:
Options const options; Options const options;
// The patch tables being created // The patch table being created
PatchTables * tables; PatchTable * table;
public: public:
@ -341,16 +341,16 @@ public:
}; };
// Constructor // Constructor
PatchTablesFactory::AdaptiveContext::AdaptiveContext( PatchTableFactory::AdaptiveContext::AdaptiveContext(
TopologyRefiner const & ref, Options opts) : TopologyRefiner const & ref, Options opts) :
refiner(ref), options(opts), tables(0), refiner(ref), options(opts), table(0),
fvarChannelCursor(ref, opts) { fvarChannelCursor(ref, opts) {
fvarPatchValues.resize(fvarChannelCursor.size()); fvarPatchValues.resize(fvarChannelCursor.size());
} }
void void
PatchTablesFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) { PatchTableFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) {
FVarChannelCursor & fvc = fvarChannelCursor; FVarChannelCursor & fvc = fvarChannelCursor;
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
@ -367,31 +367,31 @@ PatchTablesFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) {
} }
bool bool
PatchTablesFactory::AdaptiveContext::RequiresFVarPatches() const { PatchTableFactory::AdaptiveContext::RequiresFVarPatches() const {
return not fvarPatchValues.empty(); 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 void
PatchTablesFactory::allocateVertexTables(PatchTables * tables, int /* nlevels */, bool hasSharpness) { PatchTableFactory::allocateVertexTables(PatchTable * table, int /* nlevels */, bool hasSharpness) {
int ncvs = 0, npatches = 0; int ncvs = 0, npatches = 0;
for (int i=0; i<tables->GetNumPatchArrays(); ++i) { for (int i=0; i<table->GetNumPatchArrays(); ++i) {
npatches += tables->GetNumPatches(i); npatches += table->GetNumPatches(i);
ncvs += tables->GetNumControlVertices(i); ncvs += table->GetNumControlVertices(i);
} }
if (ncvs==0 or npatches==0) if (ncvs==0 or npatches==0)
return; return;
tables->_patchVerts.resize( ncvs ); table->_patchVerts.resize( ncvs );
tables->_paramTable.resize( npatches ); table->_paramTable.resize( npatches );
if (hasSharpness) { 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 // Allocate face-varying tables
// //
void void
PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner, PatchTableFactory::allocateFVarChannels(TopologyRefiner const & refiner,
Options options, int npatches, PatchTables * tables) { Options options, int npatches, PatchTable * table) {
assert(options.generateFVarTables and 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 // Create a channel cursor to iterate over client-selected channels or
// default to the channels found in the TopologyRefiner // default to the channels found in the TopologyRefiner
@ -412,7 +412,7 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner,
return; return;
} }
tables->allocateFVarPatchChannels(fvc.size()); table->allocateFVarPatchChannels(fvc.size());
// Iterate with the cursor to initialize each channel // Iterate with the cursor to initialize each channel
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
@ -420,7 +420,7 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner,
Sdc::Options::FVarLinearInterpolation interpolation = Sdc::Options::FVarLinearInterpolation interpolation =
refiner.GetFVarLinearInterpolation(*fvc); refiner.GetFVarLinearInterpolation(*fvc);
tables->setFVarPatchChannelLinearInterpolation(fvc.pos(), interpolation); table->setFVarPatchChannelLinearInterpolation(fvc.pos(), interpolation);
int nverts = 0; int nverts = 0;
if (interpolation==Sdc::Options::FVAR_LINEAR_ALL) { if (interpolation==Sdc::Options::FVAR_LINEAR_ALL) {
@ -428,20 +428,20 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner,
PatchDescriptor::Type type = options.triangulateQuads ? PatchDescriptor::Type type = options.triangulateQuads ?
PatchDescriptor::TRIANGLES : PatchDescriptor::QUADS; PatchDescriptor::TRIANGLES : PatchDescriptor::QUADS;
tables->setFVarPatchChannelPatchesType(fvc.pos(), type); table->setFVarPatchChannelPatchesType(fvc.pos(), type);
nverts = nverts =
npatches * PatchDescriptor::GetNumFVarControlVertices(type); npatches * PatchDescriptor::GetNumFVarControlVertices(type);
} }
tables->allocateChannelValues(fvc.pos(), npatches, nverts); table->allocateChannelValues(fvc.pos(), npatches, nverts);
} }
} }
// gather face-varying patch points // gather face-varying patch points
int int
PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level, PatchTableFactory::gatherFVarData(AdaptiveContext & context, int level,
Index faceIndex, Index levelFaceOffset, int rotation, Index faceIndex, Index levelFaceOffset, int rotation,
Index const * levelFVarVertOffsets, Index fofss, Index ** fptrs) { Index const * levelFVarVertOffsets, Index fofss, Index ** fptrs) {
@ -451,7 +451,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
TopologyRefiner const & refiner = context.refiner; TopologyRefiner const & refiner = context.refiner;
PatchTables * tables = context.tables; PatchTable * table = context.table;
assert((levelFaceOffset + faceIndex)<(int)context.patchTags.size()); assert((levelFaceOffset + faceIndex)<(int)context.patchTags.size());
PatchFaceTag & vertexPatchTag = context.patchTags[levelFaceOffset + faceIndex]; PatchFaceTag & vertexPatchTag = context.patchTags[levelFaceOffset + faceIndex];
@ -572,7 +572,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
} }
Vtr::Array<PatchDescriptor::Type> patchTypes = Vtr::Array<PatchDescriptor::Type> patchTypes =
tables->getFVarPatchTypes(fvc.pos()); table->getFVarPatchTypes(fvc.pos());
assert(not patchTypes.empty()); assert(not patchTypes.empty());
patchTypes[fofss] = fvarPatchType; patchTypes[fofss] = fvarPatchType;
@ -652,7 +652,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
// a pointer to the next descriptor // a pointer to the next descriptor
// //
PatchParam * PatchParam *
PatchTablesFactory::computePatchParam( PatchTableFactory::computePatchParam(
TopologyRefiner const & refiner, PtexIndices const &ptexIndices, TopologyRefiner const & refiner, PtexIndices const &ptexIndices,
int depth, Vtr::Index faceIndex, int boundaryMask, int depth, Vtr::Index faceIndex, int boundaryMask,
int transitionMask, PatchParam *coord) { int transitionMask, PatchParam *coord) {
@ -665,7 +665,7 @@ PatchTablesFactory::computePatchParam(
v = 0, v = 0,
ofs = 1; 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) { for (int i = depth; i > 0; --i) {
Vtr::Refinement const& refinement = refiner.getRefinement(i-1); Vtr::Refinement const& refinement = refiner.getRefinement(i-1);
@ -733,8 +733,8 @@ assignSharpnessIndex(float sharpness, std::vector<float> & sharpnessValues) {
// cases. In the past, more additional arguments were passed to the uniform version, // 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)... // but that may no longer be necessary (see notes in the uniform version below)...
// //
PatchTables * PatchTable *
PatchTablesFactory::Create(TopologyRefiner const & refiner, Options options) { PatchTableFactory::Create(TopologyRefiner const & refiner, Options options) {
if (refiner.IsUniform()) { if (refiner.IsUniform()) {
return createUniform(refiner, options); return createUniform(refiner, options);
@ -743,8 +743,8 @@ PatchTablesFactory::Create(TopologyRefiner const & refiner, Options options) {
} }
} }
PatchTables * PatchTable *
PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options options) { PatchTableFactory::createUniform(TopologyRefiner const & refiner, Options options) {
assert(refiner.IsUniform()); assert(refiner.IsUniform());
@ -772,22 +772,26 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
assert(ptype!=PatchDescriptor::NON_PATCH); 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); PatchDescriptor desc(ptype);
// generate patch arrays // generate patch arrays
for (int level=firstlevel, poffset=0, voffset=0; level<=maxlevel; ++level) { 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()) { if (refiner.HasHoles()) {
npatches -= refiner.GetNumHoles(level); for (int i = npatches - 1; i >= 0; --i) {
npatches -= refLevel.IsFaceHole(i);
}
} }
assert(npatches>=0); assert(npatches>=0);
@ -795,31 +799,31 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
npatches *= 2; npatches *= 2;
if (level>=firstlevel) { if (level>=firstlevel) {
tables->pushPatchArray(desc, npatches, &voffset, &poffset, 0); table->pushPatchArray(desc, npatches, &voffset, &poffset, 0);
} }
} }
// Allocate various tables // Allocate various tables
allocateVertexTables( tables, 0, /*hasSharpness=*/false ); allocateVertexTables( table, 0, /*hasSharpness=*/false );
bool generateFVarPatches=false; bool generateFVarPatches=false;
FVarChannelCursor fvc(refiner, options); FVarChannelCursor fvc(refiner, options);
if (options.generateFVarTables and fvc.size()>0) { if (options.generateFVarTables and fvc.size()>0) {
int npatches = tables->GetNumPatchesTotal(); int npatches = table->GetNumPatchesTotal();
allocateFVarChannels(refiner, options, npatches, tables); allocateFVarChannels(refiner, options, npatches, table);
assert(fvc.size() == tables->GetNumFVarChannels()); assert(fvc.size() == table->GetNumFVarChannels());
} }
// //
// Now populate the patches: // Now populate the patches:
// //
Index * iptr = &tables->_patchVerts[0]; Index * iptr = &table->_patchVerts[0];
PatchParam * pptr = &tables->_paramTable[0]; PatchParam * pptr = &table->_paramTable[0];
Index ** fptr = 0; Index ** fptr = 0;
Index levelVertOffset = options.generateAllLevels ? Index levelVertOffset = options.generateAllLevels ?
0 : refiner.GetNumVertices(0); 0 : refiner.GetLevel(0).GetNumVertices();
Index * levelFVarVertOffsets = 0; Index * levelFVarVertOffsets = 0;
if (generateFVarPatches) { if (generateFVarPatches) {
@ -829,21 +833,23 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
fptr = (Index **)alloca(fvc.size()*sizeof(Index *)); fptr = (Index **)alloca(fvc.size()*sizeof(Index *));
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { 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) { 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) { if (level>=firstlevel) {
for (int face=0; face<nfaces; ++face) { for (int face=0; face<nfaces; ++face) {
if (refiner.HasHoles() and refiner.IsFaceHole(level, face)) { if (refiner.HasHoles() and refLevel.IsFaceHole(face)) {
continue; continue;
} }
ConstIndexArray fverts = refiner.GetFaceVertices(level, face); ConstIndexArray fverts = refLevel.GetFaceVertices(face);
for (int vert=0; vert<fverts.size(); ++vert) { for (int vert=0; vert<fverts.size(); ++vert) {
*iptr++ = levelVertOffset + fverts[vert]; *iptr++ = levelVertOffset + fverts[vert];
} }
@ -852,9 +858,9 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
if (generateFVarPatches) { if (generateFVarPatches) {
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
ConstIndexArray fvalues = refiner.GetFVarFaceValues(level, face, *fvc); ConstIndexArray fvalues = refLevel.GetFVarFaceValues(face, *fvc);
for (int vert=0; vert<fvalues.size(); ++vert) { for (int vert=0; vert<fvalues.size(); ++vert) {
assert((levelVertOffset + fvalues[vert]) < (int)tables->getFVarPatchesValues(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()][vert] = levelFVarVertOffsets[fvc.pos()] + fvalues[vert];
} }
fptr[fvc.pos()]+=fvalues.size(); fptr[fvc.pos()]+=fvalues.size();
@ -884,17 +890,17 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
} }
if (options.generateAllLevels) { if (options.generateAllLevels) {
levelVertOffset += refiner.GetNumVertices(level); levelVertOffset += refiner.GetLevel(level).GetNumVertices();
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { 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 * PatchTable *
PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options options) { PatchTableFactory::createAdaptive(TopologyRefiner const & refiner, Options options) {
assert(not refiner.IsUniform()); assert(not refiner.IsUniform());
@ -909,15 +915,15 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
identifyAdaptivePatches(context); 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: // the inventory of patches determined above:
// //
int maxValence = refiner.GetMaxValence(); int maxValence = refiner.GetMaxValence();
context.tables = new PatchTables(maxValence); context.table = new PatchTable(maxValence);
// Populate the patch array descriptors // 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 // Sort through the inventory and push back non-empty patch arrays
ConstPatchDescriptorArray const & descs = ConstPatchDescriptorArray const & descs =
@ -926,21 +932,21 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
int voffset=0, poffset=0, qoffset=0; int voffset=0, poffset=0, qoffset=0;
for (int i=0; i<descs.size(); ++i) { for (int i=0; i<descs.size(); ++i) {
PatchDescriptor desc = descs[i]; PatchDescriptor desc = descs[i];
context.tables->pushPatchArray(desc, context.table->pushPatchArray(desc,
context.patchInventory.getValue(desc), &voffset, &poffset, &qoffset ); context.patchInventory.getValue(desc), &voffset, &poffset, &qoffset );
} }
context.tables->_numPtexFaces = ptexIndices.GetNumFaces(); context.table->_numPtexFaces = ptexIndices.GetNumFaces();
// Allocate various tables // Allocate various tables
bool hasSharpness = context.options.useSingleCreasePatch; bool hasSharpness = context.options.useSingleCreasePatch;
allocateVertexTables(context.tables, 0, hasSharpness); allocateVertexTables(context.table, 0, hasSharpness);
if (context.RequiresFVarPatches()) { 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. // Reserve temporary non-sparse storage for non-linear fvar channels.
// FVar Values for these channels are copied into the final // FVar Values for these channels are copied into the final
@ -954,7 +960,7 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
// //
populateAdaptivePatches(context, ptexIndices); 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. // later with no additional analysis.
// //
void void
PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) { PatchTableFactory::identifyAdaptivePatches(AdaptiveContext & context) {
TopologyRefiner const & refiner = context.refiner; TopologyRefiner const & refiner = context.refiner;
@ -1225,12 +1231,12 @@ PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) {
// idenified. // idenified.
// //
void void
PatchTablesFactory::populateAdaptivePatches( PatchTableFactory::populateAdaptivePatches(
AdaptiveContext & context, PtexIndices const & ptexIndices) { AdaptiveContext & context, PtexIndices const & ptexIndices) {
TopologyRefiner const & refiner = context.refiner; 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 // Setup convenience pointers at the beginning of each patch array for each
@ -1249,33 +1255,33 @@ PatchTablesFactory::populateAdaptivePatches(
PatchDescriptor desc = descs[i]; PatchDescriptor desc = descs[i];
Index arrayIndex = tables->findPatchArray(desc); Index arrayIndex = table->findPatchArray(desc);
if (arrayIndex==Vtr::INDEX_INVALID) { if (arrayIndex==Vtr::INDEX_INVALID) {
continue; continue;
} }
iptrs.getValue(desc) = tables->getPatchArrayVertices(arrayIndex).begin(); iptrs.getValue(desc) = table->getPatchArrayVertices(arrayIndex).begin();
pptrs.getValue(desc) = tables->getPatchParams(arrayIndex).begin(); pptrs.getValue(desc) = table->getPatchParams(arrayIndex).begin();
if (context.options.useSingleCreasePatch) { if (context.options.useSingleCreasePatch) {
sptrs.getValue(desc) = tables->getSharpnessIndices(arrayIndex); sptrs.getValue(desc) = table->getSharpnessIndices(arrayIndex);
} }
if (context.RequiresFVarPatches()) { if (context.RequiresFVarPatches()) {
Index & offsets = fofss.getValue(desc); 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 // XXXX manuelk this stuff will go away as we use offsets from FVarPatchChannel
FVarChannelCursor & fvc = context.fvarChannelCursor; FVarChannelCursor & fvc = context.fvarChannelCursor;
assert(fvc.size() == tables->GetNumFVarChannels()); assert(fvc.size() == table->GetNumFVarChannels());
Index ** fptr = (Index **)alloca(fvc.size()*sizeof(Index *)); Index ** fptr = (Index **)alloca(fvc.size()*sizeof(Index *));
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
Index pidx = tables->getPatchIndex(arrayIndex, 0); Index pidx = table->getPatchIndex(arrayIndex, 0);
int ofs = pidx * 4; int ofs = pidx * 4;
fptr[fvc.pos()] = &tables->getFVarPatchesValues(fvc.pos())[ofs]; fptr[fvc.pos()] = &table->getFVarPatchesValues(fvc.pos())[ofs];
} }
fptrs.getValue(desc) = fptr; fptrs.getValue(desc) = fptr;
} }
@ -1371,7 +1377,7 @@ PatchTablesFactory::populateAdaptivePatches(
iptrs.R += 16; iptrs.R += 16;
pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, boundaryMask, transitionMask, pptrs.R); pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, boundaryMask, transitionMask, pptrs.R);
// XXX: sharpness will be integrated into patch param soon. // 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, fofss.R += gatherFVarData(context,
i, faceIndex, levelFaceOffset, /*rotation*/0, levelFVarVertOffsets, fofss.R, fptrs.R); i, faceIndex, levelFaceOffset, /*rotation*/0, levelFVarVertOffsets, fofss.R, fptrs.R);
@ -1389,7 +1395,7 @@ PatchTablesFactory::populateAdaptivePatches(
iptrs.R += 16; iptrs.R += 16;
pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, /*boundary*/0, transitionMask, pptrs.R); 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, fofss.R += gatherFVarData(context,
i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.R, fptrs.R); i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.R, fptrs.R);
@ -1410,7 +1416,7 @@ PatchTablesFactory::populateAdaptivePatches(
iptrs.GP += cvs.size(); iptrs.GP += cvs.size();
pptrs.GP = computePatchParam( pptrs.GP = computePatchParam(
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.GP); 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, fofss.GP += gatherFVarData(context,
i, faceIndex, levelFaceOffset, i, faceIndex, levelFaceOffset,
0, levelFVarVertOffsets, fofss.GP, fptrs.GP); 0, levelFVarVertOffsets, fofss.GP, fptrs.GP);
@ -1425,7 +1431,7 @@ PatchTablesFactory::populateAdaptivePatches(
iptrs.R += cvs.size(); iptrs.R += cvs.size();
pptrs.R = computePatchParam( pptrs.R = computePatchParam(
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.R); 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, fofss.R += gatherFVarData(context,
i, faceIndex, levelFaceOffset, i, faceIndex, levelFaceOffset,
0, levelFVarVertOffsets, fofss.R, fptrs.R); 0, levelFVarVertOffsets, fofss.R, fptrs.R);
@ -1441,7 +1447,7 @@ PatchTablesFactory::populateAdaptivePatches(
iptrs.G += cvs.size(); iptrs.G += cvs.size();
pptrs.G = computePatchParam( pptrs.G = computePatchParam(
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.G); 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, fofss.G += gatherFVarData(context,
i, faceIndex, levelFaceOffset, i, faceIndex, levelFaceOffset,
0, levelFVarVertOffsets, fofss.G, fptrs.G); 0, levelFVarVertOffsets, fofss.G, fptrs.G);
@ -1450,7 +1456,7 @@ PatchTablesFactory::populateAdaptivePatches(
iptrs.GB += cvs.size(); iptrs.GB += cvs.size();
pptrs.GB = computePatchParam( pptrs.GB = computePatchParam(
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.GB); 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, fofss.GB += gatherFVarData(context,
i, faceIndex, levelFaceOffset, i, faceIndex, levelFaceOffset,
0, levelFVarVertOffsets, fofss.GB, fptrs.GB); 0, levelFVarVertOffsets, fofss.GB, fptrs.GB);
@ -1480,24 +1486,24 @@ PatchTablesFactory::populateAdaptivePatches(
// finalize end patches // finalize end patches
switch(context.options.GetEndCapType()) { switch(context.options.GetEndCapType()) {
case Options::ENDCAP_GREGORY_BASIS: case Options::ENDCAP_GREGORY_BASIS:
tables->_vertexStencilTables = table->_vertexStencilTable =
endCapGregoryBasis->CreateVertexStencilTables(); endCapGregoryBasis->CreateVertexStencilTable();
tables->_varyingStencilTables = table->_varyingStencilTable =
endCapGregoryBasis->CreateVaryingStencilTables(); endCapGregoryBasis->CreateVaryingStencilTable();
delete endCapGregoryBasis; delete endCapGregoryBasis;
break; break;
case Options::ENDCAP_BSPLINE_BASIS: case Options::ENDCAP_BSPLINE_BASIS:
tables->_vertexStencilTables = table->_vertexStencilTable =
endCapBSpline->CreateVertexStencilTables(); endCapBSpline->CreateVertexStencilTable();
tables->_varyingStencilTables = table->_varyingStencilTable =
endCapBSpline->CreateVaryingStencilTables(); endCapBSpline->CreateVaryingStencilTable();
delete endCapBSpline; delete endCapBSpline;
break; break;
case Options::ENDCAP_LEGACY_GREGORY: case Options::ENDCAP_LEGACY_GREGORY:
endCapLegacyGregory->Finalize( endCapLegacyGregory->Finalize(
tables->GetMaxValence(), table->GetMaxValence(),
&tables->_quadOffsetsTable, &table->_quadOffsetsTable,
&tables->_vertexValenceTable); &table->_vertexValenceTable);
delete endCapLegacyGregory; delete endCapLegacyGregory;
break; break;
default: default:
@ -1511,8 +1517,8 @@ PatchTablesFactory::populateAdaptivePatches(
FVarChannelCursor & fvc = context.fvarChannelCursor; FVarChannelCursor & fvc = context.fvarChannelCursor;
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
if (tables->GetFVarChannelLinearInterpolation(fvc.pos())!=Sdc::Options::FVAR_LINEAR_ALL) { if (table->GetFVarChannelLinearInterpolation(fvc.pos())!=Sdc::Options::FVAR_LINEAR_ALL) {
tables->setBicubicFVarPatchChannelValues(fvc.pos(), table->setBicubicFVarPatchChannelValues(fvc.pos(),
context.fvarPatchSize, context.fvarPatchValues[fvc.pos()]); context.fvarPatchSize, context.fvarPatchValues[fvc.pos()]);
} }
} }

View File

@ -22,12 +22,12 @@
// language governing permissions and limitations under the Apache License. // language governing permissions and limitations under the Apache License.
// //
#ifndef OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H #ifndef OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H
#define OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H #define OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H
#include "../version.h" #include "../version.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
@ -40,12 +40,12 @@ namespace Far {
class PtexIndices; class PtexIndices;
class TopologyRefiner; class TopologyRefiner;
class PatchTablesFactory { class PatchTableFactory {
public: public:
// PatchFaceTag // PatchFaceTag
// A simple struct containing all information gathered about a face that is relevant // 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 // 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<T>::AdaptiveFlags, this struct aggregates all of the face tags // Like the HbrFace<T>::AdaptiveFlags, this struct aggregates all of the face tags
// supporting feature adaptive refinement. For now it is not used elsewhere and can // 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 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 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, static PatchTable * Create(TopologyRefiner const & refiner,
Options options=Options()); Options options=Options());
private: private:
// //
@ -145,11 +145,11 @@ private:
// //
// Methods for allocating and managing the patch table data arrays: // Methods for allocating and managing the patch table data arrays:
// //
static PatchTables * createUniform(TopologyRefiner const & refiner, static PatchTable * createUniform(TopologyRefiner const & refiner,
Options options); Options options);
static PatchTables * createAdaptive(TopologyRefiner const & refiner, static PatchTable * createAdaptive(TopologyRefiner const & refiner,
Options options); Options options);
// //
// High-level methods for identifying and populating patches associated with faces: // High-level methods for identifying and populating patches associated with faces:
@ -160,10 +160,10 @@ private:
static void populateAdaptivePatches(AdaptiveContext & state, static void populateAdaptivePatches(AdaptiveContext & state,
PtexIndices const &ptexIndices); 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, static void allocateFVarChannels(TopologyRefiner const & refiner,
Options options, int npatches, PatchTables * tables); Options options, int npatches, PatchTable * table);
static PatchParam * computePatchParam(TopologyRefiner const & refiner, static PatchParam * computePatchParam(TopologyRefiner const & refiner,
PtexIndices const & ptexIndices, PtexIndices const & ptexIndices,
@ -184,4 +184,4 @@ using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv } // end namespace OpenSubdiv
#endif /* OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H */ #endif /* OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H */

View File

@ -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 <cstring>
#include <map>
#include <vector>
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 <typename PROTOSTENCIL, class BIG_PROTOSTENCIL>
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<GetNumStencils(); ++i) {
nverts += _sizes[i];
}
return nverts;
}
// Returns true if the pool allocator executes AddVaryingWithWeight
// factorization
bool GetInterpolateVarying() const {
return _interpolateVarying;
}
// Allocates storage for 'size' stencils with a fixed '_maxsize' supporting
// basis of control-vertices
void Resize(int numStencils) {
clearBigStencils();
int nelems = numStencils * _maxsize;
_sizes.clear();
_sizes.resize(numStencils);
_indices.resize(nelems);
_weights.resize(nelems);
}
// Adds the contribution of a supporting vertex that was not yet
// in the stencil
void PushBackVertex(Index protoStencil, Index vert, float weight) {
assert(weight!=0.0f);
int & size = _sizes[protoStencil];
Index idx = protoStencil*_maxsize;
if (size < (_maxsize-1)) {
idx += size;
_indices[idx] = vert;
_weights[idx] = weight;
} else {
BIG_PROTOSTENCIL * dst = 0;
if (size==(_maxsize-1)) {
dst = new BIG_PROTOSTENCIL(size, &_indices[idx], &_weights[idx]);
assert(_bigStencils.find(protoStencil)==_bigStencils.end());
_bigStencils[protoStencil] = dst;
} else {
assert(_bigStencils.find(protoStencil)!=_bigStencils.end());
dst = _bigStencils[protoStencil];
}
dst->_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<size; ++i) {
if (indices[i]==vert) {
return i;
}
}
return Vtr::INDEX_INVALID;
}
// Returns true of the stencil does not fit in the pool allocator and
// has been moved to the 'big' (slow) allocation pool
bool IsBigStencil(Index protoStencil) const {
assert(protoStencil<(int)_sizes.size());
return _sizes[protoStencil]>=_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<Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL> *>(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<int> _sizes; // 'fast' memory pool
std::vector<int> _indices;
std::vector<float> _weights;
typedef std::map<int, BIG_PROTOSTENCIL *> BigStencilMap;
BigStencilMap _bigStencils; // 'slow' memory pool
};
//
// Specialization of the Allocator for stencils with tangents that require
// additional derivative weights.
//
template <typename PROTOSTENCIL, class BIG_PROTOSTENCIL>
class LimitAllocator : public Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL> {
public:
// Constructor
LimitAllocator(int maxSize) :
Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL>(maxSize) { }
void Resize(int size) {
Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL>::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<PROTOSTENCIL, BIG_PROTOSTENCIL>::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<PROTOSTENCIL, BIG_PROTOSTENCIL>::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<float> _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<Index> _indices;
std::vector<float> _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<float> _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<ProtoStencil, BigStencil> * 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(idx<table.GetNumStencils());
if(weight==0.0f) {
return;
}
int srcSize = table.GetSizes()[idx];
Index offset = table.GetOffsets()[idx];
Index const * srcIndices = &table.GetControlIndices()[offset];
float const * srcWeights = &table.GetWeights()[offset];
addWithWeight(weight, srcSize, srcIndices, srcWeights);
}
void AddVaryingWithWeight(ProtoStencil const & src, float weight) {
if (_alloc->GetInterpolateVarying()) {
AddWithWeight(src, weight);
}
}
protected:
void addWithWeight(float weight, int srcSize,
Index const * srcIndices, float const * srcWeights) {
for (int i=0; i<srcSize; ++i) {
assert(srcWeights[i]!=0.0f);
float w = weight * srcWeights[i];
if (w==0.0f) {
continue;
}
Index vertIndex = srcIndices[i],
n = _alloc->FindVertex(_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<ProtoStencil, BigStencil> * _alloc;
};
typedef Allocator<ProtoStencil, BigStencil> StencilAllocator;
//
// ProtoLimitStencil
//
class ProtoLimitStencil {
public:
ProtoLimitStencil(Index id,
LimitAllocator<ProtoLimitStencil, BigLimitStencil> * 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; i<srcSize; ++i) {
float w = srcWeights[i];
if (w==0.0f) {
continue;
}
Index vertIndex = srcIndices[i],
n = _alloc->FindVertex(_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<ProtoLimitStencil, BigLimitStencil> * _alloc;
};
typedef LimitAllocator<ProtoLimitStencil, BigLimitStencil> LimitStencilAllocator;
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv
#endif // OPENSUBDIV3_FAR_PROTOSTENCIL_H

View File

@ -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 <class W, class WACCUM>
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<int> const&
GetOffsets() const { return _indices; }
std::vector<int> const&
GetSizes() const { return _sizes; }
std::vector<int> const&
GetSources() const { return _sources; }
std::vector<float> const&
GetWeights() const { return _weights; }
std::vector<float> const&
GetDuWeights() const { return _duWeights; }
std::vector<float> 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 <class W, class WACCUM>
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 <class W, class WACCUM>
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<int> _dests;
// The actual stencil data.
std::vector<int> _sources;
std::vector<float> _weights;
std::vector<float> _duWeights;
std::vector<float> _dvWeights;
// Index data used to recover stencil-to-vertex mapping.
std::vector<int> _indices;
std::vector<int> _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<int> const&
StencilBuilder::GetStencilOffsets() const {
return _weightTable->GetOffsets();
}
std::vector<int> const&
StencilBuilder::GetStencilSizes() const {
return _weightTable->GetSizes();
}
std::vector<int> const&
StencilBuilder::GetStencilSources() const {
return _weightTable->GetSources();
}
std::vector<float> const&
StencilBuilder::GetStencilWeights() const {
return _weightTable->GetWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDuWeights() const {
return _weightTable->GetDuWeights();
}
std::vector<float> 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

View File

@ -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 <vector>
#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<int> const& GetStencilOffsets() const;
// The number of contributing sources and weights in stencil[i]
std::vector<int> const& GetStencilSizes() const;
// The absolute source vertex offsets.
std::vector<int> const& GetStencilSources() const;
// The individual vertex weights, each weight is paired with one source.
std::vector<float> const& GetStencilWeights() const;
std::vector<float> const& GetStencilDuWeights() const;
std::vector<float> 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

View File

@ -22,24 +22,102 @@
// language governing permissions and limitations under the Apache License. // language governing permissions and limitations under the Apache License.
// //
#ifndef OPENSUBDIV3_FAR_STENCILTABLES_H #ifndef OPENSUBDIV3_FAR_STENCILTABLE_H
#define OPENSUBDIV3_FAR_STENCILTABLES_H #define OPENSUBDIV3_FAR_STENCILTABLE_H
#include "../version.h" #include "../version.h"
#include "../far/types.h" #include "../far/types.h"
#include <cassert> #include <cassert>
#include <cstring>
#include <vector> #include <vector>
#include <iostream>
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
namespace {
void
copyStencilData(int numControlVerts,
bool includeCoarseVerts,
size_t firstOffset,
std::vector<int> const* offsets,
std::vector<int> * _offsets,
std::vector<int> const* sizes,
std::vector<int> * _sizes,
std::vector<int> const* sources,
std::vector<int> * _sources,
std::vector<float> const* weights,
std::vector<float> * _weights,
std::vector<float> const* duWeights=NULL,
std::vector<float> * _duWeights=NULL,
std::vector<float> const* dvWeights=NULL,
std::vector<float> * _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 /// \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 { class Stencil {
@ -100,8 +178,8 @@ public:
} }
protected: protected:
friend class StencilTablesFactory; friend class StencilTableFactory;
friend class LimitStencilTablesFactory; friend class LimitStencilTableFactory;
int * _size; int * _size;
Index * _indices; Index * _indices;
@ -120,7 +198,24 @@ protected:
/// recomputed simply by applying the blending weights to the series of coarse /// recomputed simply by applying the blending weights to the series of coarse
/// control vertices. /// control vertices.
/// ///
class StencilTables { class StencilTable {
StencilTable(int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
bool includeCoarseVerts,
size_t firstOffset)
: _numControlVertices(numControlVerts)
{
copyStencilData(numControlVerts,
includeCoarseVerts,
firstOffset,
&offsets, &_offsets,
&sizes, &_sizes,
&sources, &_indices,
&weights, &_weights);
}
public: public:
@ -134,7 +229,7 @@ public:
return _numControlVertices; 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; Stencil GetStencil(Index i) const;
/// \brief Returns the number of control vertices of each stencil in the table /// \brief Returns the number of control vertices of each stencil in the table
@ -157,7 +252,7 @@ public:
return _weights; 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; Stencil operator[] (Index index) const;
/// \brief Updates point values based on the control values /// \brief Updates point values based on the control values
@ -202,9 +297,12 @@ protected:
void resize(int nstencils, int nelems); void resize(int nstencils, int nelems);
protected: 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. // XXX: temporarily, GregoryBasis class will go away.
friend class GregoryBasis; friend class GregoryBasis;
@ -267,8 +365,8 @@ public:
private: private:
friend class StencilTablesFactory; friend class StencilTableFactory;
friend class LimitStencilTablesFactory; friend class LimitStencilTableFactory;
float * _duWeights, // pointer to stencil u derivative limit weights float * _duWeights, // pointer to stencil u derivative limit weights
* _dvWeights; // pointer to stencil v derivative limit weights * _dvWeights; // pointer to stencil v derivative limit weights
@ -277,10 +375,33 @@ private:
/// \brief Table of limit subdivision stencils. /// \brief Table of limit subdivision stencils.
/// ///
/// ///
class LimitStencilTables : public StencilTables { class LimitStencilTable : public StencilTable {
public: public:
// TODO: share construction logic
LimitStencilTable(int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
std::vector<float> const& duWeights,
std::vector<float> 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 /// \brief Returns the 'u' derivative stencil interpolation weights
std::vector<float> const & GetDuWeights() const { std::vector<float> const & GetDuWeights() const {
return _duWeights; return _duWeights;
@ -318,13 +439,13 @@ public:
/// \brief Clears the stencils from the table /// \brief Clears the stencils from the table
void Clear() { void Clear() {
StencilTables::Clear(); StencilTable::Clear();
_duWeights.clear(); _duWeights.clear();
_dvWeights.clear(); _dvWeights.clear();
} }
private: private:
friend class LimitStencilTablesFactory; friend class LimitStencilTableFactory;
// Resize the table arrays (factory helper) // Resize the table arrays (factory helper)
void resize(int nstencils, int nelems); void resize(int nstencils, int nelems);
@ -337,7 +458,7 @@ private:
// Update values by appling cached stencil weights to new control values // Update values by appling cached stencil weights to new control values
template <class T> void template <class T> void
StencilTables::update(T const *controlValues, T *values, StencilTable::update(T const *controlValues, T *values,
std::vector<float> const &valueWeights, Index start, Index end) const { std::vector<float> const &valueWeights, Index start, Index end) const {
int const * sizes = &_sizes.at(0); int const * sizes = &_sizes.at(0);
@ -370,7 +491,7 @@ StencilTables::update(T const *controlValues, T *values,
} }
inline void inline void
StencilTables::generateOffsets() { StencilTable::generateOffsets() {
Index offset=0; Index offset=0;
int noffsets = (int)_sizes.size(); int noffsets = (int)_sizes.size();
_offsets.resize(noffsets); _offsets.resize(noffsets);
@ -381,7 +502,7 @@ StencilTables::generateOffsets() {
} }
inline void inline void
StencilTables::resize(int nstencils, int nelems) { StencilTable::resize(int nstencils, int nelems) {
_sizes.resize(nstencils); _sizes.resize(nstencils);
_indices.resize(nelems); _indices.resize(nelems);
@ -390,7 +511,7 @@ StencilTables::resize(int nstencils, int nelems) {
// Returns a Stencil at index i in the table // Returns a Stencil at index i in the table
inline Stencil inline Stencil
StencilTables::GetStencil(Index i) const { StencilTable::GetStencil(Index i) const {
assert((not _offsets.empty()) and i<(int)_offsets.size()); assert((not _offsets.empty()) and i<(int)_offsets.size());
@ -402,14 +523,14 @@ StencilTables::GetStencil(Index i) const {
} }
inline Stencil inline Stencil
StencilTables::operator[] (Index index) const { StencilTable::operator[] (Index index) const {
return GetStencil(index); return GetStencil(index);
} }
inline void 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); _duWeights.resize(nelems);
_dvWeights.resize(nelems); _dvWeights.resize(nelems);
} }
@ -422,4 +543,4 @@ using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv } // end namespace OpenSubdiv
#endif // OPENSUBDIV3_FAR_STENCILTABLES_H #endif // OPENSUBDIV3_FAR_STENCILTABLE_H

View File

@ -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 <cassert>
#include <algorithm>
#include <iostream>
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<numControlVerts; ++i) {
*dst._size = 1;
*dst._indices = i;
*dst._weights = 1.0f;
dst.Next();
}
}
//
// StencilTable factory
//
StencilTable const *
StencilTableFactory::Create(TopologyRefiner const & refiner,
Options options) {
int maxlevel = std::min(int(options.maxLevel), refiner.GetMaxLevel());
if (maxlevel==0 and (not options.generateControlVerts)) {
StencilTable * result = new StencilTable;
result->_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<numTables; ++i) {
StencilTable const * st = tables[i];
// allow the tables could have a null entry.
if (!st) continue;
if (ncvs >= 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; i<numTables; ++i) {
StencilTable const * st = tables[i];
if (!st) continue;
int st_nstencils = st->GetNumStencils(),
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<locationArrays.size(); ++i) {
LocationArray const & array = locationArrays[i];
assert(array.ptexIdx>=0);
for (int j=0; j<array.numLocations; ++j) {
float s = array.s[j],
t = array.t[j];
PatchMap::Handle const * handle =
patchmap.FindPatch(array.ptexIdx, s, t);
if (handle) {
ConstIndexArray cvs = patchtable->GetPatchVertices(*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

View File

@ -27,7 +27,7 @@
#include "../version.h" #include "../version.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
#include <vector> #include <vector>
@ -39,13 +39,13 @@ namespace Far {
class TopologyRefiner; class TopologyRefiner;
class Stencil; class Stencil;
class StencilTables; class StencilTable;
class LimitStencil; class LimitStencil;
class LimitStencilTables; class LimitStencilTable;
/// \brief A specialized factory for StencilTables /// \brief A specialized factory for StencilTable
/// ///
class StencilTablesFactory { class StencilTableFactory {
public: public:
@ -73,7 +73,7 @@ public:
maxLevel : 4; ///< generate stencils up to 'maxLevel' 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. /// refined uniformly or adaptively.
/// ///
/// \note The factory only creates stencils for vertices that have already /// \note The factory only creates stencils for vertices that have already
@ -82,45 +82,45 @@ public:
/// ///
/// @param refiner The TopologyRefiner containing the topology /// @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()); Options options = Options());
/// \brief Instantiates StencilTables by concatenating an array of existing /// \brief Instantiates StencilTable by concatenating an array of existing
/// stencil tables. /// 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. /// of supporting control vertices - no re-indexing is done.
/// GetNumControlVertices() *must* return the same value for all input /// GetNumControlVertices() *must* return the same value for all input
/// tables. /// tables.
/// ///
/// @param numTables Number of input StencilTables /// @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. /// \brief Utility function for stencil splicing for endcap stencils.
/// ///
/// @param refiner The TopologyRefiner containing the topology /// @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. /// has to be relative to the max level of subdivision.
/// ///
/// @param factorize If factorize sets to true, endcap stencils will be /// @param factorize If factorize sets to true, endcap stencils will be
/// factorized with supporting vertices from baseStencil /// 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. /// directly from control vertices.
/// ///
static StencilTables const * AppendEndCapStencilTables( static StencilTable const * AppendEndCapStencilTable(
TopologyRefiner const &refiner, TopologyRefiner const &refiner,
StencilTables const *baseStencilTables, StencilTable const *baseStencilTable,
StencilTables const *endCapStencilTables, StencilTable const *endCapStencilTable,
bool factorize = true); bool factorize = true);
private: private:
@ -129,9 +129,9 @@ private:
static void generateControlVertStencils(int numControlVerts, Stencil & dst); 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. /// stencils can interpolate any arbitrary location on the limit surface.
/// The stencils will be bilinear if the surface is refined uniformly, and /// The stencils will be bilinear if the surface is refined uniformly, and
/// bicubic if feature adaptive isolation is used instead. /// bicubic if feature adaptive isolation is used instead.
@ -140,7 +140,7 @@ private:
/// normalized (s,t) patch coordinates. The factory exposes the LocationArray /// normalized (s,t) patch coordinates. The factory exposes the LocationArray
/// struct as a container for these location descriptors. /// struct as a container for these location descriptors.
/// ///
class LimitStencilTablesFactory { class LimitStencilTableFactory {
public: public:
@ -158,7 +158,7 @@ public:
typedef std::vector<LocationArray> LocationArrayVec; typedef std::vector<LocationArray> LocationArrayVec;
/// \brief Instantiates LimitStencilTables from a TopologyRefiner that has /// \brief Instantiates LimitStencilTable from a TopologyRefiner that has
/// been refined either uniformly or adaptively. /// been refined either uniformly or adaptively.
/// ///
/// @param refiner The TopologyRefiner containing the topology /// @param refiner The TopologyRefiner containing the topology
@ -166,18 +166,18 @@ public:
/// @param locationArrays An array of surface location descriptors /// @param locationArrays An array of surface location descriptors
/// (see LocationArray) /// (see LocationArray)
/// ///
/// @param cvStencils A set of StencilTables generated from the /// @param cvStencils A set of StencilTable generated from the
/// TopologyRefiner (optional: prevents redundant /// 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 /// 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, LocationArrayVec const & locationArrays,
StencilTables const * cvStencils=0, StencilTable const * cvStencils=0,
PatchTables const * patchTables=0); PatchTable const * patchTable=0);
}; };

View File

@ -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 <cassert>
#include <algorithm>
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<numControlVerts; ++i) {
*dst._size = 1;
*dst._indices = i;
*dst._weights = 1.0f;
dst.Next();
}
}
//
// StencilTables factory
//
StencilTables const *
StencilTablesFactory::Create(TopologyRefiner const & refiner,
Options options) {
StencilTables * result = new StencilTables;
// always initialize numControlVertices (useful for torus case)
result->_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<StencilAllocator> 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 (level<maxlevel) {
if (options.factorizeIntermediateLevels) {
srcAlloc = &allocators[level];
} else {
// if the stencils are dependent on the previous level of
// subdivision, pass an empty allocator to treat all parent
// vertices as control vertices
assert(allocators[0].GetNumStencils()==0);
}
dstAlloc = &allocators[level+1];
}
} else {
std::swap(srcAlloc, dstAlloc);
}
}
// Copy stencils from the pool allocator into the tables
{
// Add total number of stencils, weights & indices
int nelems = 0, nstencils=0;
if (options.generateIntermediateLevels) {
for (int level=0; level<=maxlevel; ++level) {
nstencils += allocators[level].GetNumStencils();
nelems += allocators[level].GetNumVerticesTotal();
}
} else {
nstencils = (int)srcAlloc->GetNumStencils();
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; i<allocators[level].GetNumStencils(); ++i) {
*dst._size = allocators[level].CopyStencil(i, dst._indices, dst._weights);
dst.Next();
}
}
} else {
for (int i=0; i<srcAlloc->GetNumStencils(); ++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<numTables; ++i) {
StencilTables const * st = tables[i];
// allow the tables could have a null entry.
if (!st) continue;
if (ncvs >= 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; i<numTables; ++i) {
StencilTables const * st = tables[i];
if (!st) continue;
int st_nstencils = st->GetNumStencils(),
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; j<array.numLocations; ++j, ++currentStencil) {
float s = array.s[j],
t = array.t[j];
PatchMap::Handle const * handle = patchmap.FindPatch(array.ptexIdx, s, t);
if (handle) {
ConstIndexArray cvs = patchTables->GetPatchVertices(*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; i<alloc.GetNumStencils(); ++i) {
*dst._size = alloc.CopyLimitStencil(i, dst._indices, dst._weights,
dst._duWeights, dst._dvWeights);
dst.Next();
}
// XXXX manuelk should offset creation be optional ?
result->generateOffsets();
}
result->_numControlVertices = refiner.GetNumVertices(0);
return result;
}
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -192,18 +192,6 @@ TopologyRefiner::GetNumFVarValuesTotal(int channel) const {
return sum; 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: // Main refinement method -- allocating and initializing levels and refinements:

View File

@ -217,8 +217,8 @@ public:
/// \brief Apply vertex and varying interpolation weights to a primvar /// \brief Apply vertex and varying interpolation weights to a primvar
/// buffer /// buffer
/// ///
/// The destination buffer must allocate an array of data for all the /// The destination buffer must allocate an array of data for all the refined
/// refined vertices (at least GetNumVerticesTotal()-GetNumVertices(0)) /// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices())
/// ///
/// @param src Source primvar buffer (\ref templating control vertex data) /// @param src Source primvar buffer (\ref templating control vertex data)
/// ///
@ -231,7 +231,7 @@ public:
/// level of refinement. /// level of refinement.
/// ///
/// The destination buffer must allocate an array of data for all the /// 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 /// @param level The refinement level
/// ///
@ -247,8 +247,8 @@ public:
/// This method can be a useful alternative if the varying primvar data /// This method can be a useful alternative if the varying primvar data
/// does not need to be re-computed over time. /// does not need to be re-computed over time.
/// ///
/// The destination buffer must allocate an array of data for all the /// The destination buffer must allocate an array of data for all the refined
/// refined vertices (at least GetNumVerticesTotal()-GetNumVertices(0)) /// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices())
/// ///
/// @param src Source primvar buffer (\ref templating control vertex data) /// @param src Source primvar buffer (\ref templating control vertex data)
/// ///
@ -263,7 +263,7 @@ public:
/// does not need to be re-computed over time. /// does not need to be re-computed over time.
/// ///
/// The destination buffer must allocate an array of data for all the /// 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 /// @param level The refinement level
/// ///
@ -288,7 +288,7 @@ public:
/// The source buffer must refer to an array of previously interpolated /// The source buffer must refer to an array of previously interpolated
/// vertex data for the last refinement level. The destination buffer /// vertex data for the last refinement level. The destination buffer
/// must allocate an array for all vertices at the last refinement level /// 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 /// @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: protected:
// //
@ -440,7 +373,7 @@ protected:
// Lower level protected methods intended strictly for internal use: // Lower level protected methods intended strictly for internal use:
// //
friend class TopologyRefinerFactoryBase; friend class TopologyRefinerFactoryBase;
friend class PatchTablesFactory; friend class PatchTableFactory;
friend class EndCapGregoryBasisPatchFactory; friend class EndCapGregoryBasisPatchFactory;
friend class EndCapLegacyGregoryPatchFactory; friend class EndCapLegacyGregoryPatchFactory;
friend class PtexIndices; friend class PtexIndices;
@ -549,7 +482,7 @@ TopologyRefiner::Interpolate(T const * src, U * dst) const {
Interpolate(level, src, dst); Interpolate(level, src, dst);
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); InterpolateVarying(level, src, dst);
src = dst; src = dst;
dst += GetNumVertices(level); dst += GetLevel(level).GetNumVertices();
} }
} }

View File

@ -317,13 +317,14 @@ bool
TopologyRefinerFactory<TopologyRefinerFactoryBase::TopologyDescriptor>::assignComponentTags( TopologyRefinerFactory<TopologyRefinerFactoryBase::TopologyDescriptor>::assignComponentTags(
TopologyRefiner & refiner, TopologyDescriptor const & desc) { TopologyRefiner & refiner, TopologyDescriptor const & desc) {
TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
if ((desc.numCreases>0) and desc.creaseVertexIndexPairs and desc.creaseWeights) { if ((desc.numCreases>0) and desc.creaseVertexIndexPairs and desc.creaseWeights) {
int const * vertIndexPairs = desc.creaseVertexIndexPairs; int const * vertIndexPairs = desc.creaseVertexIndexPairs;
for (int edge=0; edge<desc.numCreases; ++edge, vertIndexPairs+=2) { for (int edge=0; edge<desc.numCreases; ++edge, vertIndexPairs+=2) {
Index idx = refiner.FindEdge(0, vertIndexPairs[0], vertIndexPairs[1]); Index idx = refBaseLevel.FindEdge(vertIndexPairs[0], vertIndexPairs[1]);
if (idx!=Vtr::INDEX_INVALID) { if (idx!=Vtr::INDEX_INVALID) {
refiner.setBaseEdgeSharpness(idx, desc.creaseWeights[edge]); refiner.setBaseEdgeSharpness(idx, desc.creaseWeights[edge]);
@ -342,7 +343,7 @@ TopologyRefinerFactory<TopologyRefinerFactoryBase::TopologyDescriptor>::assignCo
int idx = desc.cornerVertexIndices[vert]; 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]); refiner.setBaseVertexSharpness(idx, desc.cornerWeights[vert]);
} else { } else {
char msg[1024]; char msg[1024];

View File

@ -343,7 +343,7 @@ TopologyRefinerFactory<MESH>::assignComponentTopology(TopologyRefiner& /* refine
// //
// void TopologyRefiner::setBaseVertexNonManifold(Index vertex, bool b); // 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. // that topolology has been completely and correctly specified.
// //
return false; return false;

View File

@ -30,7 +30,7 @@
#include "../osd/opencl.h" #include "../osd/opencl.h"
#include "../far/error.h" #include "../far/error.h"
#include "../far/stencilTables.h" #include "../far/stencilTable.h"
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
@ -61,22 +61,22 @@ createCLBuffer(std::vector<T> const & src, cl_context clContext) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
CLStencilTables::CLStencilTables(Far::StencilTables const *stencilTables, CLStencilTable::CLStencilTable(Far::StencilTable const *stencilTable,
cl_context clContext) { cl_context clContext) {
_numStencils = stencilTables->GetNumStencils(); _numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0) { if (_numStencils > 0) {
_sizes = createCLBuffer(stencilTables->GetSizes(), clContext); _sizes = createCLBuffer(stencilTable->GetSizes(), clContext);
_offsets = createCLBuffer(stencilTables->GetOffsets(), clContext); _offsets = createCLBuffer(stencilTable->GetOffsets(), clContext);
_indices = createCLBuffer(stencilTables->GetControlIndices(), _indices = createCLBuffer(stencilTable->GetControlIndices(),
clContext); clContext);
_weights = createCLBuffer(stencilTables->GetWeights(), clContext); _weights = createCLBuffer(stencilTable->GetWeights(), clContext);
} else { } else {
_sizes = _offsets = _indices = _weights = NULL; _sizes = _offsets = _indices = _weights = NULL;
} }
} }
CLStencilTables::~CLStencilTables() { CLStencilTable::~CLStencilTable() {
if (_sizes) clReleaseMemObject(_sizes); if (_sizes) clReleaseMemObject(_sizes);
if (_offsets) clReleaseMemObject(_offsets); if (_offsets) clReleaseMemObject(_offsets);
if (_indices) clReleaseMemObject(_indices); if (_indices) clReleaseMemObject(_indices);

View File

@ -34,29 +34,29 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
class StencilTables; class StencilTable;
} }
namespace Osd { 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 /// CLCompute consumes this table to apply stencils
/// ///
/// ///
class CLStencilTables { class CLStencilTable {
public: public:
template <typename DEVICE_CONTEXT> template <typename DEVICE_CONTEXT>
static CLStencilTables *Create(Far::StencilTables const *stencilTables, static CLStencilTable *Create(Far::StencilTable const *stencilTable,
DEVICE_CONTEXT context) { DEVICE_CONTEXT context) {
return new CLStencilTables(stencilTables, context->GetContext()); return new CLStencilTable(stencilTable, context->GetContext());
} }
CLStencilTables(Far::StencilTables const *stencilTables, CLStencilTable(Far::StencilTable const *stencilTable,
cl_context clContext); cl_context clContext);
~CLStencilTables(); ~CLStencilTable();
// interfaces needed for CLComputeKernel // interfaces needed for CLComputeKernel
cl_mem GetSizesBuffer() const { return _sizes; } cl_mem GetSizesBuffer() const { return _sizes; }
@ -123,7 +123,7 @@ public:
/// ///
/// @param dstDesc vertex buffer descriptor for the output buffer /// @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. /// OpenCL memory interfaces.
/// ///
/// @param instance cached compiled instance. Clients are supposed to /// @param instance cached compiled instance. Clients are supposed to

View File

@ -59,10 +59,10 @@ CpuEvaluator::EvalStencils(const float *src,
VertexBufferDescriptor const &srcDesc, VertexBufferDescriptor const &srcDesc,
float *dst, float *dst,
VertexBufferDescriptor const &dstDesc, VertexBufferDescriptor const &dstDesc,
float *dstDu, float *dstDs,
VertexBufferDescriptor const &dstDuDesc, VertexBufferDescriptor const &dstDsDesc,
float *dstDv, float *dstDt,
VertexBufferDescriptor const &dstDvDesc, VertexBufferDescriptor const &dstDtDesc,
const int * sizes, const int * sizes,
const int * offsets, const int * offsets,
const int * indices, const int * indices,
@ -72,13 +72,13 @@ CpuEvaluator::EvalStencils(const float *src,
int start, int end) { int start, int end) {
if (end <= start) return true; if (end <= start) return true;
if (srcDesc.length != dstDesc.length) return false; if (srcDesc.length != dstDesc.length) return false;
if (srcDesc.length != dstDuDesc.length) return false; if (srcDesc.length != dstDsDesc.length) return false;
if (srcDesc.length != dstDvDesc.length) return false; if (srcDesc.length != dstDtDesc.length) return false;
CpuEvalStencils(src, srcDesc, CpuEvalStencils(src, srcDesc,
dst, dstDesc, dst, dstDesc,
dstDu, dstDuDesc, dstDs, dstDsDesc,
dstDv, dstDvDesc, dstDt, dstDtDesc,
sizes, offsets, indices, sizes, offsets, indices,
weights, duWeights, dvWeights, weights, duWeights, dvWeights,
start, end); start, end);
@ -93,19 +93,21 @@ struct BufferAdapter {
void Clear() { void Clear() {
for (int i = 0; i < _length; ++i) _p[i] = 0; for (int i = 0; i < _length; ++i) _p[i] = 0;
} }
void AddWithWeight(T const *src, float w, float wu, float wv) { void AddWithWeight(T const *src, float w) {
(void)wu; if (_p) {
(void)wv; // TODO: derivatives.
// TODO: derivatives. for (int i = 0; i < _length; ++i) {
for (int i = 0; i < _length; ++i) { _p[i] += src[i] * w;
_p[i] += src[i] * w; }
} }
} }
const T *operator[] (int index) const { const T *operator[] (int index) const {
return _p + _stride * index; return _p + _stride * index;
} }
BufferAdapter<T> & operator ++() { BufferAdapter<T> & operator ++() {
_p += _stride; if (_p) {
_p += _stride;
}
return *this; return *this;
} }
@ -115,24 +117,23 @@ struct BufferAdapter {
}; };
/* static */ /* static */
int bool
CpuEvaluator::EvalPatches(const float *src, CpuEvaluator::EvalPatches(const float *src,
VertexBufferDescriptor const &srcDesc, VertexBufferDescriptor const &srcDesc,
float *dst, float *dst,
VertexBufferDescriptor const &dstDesc, VertexBufferDescriptor const &dstDesc,
PatchCoordArray const &patchCoords, int numPatchCoords,
Far::PatchTables const *patchTable) { PatchCoord const *patchCoords,
Far::PatchTable const *patchTable) {
src += srcDesc.offset; src += srcDesc.offset;
dst += dstDesc.offset; if (dst) dst += dstDesc.offset;
int count = 0;
// XXX: this implementaion is temporary.
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride); BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride); BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
float wP[20], wDs[20], wDt[20]; 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]; PatchCoord const &coords = patchCoords[i];
patchTable->EvaluateBasis(coords.handle, coords.s, coords.t, wP, wDs, wDt); patchTable->EvaluateBasis(coords.handle, coords.s, coords.t, wP, wDs, wDt);
@ -141,13 +142,58 @@ CpuEvaluator::EvalPatches(const float *src,
dstT.Clear(); dstT.Clear();
for (int j = 0; j < cvs.size(); ++j) { 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; ++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<const float> srcT(src, srcDesc.length, srcDesc.stride);
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
BufferAdapter<float> dstDsT(dstDs, dstDsDesc.length, dstDsDesc.stride);
BufferAdapter<float> 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;
} }

View File

@ -30,7 +30,7 @@
#include <cstddef> #include <cstddef>
#include <vector> #include <vector>
#include "../osd/vertexDescriptor.h" #include "../osd/vertexDescriptor.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
@ -49,21 +49,24 @@ struct PatchCoord {
/// ///
/// @param t parametric location on the patch /// @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) { } 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 float s, t; ///< parametric location on patch
}; };
typedef std::vector<PatchCoord> PatchCoordArray;
class CpuEvaluator { class CpuEvaluator {
public: public:
/// ----------------------------------------------------------------------
///
/// Stencil evaluations with StencilTable
///
/// ----------------------------------------------------------------------
/// \brief Generic static eval stencils function. This function has a same /// \brief Generic static eval stencils function. This function has a same
/// signature as other device kernels have so that it can be called /// 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. /// @param srcBuffer Input primvar buffer.
/// must have BindCpuBuffer() method returning a /// must have BindCpuBuffer() method returning a
@ -108,7 +111,28 @@ public:
/*end = */ stencilTable->GetNumStencils()); /*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, static bool EvalStencils(const float *src,
VertexBufferDescriptor const &srcDesc, VertexBufferDescriptor const &srcDesc,
float *dst, float *dst,
@ -120,15 +144,52 @@ public:
int start, int start,
int end); 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 <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE> template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
static bool EvalStencils(SRC_BUFFER *srcBuffer, static bool EvalStencils(SRC_BUFFER *srcBuffer,
VertexBufferDescriptor const &srcDesc, VertexBufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, DST_BUFFER *dstBuffer,
VertexBufferDescriptor const &dstDesc, VertexBufferDescriptor const &dstDesc,
DST_BUFFER *dstDuBuffer, DST_BUFFER *dstDsBuffer,
VertexBufferDescriptor const &dstDuDesc, VertexBufferDescriptor const &dstDsDesc,
DST_BUFFER *dstDvBuffer, DST_BUFFER *dstDtBuffer,
VertexBufferDescriptor const &dstDvDesc, VertexBufferDescriptor const &dstDtDesc,
STENCIL_TABLE const *stencilTable, STENCIL_TABLE const *stencilTable,
const CpuEvaluator *evaluator = NULL, const CpuEvaluator *evaluator = NULL,
void * deviceContext = NULL) { void * deviceContext = NULL) {
@ -139,10 +200,10 @@ public:
srcDesc, srcDesc,
dstBuffer->BindCpuBuffer(), dstBuffer->BindCpuBuffer(),
dstDesc, dstDesc,
dstDuBuffer->BindCpuBuffer(), dstDsBuffer->BindCpuBuffer(),
dstDuDesc, dstDsDesc,
dstDvBuffer->BindCpuBuffer(), dstDtBuffer->BindCpuBuffer(),
dstDvDesc, dstDtDesc,
&stencilTable->GetSizes()[0], &stencilTable->GetSizes()[0],
&stencilTable->GetOffsets()[0], &stencilTable->GetOffsets()[0],
&stencilTable->GetControlIndices()[0], &stencilTable->GetControlIndices()[0],
@ -153,14 +214,46 @@ public:
/*end = */ stencilTable->GetNumStencils()); /*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, static bool EvalStencils(const float *src,
VertexBufferDescriptor const &srcDesc, VertexBufferDescriptor const &srcDesc,
float *dst, float *dst,
VertexBufferDescriptor const &dstDesc, VertexBufferDescriptor const &dstDesc,
float *dstDu, float *dstDs,
VertexBufferDescriptor const &dstDuDesc, VertexBufferDescriptor const &dstDsDesc,
float *dstDv, float *dstDt,
VertexBufferDescriptor const &dstDvDesc, VertexBufferDescriptor const &dstDtDesc,
const int * sizes, const int * sizes,
const int * offsets, const int * offsets,
const int * indices, const int * indices,
@ -170,11 +263,15 @@ public:
int start, int start,
int end); int end);
/// ----------------------------------------------------------------------
///
/// Limit evaluations with PatchTable
///
/// ----------------------------------------------------------------------
/// \brief Generic limit eval function. This function has a same /// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called /// signature as other device kernels have so that it can be called
/// transparently. /// in the same way.
///
/// XXX: This interface is still work in progress. XXX
/// ///
/// @param srcBuffer Input primvar buffer. /// @param srcBuffer Input primvar buffer.
/// must have BindCpuBuffer() method returning a /// must have BindCpuBuffer() method returning a
@ -188,23 +285,26 @@ public:
/// ///
/// @param dstDesc vertex buffer descriptor for the output buffer /// @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 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 /// @param deviceContext not used in the cpu evaluator
/// ///
template <typename SRC_BUFFER, typename DST_BUFFER> template <typename SRC_BUFFER, typename DST_BUFFER>
static int EvalPatches(SRC_BUFFER *srcBuffer, static bool EvalPatches(SRC_BUFFER *srcBuffer,
VertexBufferDescriptor const &srcDesc, VertexBufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer, DST_BUFFER *dstBuffer,
VertexBufferDescriptor const &dstDesc, VertexBufferDescriptor const &dstDesc,
PatchCoordArray const &patchCoords, int numPatchCoords,
Far::PatchTables const *patchTable, PatchCoord const *patchCoords,
CpuEvaluator const *instance, Far::PatchTable const *patchTable,
void * deviceContext = NULL) { CpuEvaluator const *instance,
void * deviceContext = NULL) {
(void)instance; // unused (void)instance; // unused
(void)deviceContext; // unused (void)deviceContext; // unused
@ -212,17 +312,158 @@ public:
srcDesc, srcDesc,
dstBuffer->BindCpuBuffer(), dstBuffer->BindCpuBuffer(),
dstDesc, dstDesc,
numPatchCoords,
patchCoords, patchCoords,
patchTable); patchTable);
} }
/// \brief limit eval function. /// \brief Generic limit eval function with derivatives. This function has
static int EvalPatches(const float *src, /// a same signature as other device kernels have so that it can be
VertexBufferDescriptor const &srcDesc, /// called in the same way.
float *dst, ///
VertexBufferDescriptor const &dstDesc, /// @param srcBuffer Input primvar buffer.
PatchCoordArray const &patchCoords, /// must have BindCpuBuffer() method returning a
Far::PatchTables const *patchTable); /// 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 <typename SRC_BUFFER, typename DST_BUFFER>
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. /// \brief synchronize all asynchronous computation invoked on this device.
static void Synchronize(void * /*deviceContext = NULL*/) { static void Synchronize(void * /*deviceContext = NULL*/) {

View File

@ -36,14 +36,14 @@ CpuSmoothNormalContext::CpuSmoothNormalContext(
Far::TopologyRefiner const & refiner, int level, bool resetMemory) : Far::TopologyRefiner const & refiner, int level, bool resetMemory) :
_numVertices(0), _resetMemory(resetMemory) { _numVertices(0), _resetMemory(resetMemory) {
int nfaces = refiner.GetNumFaces(level), int nfaces = refiner.GetLevel(level).GetNumFaces(),
nverts = nfaces * 4; nverts = nfaces * 4;
_faceVerts.resize(nverts); _faceVerts.resize(nverts);
Far::Index * dest = &_faceVerts[0]; Far::Index * dest = &_faceVerts[0];
for (int face=0; face<nfaces; ++face, dest+=4) { for (int face=0; face<nfaces; ++face, dest+=4) {
Far::ConstIndexArray fverts = refiner.GetFaceVertices(level, face); Far::ConstIndexArray fverts = refiner.GetLevel(level).GetFaceVertices(face);
memcpy(dest, fverts.begin(), 4 * sizeof(Far::Index)); memcpy(dest, fverts.begin(), 4 * sizeof(Far::Index));
} }
} }

View File

@ -27,7 +27,7 @@
#include <cuda_runtime.h> #include <cuda_runtime.h>
#include <vector> #include <vector>
#include "../far/stencilTables.h" #include "../far/stencilTable.h"
extern "C" { extern "C" {
void CudaEvalStencils(const float *src, void CudaEvalStencils(const float *src,
@ -69,19 +69,19 @@ createCudaBuffer(std::vector<T> const & src) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
CudaStencilTables::CudaStencilTables(Far::StencilTables const *stencilTables) { CudaStencilTable::CudaStencilTable(Far::StencilTable const *stencilTable) {
_numStencils = stencilTables->GetNumStencils(); _numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0) { if (_numStencils > 0) {
_sizes = createCudaBuffer(stencilTables->GetSizes()); _sizes = createCudaBuffer(stencilTable->GetSizes());
_offsets = createCudaBuffer(stencilTables->GetOffsets()); _offsets = createCudaBuffer(stencilTable->GetOffsets());
_indices = createCudaBuffer(stencilTables->GetControlIndices()); _indices = createCudaBuffer(stencilTable->GetControlIndices());
_weights = createCudaBuffer(stencilTables->GetWeights()); _weights = createCudaBuffer(stencilTable->GetWeights());
} else { } else {
_sizes = _offsets = _indices = _weights = NULL; _sizes = _offsets = _indices = _weights = NULL;
} }
} }
CudaStencilTables::~CudaStencilTables() { CudaStencilTable::~CudaStencilTable() {
if (_sizes) cudaFree(_sizes); if (_sizes) cudaFree(_sizes);
if (_offsets) cudaFree(_offsets); if (_offsets) cudaFree(_offsets);
if (_indices) cudaFree(_indices); if (_indices) cudaFree(_indices);

View File

@ -34,28 +34,28 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
class StencilTables; class StencilTable;
} }
namespace Osd { 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 /// CudaComputeKernel consumes this table to apply stencils
/// ///
/// ///
class CudaStencilTables { class CudaStencilTable {
public: public:
static CudaStencilTables *Create(Far::StencilTables const *stencilTables, static CudaStencilTable *Create(Far::StencilTable const *stencilTable,
void *deviceContext = NULL) { void *deviceContext = NULL) {
(void)deviceContext; // unused (void)deviceContext; // unused
return new CudaStencilTables(stencilTables); return new CudaStencilTable(stencilTable);
} }
explicit CudaStencilTables(Far::StencilTables const *stencilTables); explicit CudaStencilTable(Far::StencilTable const *stencilTable);
~CudaStencilTables(); ~CudaStencilTable();
// interfaces needed for CudaCompute // interfaces needed for CudaCompute
void *GetSizesBuffer() const { return _sizes; } void *GetSizesBuffer() const { return _sizes; }
@ -92,7 +92,7 @@ public:
/// ///
/// @param dstDesc vertex buffer descriptor for the output buffer /// @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. /// Cuda memory interfaces.
/// ///
/// @param instance not used in the CudaEvaluator /// @param instance not used in the CudaEvaluator

View File

@ -35,7 +35,7 @@
#include <D3Dcompiler.h> #include <D3Dcompiler.h>
#include "../far/error.h" #include "../far/error.h"
#include "../far/stencilTables.h" #include "../far/stencilTable.h"
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
@ -112,37 +112,37 @@ static ID3D11ShaderResourceView *createSRV(ID3D11Buffer *buffer,
return srv; return srv;
} }
D3D11StencilTables::D3D11StencilTables(Far::StencilTables const *stencilTables, D3D11StencilTable::D3D11StencilTable(Far::StencilTable const *stencilTable,
ID3D11DeviceContext *deviceContext) ID3D11DeviceContext *deviceContext)
{ {
ID3D11Device *device = NULL; ID3D11Device *device = NULL;
deviceContext->GetDevice(&device); deviceContext->GetDevice(&device);
assert(device); assert(device);
_numStencils = stencilTables->GetNumStencils(); _numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0) { if (_numStencils > 0) {
std::vector<int> const &sizes = stencilTables->GetSizes(); std::vector<int> const &sizes = stencilTable->GetSizes();
_sizesBuffer = createBuffer(sizes, device); _sizesBuffer = createBuffer(sizes, device);
_offsetsBuffer = createBuffer(stencilTables->GetOffsets(), device); _offsetsBuffer = createBuffer(stencilTable->GetOffsets(), device);
_indicesBuffer = createBuffer(stencilTables->GetControlIndices(), device); _indicesBuffer = createBuffer(stencilTable->GetControlIndices(), device);
_weightsBuffer = createBuffer(stencilTables->GetWeights(), device); _weightsBuffer = createBuffer(stencilTable->GetWeights(), device);
_sizes = createSRV(_sizesBuffer, DXGI_FORMAT_R32_SINT, device, _sizes = createSRV(_sizesBuffer, DXGI_FORMAT_R32_SINT, device,
stencilTables->GetSizes().size()); stencilTable->GetSizes().size());
_offsets = createSRV(_offsetsBuffer, DXGI_FORMAT_R32_SINT, device, _offsets = createSRV(_offsetsBuffer, DXGI_FORMAT_R32_SINT, device,
stencilTables->GetOffsets().size()); stencilTable->GetOffsets().size());
_indices = createSRV(_indicesBuffer, DXGI_FORMAT_R32_SINT, device, _indices = createSRV(_indicesBuffer, DXGI_FORMAT_R32_SINT, device,
stencilTables->GetControlIndices().size()); stencilTable->GetControlIndices().size());
_weights= createSRV(_weightsBuffer, DXGI_FORMAT_R32_FLOAT, device, _weights= createSRV(_weightsBuffer, DXGI_FORMAT_R32_FLOAT, device,
stencilTables->GetWeights().size()); stencilTable->GetWeights().size());
} else { } else {
_sizes = _offsets = _indices = _weights = NULL; _sizes = _offsets = _indices = _weights = NULL;
_sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL; _sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL;
} }
} }
D3D11StencilTables::~D3D11StencilTables() { D3D11StencilTable::~D3D11StencilTable() {
SAFE_RELEASE(_sizes); SAFE_RELEASE(_sizes);
SAFE_RELEASE(_sizesBuffer); SAFE_RELEASE(_sizesBuffer);
SAFE_RELEASE(_offsets); SAFE_RELEASE(_offsets);
@ -341,7 +341,7 @@ D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV,
ID3D11ShaderResourceView *SRViews[] = { ID3D11ShaderResourceView *SRViews[] = {
sizesSRV, offsetsSRV, indicesSRV, weightsSRV }; sizesSRV, offsetsSRV, indicesSRV, weightsSRV };
// bind source vertex and stencil tables // bind source vertex and stencil table
deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4 deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4
if (srcUAV == dstUAV) { if (srcUAV == dstUAV) {
@ -356,7 +356,7 @@ D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV,
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1); 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; SRViews[0] = SRViews[1] = SRViews[2] = SRViews[3] = NULL;
deviceContext->CSSetShaderResources(1, 4, SRViews); deviceContext->CSSetShaderResources(1, 4, SRViews);

View File

@ -41,35 +41,35 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
class StencilTables; class StencilTable;
} }
namespace Osd { namespace Osd {
/// \brief D3D11 stencil tables /// \brief D3D11 stencil table
/// ///
/// This class is a D3D11 Shader Resource View representation of /// This class is a D3D11 Shader Resource View representation of
/// Far::StencilTables. /// Far::StencilTable.
/// ///
/// D3D11ComputeEvaluator consumes this table to apply stencils /// D3D11ComputeEvaluator consumes this table to apply stencils
/// ///
class D3D11StencilTables { class D3D11StencilTable {
public: public:
template <typename DEVICE_CONTEXT> template <typename DEVICE_CONTEXT>
static D3D11StencilTables *Create(Far::StencilTables const *stencilTables, static D3D11StencilTable *Create(Far::StencilTable const *stencilTable,
DEVICE_CONTEXT context) { 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) { ID3D11DeviceContext *deviceContext) {
return new D3D11StencilTables(stencilTables, deviceContext); return new D3D11StencilTable(stencilTable, deviceContext);
} }
D3D11StencilTables(Far::StencilTables const *stencilTables, D3D11StencilTable(Far::StencilTable const *stencilTable,
ID3D11DeviceContext *deviceContext); ID3D11DeviceContext *deviceContext);
~D3D11StencilTables(); ~D3D11StencilTable();
// interfaces needed for D3D11ComputeEvaluator // interfaces needed for D3D11ComputeEvaluator
ID3D11ShaderResourceView *GetSizesSRV() const { return _sizes; } ID3D11ShaderResourceView *GetSizesSRV() const { return _sizes; }
@ -122,7 +122,7 @@ public:
/// ///
/// @param dstDesc vertex buffer descriptor for the output buffer /// @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. /// SSBO interfaces.
/// ///
/// @param instance cached compiled instance. Clients are supposed to /// @param instance cached compiled instance. Clients are supposed to

View File

@ -46,7 +46,7 @@ D3D11LegacyGregoryPatchTable::~D3D11LegacyGregoryPatchTable() {
} }
D3D11LegacyGregoryPatchTable * D3D11LegacyGregoryPatchTable *
D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables, D3D11LegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable,
ID3D11DeviceContext *pd3d11DeviceContext) { ID3D11DeviceContext *pd3d11DeviceContext) {
ID3D11Device *pd3d11Device = NULL; ID3D11Device *pd3d11Device = NULL;
pd3d11DeviceContext->GetDevice(&pd3d11Device); pd3d11DeviceContext->GetDevice(&pd3d11Device);
@ -54,10 +54,10 @@ D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables,
D3D11LegacyGregoryPatchTable *result = new D3D11LegacyGregoryPatchTable(); D3D11LegacyGregoryPatchTable *result = new D3D11LegacyGregoryPatchTable();
Far::PatchTables::VertexValenceTable const & Far::PatchTable::VertexValenceTable const &
valenceTable = farPatchTables->GetVertexValenceTable(); valenceTable = farPatchTable->GetVertexValenceTable();
Far::PatchTables::QuadOffsetsTable const & Far::PatchTable::QuadOffsetsTable const &
quadOffsetsTable = farPatchTables->GetQuadOffsetsTable(); quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
if (not valenceTable.empty()) { if (not valenceTable.empty()) {
D3D11_BUFFER_DESC bd; D3D11_BUFFER_DESC bd;
@ -126,11 +126,11 @@ D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables,
result->_quadOffsetsBase[1] = 0; result->_quadOffsetsBase[1] = 0;
// scan patchtable to find quadOffsetsBase. // 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. // GREGORY_BOUNDARY's quadoffsets come after GREGORY's.
if (farPatchTables->GetPatchArrayDescriptor(i) == if (farPatchTable->GetPatchArrayDescriptor(i) ==
Far::PatchDescriptor::GREGORY) { Far::PatchDescriptor::GREGORY) {
result->_quadOffsetsBase[1] = farPatchTables->GetNumPatches(i) * 4; result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
break; break;
} }
} }

View File

@ -27,7 +27,7 @@
#include "../version.h" #include "../version.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
#include "../osd/nonCopyable.h" #include "../osd/nonCopyable.h"
struct ID3D11Buffer; struct ID3D11Buffer;
@ -47,12 +47,12 @@ public:
template<typename DEVICE_CONTEXT> template<typename DEVICE_CONTEXT>
static D3D11LegacyGregoryPatchTable *Create( static D3D11LegacyGregoryPatchTable *Create(
Far::PatchTables const *farPatchTables, DEVICE_CONTEXT context) { Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context) {
return Create(farPatchTables, context->GetDeviceContext()); return Create(farPatchTable, context->GetDeviceContext());
} }
static D3D11LegacyGregoryPatchTable *Create( static D3D11LegacyGregoryPatchTable *Create(
Far::PatchTables const *farPatchTables, Far::PatchTable const *farPatchTable,
ID3D11DeviceContext *deviceContext); ID3D11DeviceContext *deviceContext);
void UpdateVertexBuffer(ID3D11Buffer *vbo, void UpdateVertexBuffer(ID3D11Buffer *vbo,

View File

@ -25,7 +25,7 @@
#include "../osd/d3d11PatchTable.h" #include "../osd/d3d11PatchTable.h"
#include <D3D11.h> #include <D3D11.h>
#include "../far/patchTables.h" #include "../far/patchTable.h"
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
@ -43,17 +43,17 @@ D3D11PatchTable::~D3D11PatchTable() {
} }
D3D11PatchTable * D3D11PatchTable *
D3D11PatchTable::Create(Far::PatchTables const *farPatchTables, D3D11PatchTable::Create(Far::PatchTable const *farPatchTable,
ID3D11DeviceContext *pd3d11DeviceContext) { ID3D11DeviceContext *pd3d11DeviceContext) {
D3D11PatchTable *instance = new D3D11PatchTable(); D3D11PatchTable *instance = new D3D11PatchTable();
if (instance->allocate(farPatchTables, pd3d11DeviceContext)) if (instance->allocate(farPatchTable, pd3d11DeviceContext))
return instance; return instance;
delete instance; delete instance;
return 0; return 0;
} }
bool bool
D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables, D3D11PatchTable::allocate(Far::PatchTable const *farPatchTable,
ID3D11DeviceContext *pd3d11DeviceContext) { ID3D11DeviceContext *pd3d11DeviceContext) {
ID3D11Device *pd3d11Device = NULL; ID3D11Device *pd3d11Device = NULL;
pd3d11DeviceContext->GetDevice(&pd3d11Device); pd3d11DeviceContext->GetDevice(&pd3d11Device);
@ -63,18 +63,18 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables,
std::vector<unsigned int> ppBuffer; std::vector<unsigned int> ppBuffer;
// needs reserve? // needs reserve?
int nPatchArrays = farPatchTables->GetNumPatchArrays(); int nPatchArrays = farPatchTable->GetNumPatchArrays();
// for each patchArray // for each patchArray
for (int j = 0; j < nPatchArrays; ++j) { for (int j = 0; j < nPatchArrays; ++j) {
PatchArray patchArray(farPatchTables->GetPatchArrayDescriptor(j), PatchArray patchArray(farPatchTable->GetPatchArrayDescriptor(j),
farPatchTables->GetNumPatches(j), farPatchTable->GetNumPatches(j),
(int)buffer.size(), (int)buffer.size(),
(int)ppBuffer.size()/3); (int)ppBuffer.size()/3);
_patchArrays.push_back(patchArray); _patchArrays.push_back(patchArray);
// indices // indices
Far::ConstIndexArray indices = farPatchTables->GetPatchArrayVertices(j); Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j);
for (int k = 0; k < indices.size(); ++k) { for (int k = 0; k < indices.size(); ++k) {
buffer.push_back(indices[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 // XXX: we need sharpness interface for patcharray or put sharpness
// into patchParam. // into patchParam.
Far::ConstPatchParamArray patchParams = Far::ConstPatchParamArray patchParams =
farPatchTables->GetPatchParams(j); farPatchTable->GetPatchParams(j);
for (int k = 0; k < patchParams.size(); ++k) { for (int k = 0; k < patchParams.size(); ++k) {
float sharpness = 0.0; float sharpness = 0.0;
ppBuffer.push_back(patchParams[k].faceIndex); ppBuffer.push_back(patchParams[k].faceIndex);
@ -93,21 +93,21 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables,
} }
#else #else
// XXX: workaround. GetPatchParamTable() will be deprecated though. // XXX: workaround. GetPatchParamTable() will be deprecated though.
Far::PatchParamTable const & patchParamTables = Far::PatchParamTable const & patchParamTable =
farPatchTables->GetPatchParamTable(); farPatchTable->GetPatchParamTable();
std::vector<Far::Index> const &sharpnessIndexTable = std::vector<Far::Index> const &sharpnessIndexTable =
farPatchTables->GetSharpnessIndexTable(); farPatchTable->GetSharpnessIndexTable();
int numPatches = farPatchTables->GetNumPatches(j); int numPatches = farPatchTable->GetNumPatches(j);
for (int k = 0; k < numPatches; ++k) { for (int k = 0; k < numPatches; ++k) {
float sharpness = 0.0; float sharpness = 0.0;
int patchIndex = (int)ppBuffer.size()/3; int patchIndex = (int)ppBuffer.size()/3;
if (patchIndex < (int)sharpnessIndexTable.size()) { if (patchIndex < (int)sharpnessIndexTable.size()) {
int sharpnessIndex = sharpnessIndexTable[patchIndex]; int sharpnessIndex = sharpnessIndexTable[patchIndex];
if (sharpnessIndex >= 0) if (sharpnessIndex >= 0)
sharpness = farPatchTables->GetSharpnessValues()[sharpnessIndex]; sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex];
} }
ppBuffer.push_back(patchParamTables[patchIndex].faceIndex); ppBuffer.push_back(patchParamTable[patchIndex].faceIndex);
ppBuffer.push_back(patchParamTables[patchIndex].bitField.field); ppBuffer.push_back(patchParamTable[patchIndex].bitField.field);
ppBuffer.push_back(*((unsigned int *)&sharpness)); ppBuffer.push_back(*((unsigned int *)&sharpness));
} }
#endif #endif

View File

@ -40,7 +40,7 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far{ namespace Far{
class PatchTables; class PatchTable;
}; };
namespace Osd { namespace Osd {
@ -80,12 +80,12 @@ public:
~D3D11PatchTable(); ~D3D11PatchTable();
template<typename DEVICE_CONTEXT> template<typename DEVICE_CONTEXT>
static D3D11PatchTable *Create(Far::PatchTables const *farPatchTables, static D3D11PatchTable *Create(Far::PatchTable const *farPatchTable,
DEVICE_CONTEXT context) { 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); ID3D11DeviceContext *deviceContext);
PatchArrayVector const &GetPatchArrays() const { PatchArrayVector const &GetPatchArrays() const {
@ -103,8 +103,8 @@ public:
} }
protected: protected:
// allocate buffers from patchTables // allocate buffers from patchTable
bool allocate(Far::PatchTables const *farPatchTables, bool allocate(Far::PatchTable const *farPatchTable,
ID3D11DeviceContext *deviceContext); ID3D11DeviceContext *deviceContext);
PatchArrayVector _patchArrays; PatchArrayVector _patchArrays;

View File

@ -30,7 +30,7 @@
#include <vector> #include <vector>
#include "../far/error.h" #include "../far/error.h"
#include "../far/stencilTables.h" #include "../far/stencilTable.h"
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
@ -65,20 +65,20 @@ createSSBO(std::vector<T> const & src) {
return devicePtr; return devicePtr;
} }
GLStencilTablesSSBO::GLStencilTablesSSBO( GLStencilTableSSBO::GLStencilTableSSBO(
Far::StencilTables const *stencilTables) { Far::StencilTable const *stencilTable) {
_numStencils = stencilTables->GetNumStencils(); _numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0) { if (_numStencils > 0) {
_sizes = createSSBO(stencilTables->GetSizes()); _sizes = createSSBO(stencilTable->GetSizes());
_offsets = createSSBO(stencilTables->GetOffsets()); _offsets = createSSBO(stencilTable->GetOffsets());
_indices = createSSBO(stencilTables->GetControlIndices()); _indices = createSSBO(stencilTable->GetControlIndices());
_weights = createSSBO(stencilTables->GetWeights()); _weights = createSSBO(stencilTable->GetWeights());
} else { } else {
_sizes = _offsets = _indices = _weights = 0; _sizes = _offsets = _indices = _weights = 0;
} }
} }
GLStencilTablesSSBO::~GLStencilTablesSSBO() { GLStencilTableSSBO::~GLStencilTableSSBO() {
if (_sizes) glDeleteBuffers(1, &_sizes); if (_sizes) glDeleteBuffers(1, &_sizes);
if (_offsets) glDeleteBuffers(1, &_offsets); if (_offsets) glDeleteBuffers(1, &_offsets);
if (_weights) glDeleteBuffers(1, &_weights); if (_weights) glDeleteBuffers(1, &_weights);

View File

@ -34,27 +34,27 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
class StencilTables; class StencilTable;
} }
namespace Osd { 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 /// GLSLComputeKernel consumes this table to apply stencils
/// ///
class GLStencilTablesSSBO { class GLStencilTableSSBO {
public: public:
static GLStencilTablesSSBO *Create(Far::StencilTables const *stencilTables, static GLStencilTableSSBO *Create(Far::StencilTable const *stencilTable,
void *deviceContext = NULL) { void *deviceContext = NULL) {
(void)deviceContext; // unused (void)deviceContext; // unused
return new GLStencilTablesSSBO(stencilTables); return new GLStencilTableSSBO(stencilTable);
} }
explicit GLStencilTablesSSBO(Far::StencilTables const *stencilTables); explicit GLStencilTableSSBO(Far::StencilTable const *stencilTable);
~GLStencilTablesSSBO(); ~GLStencilTableSSBO();
// interfaces needed for GLSLComputeKernel // interfaces needed for GLSLComputeKernel
GLuint GetSizesBuffer() const { return _sizes; } GLuint GetSizesBuffer() const { return _sizes; }
@ -190,7 +190,7 @@ public:
private: private:
GLuint _program; GLuint _program;
GLuint _uniformSizes, // stencil tables GLuint _uniformSizes, // stencil table
_uniformOffsets, _uniformOffsets,
_uniformIndices, _uniformIndices,
_uniformWeights, _uniformWeights,

View File

@ -45,17 +45,17 @@ GLLegacyGregoryPatchTable::~GLLegacyGregoryPatchTable() {
} }
GLLegacyGregoryPatchTable * GLLegacyGregoryPatchTable *
GLLegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables) { GLLegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable) {
GLLegacyGregoryPatchTable *result = new GLLegacyGregoryPatchTable(); GLLegacyGregoryPatchTable *result = new GLLegacyGregoryPatchTable();
glGenTextures(1, &result->_vertexTextureBuffer); glGenTextures(1, &result->_vertexTextureBuffer);
glGenTextures(1, &result->_vertexValenceTextureBuffer); glGenTextures(1, &result->_vertexValenceTextureBuffer);
glGenTextures(1, &result->_quadOffsetsTextureBuffer); glGenTextures(1, &result->_quadOffsetsTextureBuffer);
Far::PatchTables::VertexValenceTable const & Far::PatchTable::VertexValenceTable const &
valenceTable = farPatchTables->GetVertexValenceTable(); valenceTable = farPatchTable->GetVertexValenceTable();
Far::PatchTables::QuadOffsetsTable const & Far::PatchTable::QuadOffsetsTable const &
quadOffsetsTable = farPatchTables->GetQuadOffsetsTable(); quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
GLuint buffers[2]; GLuint buffers[2];
glGenBuffers(2, buffers); glGenBuffers(2, buffers);
@ -82,11 +82,11 @@ GLLegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables) {
result->_quadOffsetsBase[0] = 0; result->_quadOffsetsBase[0] = 0;
result->_quadOffsetsBase[1] = 0; result->_quadOffsetsBase[1] = 0;
// scan patchtable to find quadOffsetsBase. // 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. // GREGORY_BOUNDARY's quadoffsets come after GREGORY's.
if (farPatchTables->GetPatchArrayDescriptor(i) == if (farPatchTable->GetPatchArrayDescriptor(i) ==
Far::PatchDescriptor::GREGORY) { Far::PatchDescriptor::GREGORY) {
result->_quadOffsetsBase[1] = farPatchTables->GetNumPatches(i) * 4; result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
break; break;
} }
} }

View File

@ -27,7 +27,7 @@
#include "../version.h" #include "../version.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
#include "../osd/nonCopyable.h" #include "../osd/nonCopyable.h"
#include "../osd/opengl.h" #include "../osd/opengl.h"
@ -41,7 +41,7 @@ class GLLegacyGregoryPatchTable
public: public:
~GLLegacyGregoryPatchTable(); ~GLLegacyGregoryPatchTable();
static GLLegacyGregoryPatchTable *Create(Far::PatchTables const *patchTable); static GLLegacyGregoryPatchTable *Create(Far::PatchTable const *patchTable);
void UpdateVertexBuffer(GLuint vbo); void UpdateVertexBuffer(GLuint vbo);

View File

@ -24,7 +24,7 @@
#include "../osd/glPatchTable.h" #include "../osd/glPatchTable.h"
#include "../far/patchTables.h" #include "../far/patchTable.h"
#include "../osd/opengl.h" #include "../osd/opengl.h"
namespace OpenSubdiv { namespace OpenSubdiv {
@ -42,16 +42,16 @@ GLPatchTable::~GLPatchTable() {
} }
GLPatchTable * GLPatchTable *
GLPatchTable::Create(Far::PatchTables const *farPatchTables, GLPatchTable::Create(Far::PatchTable const *farPatchTable,
void * /*deviceContext*/) { void * /*deviceContext*/) {
GLPatchTable *instance = new GLPatchTable(); GLPatchTable *instance = new GLPatchTable();
if (instance->allocate(farPatchTables)) return instance; if (instance->allocate(farPatchTable)) return instance;
delete instance; delete instance;
return 0; return 0;
} }
bool bool
GLPatchTable::allocate(Far::PatchTables const *farPatchTables) { GLPatchTable::allocate(Far::PatchTable const *farPatchTable) {
glGenBuffers(1, &_indexBuffer); glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
@ -60,18 +60,18 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) {
// needs reserve? // needs reserve?
int nPatchArrays = farPatchTables->GetNumPatchArrays(); int nPatchArrays = farPatchTable->GetNumPatchArrays();
// for each patchArray // for each patchArray
for (int j = 0; j < nPatchArrays; ++j) { for (int j = 0; j < nPatchArrays; ++j) {
PatchArray patchArray(farPatchTables->GetPatchArrayDescriptor(j), PatchArray patchArray(farPatchTable->GetPatchArrayDescriptor(j),
farPatchTables->GetNumPatches(j), farPatchTable->GetNumPatches(j),
(int)buffer.size(), (int)buffer.size(),
(int)ppBuffer.size()/3); (int)ppBuffer.size()/3);
_patchArrays.push_back(patchArray); _patchArrays.push_back(patchArray);
// indices // indices
Far::ConstIndexArray indices = farPatchTables->GetPatchArrayVertices(j); Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j);
for (int k = 0; k < indices.size(); ++k) { for (int k = 0; k < indices.size(); ++k) {
buffer.push_back(indices[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 // XXX: we need sharpness interface for patcharray or put sharpness
// into patchParam. // into patchParam.
Far::ConstPatchParamArray patchParams = Far::ConstPatchParamArray patchParams =
farPatchTables->GetPatchParams(j); farPatchTable->GetPatchParams(j);
for (int k = 0; k < patchParams.size(); ++k) { for (int k = 0; k < patchParams.size(); ++k) {
float sharpness = 0.0; float sharpness = 0.0;
ppBuffer.push_back(patchParams[k].faceIndex); ppBuffer.push_back(patchParams[k].faceIndex);
@ -90,21 +90,21 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) {
} }
#else #else
// XXX: workaround. GetPatchParamTable() will be deprecated though. // XXX: workaround. GetPatchParamTable() will be deprecated though.
Far::PatchParamTable const & patchParamTables = Far::PatchParamTable const & patchParamTable =
farPatchTables->GetPatchParamTable(); farPatchTable->GetPatchParamTable();
std::vector<Far::Index> const &sharpnessIndexTable = std::vector<Far::Index> const &sharpnessIndexTable =
farPatchTables->GetSharpnessIndexTable(); farPatchTable->GetSharpnessIndexTable();
int numPatches = farPatchTables->GetNumPatches(j); int numPatches = farPatchTable->GetNumPatches(j);
for (int k = 0; k < numPatches; ++k) { for (int k = 0; k < numPatches; ++k) {
float sharpness = 0.0; float sharpness = 0.0;
int patchIndex = (int)ppBuffer.size()/3; int patchIndex = (int)ppBuffer.size()/3;
if (patchIndex < (int)sharpnessIndexTable.size()) { if (patchIndex < (int)sharpnessIndexTable.size()) {
int sharpnessIndex = sharpnessIndexTable[patchIndex]; int sharpnessIndex = sharpnessIndexTable[patchIndex];
if (sharpnessIndex >= 0) if (sharpnessIndex >= 0)
sharpness = farPatchTables->GetSharpnessValues()[sharpnessIndex]; sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex];
} }
ppBuffer.push_back(patchParamTables[patchIndex].faceIndex); ppBuffer.push_back(patchParamTable[patchIndex].faceIndex);
ppBuffer.push_back(patchParamTables[patchIndex].bitField.field); ppBuffer.push_back(patchParamTable[patchIndex].bitField.field);
ppBuffer.push_back(*((unsigned int *)&sharpness)); ppBuffer.push_back(*((unsigned int *)&sharpness));
} }
#endif #endif

View File

@ -36,7 +36,7 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far{ namespace Far{
class PatchTables; class PatchTable;
}; };
namespace Osd { namespace Osd {
@ -75,7 +75,7 @@ public:
GLPatchTable(); GLPatchTable();
~GLPatchTable(); ~GLPatchTable();
static GLPatchTable *Create(Far::PatchTables const *farPatchTables, static GLPatchTable *Create(Far::PatchTable const *farPatchTable,
void *deviceContext = NULL); void *deviceContext = NULL);
PatchArrayVector const &GetPatchArrays() const { PatchArrayVector const &GetPatchArrays() const {
@ -93,8 +93,8 @@ public:
} }
protected: protected:
// allocate buffers from patchTables // allocate buffers from patchTable
bool allocate(Far::PatchTables const *farPatchTables); bool allocate(Far::PatchTable const *farPatchTable);
PatchArrayVector _patchArrays; PatchArrayVector _patchArrays;
GLuint _indexBuffer; GLuint _indexBuffer;

View File

@ -30,7 +30,7 @@
#include <cstdio> #include <cstdio>
#include "../far/error.h" #include "../far/error.h"
#include "../far/stencilTables.h" #include "../far/stencilTable.h"
#if _MSC_VER #if _MSC_VER
#define snprintf _snprintf #define snprintf _snprintf
@ -82,23 +82,23 @@ createGLTextureBuffer(std::vector<T> const & src, GLenum type) {
return devicePtr; return devicePtr;
} }
GLStencilTablesTBO::GLStencilTablesTBO( GLStencilTableTBO::GLStencilTableTBO(
Far::StencilTables const *stencilTables) { Far::StencilTable const *stencilTable) {
_numStencils = stencilTables->GetNumStencils(); _numStencils = stencilTable->GetNumStencils();
if (_numStencils > 0) { if (_numStencils > 0) {
_sizes = createGLTextureBuffer(stencilTables->GetSizes(), GL_R32UI); _sizes = createGLTextureBuffer(stencilTable->GetSizes(), GL_R32UI);
_offsets = createGLTextureBuffer( _offsets = createGLTextureBuffer(
stencilTables->GetOffsets(), GL_R32I); stencilTable->GetOffsets(), GL_R32I);
_indices = createGLTextureBuffer( _indices = createGLTextureBuffer(
stencilTables->GetControlIndices(), GL_R32I); stencilTable->GetControlIndices(), GL_R32I);
_weights = createGLTextureBuffer(stencilTables->GetWeights(), GL_R32F); _weights = createGLTextureBuffer(stencilTable->GetWeights(), GL_R32F);
} else { } else {
_sizes = _offsets = _indices = _weights = 0; _sizes = _offsets = _indices = _weights = 0;
} }
} }
GLStencilTablesTBO::~GLStencilTablesTBO() { GLStencilTableTBO::~GLStencilTableTBO() {
if (_sizes) glDeleteTextures(1, &_sizes); if (_sizes) glDeleteTextures(1, &_sizes);
if (_offsets) glDeleteTextures(1, &_offsets); if (_offsets) glDeleteTextures(1, &_offsets);
if (_weights) glDeleteTextures(1, &_weights); if (_weights) glDeleteTextures(1, &_weights);
@ -277,7 +277,7 @@ GLXFBEvaluator::EvalStencils(GLuint srcBuffer,
bindTexture(_uniformSrcBufferTexture, _srcBufferTexture, 0); bindTexture(_uniformSrcBufferTexture, _srcBufferTexture, 0);
// bind stencil tables textures. // bind stencil table textures.
bindTexture(_uniformSizesTexture, sizesTexture, 1); bindTexture(_uniformSizesTexture, sizesTexture, 1);
bindTexture(_uniformOffsetsTexture, offsetsTexture, 2); bindTexture(_uniformOffsetsTexture, offsetsTexture, 2);
bindTexture(_uniformIndicesTexture, indicesTexture, 3); bindTexture(_uniformIndicesTexture, indicesTexture, 3);

View File

@ -34,28 +34,28 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far { namespace Far {
class StencilTables; class StencilTable;
} }
namespace Osd { 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 /// GLSLTransformFeedback consumes this table to apply stencils
/// ///
/// ///
class GLStencilTablesTBO { class GLStencilTableTBO {
public: public:
static GLStencilTablesTBO *Create( static GLStencilTableTBO *Create(
Far::StencilTables const *stencilTables, void *deviceContext = NULL) { Far::StencilTable const *stencilTable, void *deviceContext = NULL) {
(void)deviceContext; // unused (void)deviceContext; // unused
return new GLStencilTablesTBO(stencilTables); return new GLStencilTableTBO(stencilTable);
} }
explicit GLStencilTablesTBO(Far::StencilTables const *stencilTables); explicit GLStencilTableTBO(Far::StencilTable const *stencilTable);
~GLStencilTablesTBO(); ~GLStencilTableTBO();
// interfaces needed for GLSLTransformFeedbackKernel // interfaces needed for GLSLTransformFeedbackKernel
GLuint GetSizesTexture() const { return _sizes; } GLuint GetSizesTexture() const { return _sizes; }

View File

@ -33,9 +33,9 @@
#include <vector> #include <vector>
#include "../far/topologyRefiner.h" #include "../far/topologyRefiner.h"
#include "../far/patchTablesFactory.h" #include "../far/patchTableFactory.h"
#include "../far/stencilTables.h" #include "../far/stencilTable.h"
#include "../far/stencilTablesFactory.h" #include "../far/stencilTableFactory.h"
#include "../osd/vertexDescriptor.h" #include "../osd/vertexDescriptor.h"
@ -87,7 +87,7 @@ public:
virtual PatchTable * GetPatchTable() const = 0; virtual PatchTable * GetPatchTable() const = 0;
virtual Far::PatchTables const *GetFarPatchTables() const = 0; virtual Far::PatchTable const *GetFarPatchTable() const = 0;
virtual VertexBufferBinding BindVertexBuffer() = 0; virtual VertexBufferBinding BindVertexBuffer() = 0;
@ -114,32 +114,32 @@ protected:
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename STENCIL_TABLES, typename DEVICE_CONTEXT> template <typename STENCIL_TABLE, typename DEVICE_CONTEXT>
STENCIL_TABLES const * STENCIL_TABLE const *
convertToCompatibleStencilTables( convertToCompatibleStencilTable(
Far::StencilTables const *table, DEVICE_CONTEXT *context) { Far::StencilTable const *table, DEVICE_CONTEXT *context) {
if (not table) return NULL; if (not table) return NULL;
return STENCIL_TABLES::Create(table, context); return STENCIL_TABLE::Create(table, context);
} }
template <> template <>
Far::StencilTables const * Far::StencilTable const *
convertToCompatibleStencilTables<Far::StencilTables, void>( convertToCompatibleStencilTable<Far::StencilTable, void>(
Far::StencilTables const *table, void * /*context*/) { Far::StencilTable const *table, void * /*context*/) {
// no need for conversion // no need for conversion
// XXX: We don't want to even copy. // XXX: We don't want to even copy.
if (not table) return NULL; if (not table) return NULL;
return new Far::StencilTables(*table); return new Far::StencilTable(*table);
} }
template <> template <>
Far::StencilTables const * Far::StencilTable const *
convertToCompatibleStencilTables<Far::StencilTables, ID3D11DeviceContext>( convertToCompatibleStencilTable<Far::StencilTable, ID3D11DeviceContext>(
Far::StencilTables const *table, ID3D11DeviceContext * /*context*/) { Far::StencilTable const *table, ID3D11DeviceContext * /*context*/) {
// no need for conversion // no need for conversion
// XXX: We don't want to even copy. // XXX: We don't want to even copy.
if (not table) return NULL; if (not table) return NULL;
return new Far::StencilTables(*table); return new Far::StencilTable(*table);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -231,7 +231,7 @@ static EVALUATOR *GetEvaluator(
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename VERTEX_BUFFER, template <typename VERTEX_BUFFER,
typename STENCIL_TABLES, typename STENCIL_TABLE,
typename EVALUATOR, typename EVALUATOR,
typename PATCH_TABLE, typename PATCH_TABLE,
typename DEVICE_CONTEXT = void> typename DEVICE_CONTEXT = void>
@ -239,7 +239,7 @@ class Mesh : public MeshInterface<PATCH_TABLE> {
public: public:
typedef VERTEX_BUFFER VertexBuffer; typedef VERTEX_BUFFER VertexBuffer;
typedef EVALUATOR Evaluator; typedef EVALUATOR Evaluator;
typedef STENCIL_TABLES StencilTables; typedef STENCIL_TABLE StencilTable;
typedef PATCH_TABLE PatchTable; typedef PATCH_TABLE PatchTable;
typedef DEVICE_CONTEXT DeviceContext; typedef DEVICE_CONTEXT DeviceContext;
typedef EvaluatorCacheT<Evaluator> EvaluatorCache; typedef EvaluatorCacheT<Evaluator> EvaluatorCache;
@ -254,13 +254,13 @@ public:
DeviceContext * deviceContext = NULL) : DeviceContext * deviceContext = NULL) :
_refiner(refiner), _refiner(refiner),
_farPatchTables(NULL), _farPatchTable(NULL),
_numVertices(0), _numVertices(0),
_maxValence(0), _maxValence(0),
_vertexBuffer(NULL), _vertexBuffer(NULL),
_varyingBuffer(NULL), _varyingBuffer(NULL),
_vertexStencilTables(NULL), _vertexStencilTable(NULL),
_varyingStencilTables(NULL), _varyingStencilTable(NULL),
_evaluatorCache(evaluatorCache), _evaluatorCache(evaluatorCache),
_patchTable(NULL), _patchTable(NULL),
_deviceContext(deviceContext) { _deviceContext(deviceContext) {
@ -302,11 +302,11 @@ public:
virtual ~Mesh() { virtual ~Mesh() {
delete _refiner; delete _refiner;
delete _farPatchTables; delete _farPatchTable;
delete _vertexBuffer; delete _vertexBuffer;
delete _varyingBuffer; delete _varyingBuffer;
delete _vertexStencilTables; delete _vertexStencilTable;
delete _varyingStencilTables; delete _varyingStencilTable;
delete _patchTable; delete _patchTable;
// deviceContext and evaluatorCache are not owned by this class. // deviceContext and evaluatorCache are not owned by this class.
} }
@ -325,7 +325,7 @@ public:
virtual void Refine() { virtual void Refine() {
int numControlVertices = _refiner->GetNumVertices(0); int numControlVertices = _refiner->GetLevel(0).GetNumVertices();
VertexBufferDescriptor srcDesc = _vertexDesc; VertexBufferDescriptor srcDesc = _vertexDesc;
VertexBufferDescriptor dstDesc(srcDesc); VertexBufferDescriptor dstDesc(srcDesc);
@ -339,7 +339,7 @@ public:
Evaluator::EvalStencils(_vertexBuffer, srcDesc, Evaluator::EvalStencils(_vertexBuffer, srcDesc,
_vertexBuffer, dstDesc, _vertexBuffer, dstDesc,
_vertexStencilTables, _vertexStencilTable,
instance, _deviceContext); instance, _deviceContext);
if (_varyingDesc.length > 0) { if (_varyingDesc.length > 0) {
@ -354,13 +354,13 @@ public:
// non-interleaved // non-interleaved
Evaluator::EvalStencils(_varyingBuffer, srcDesc, Evaluator::EvalStencils(_varyingBuffer, srcDesc,
_varyingBuffer, dstDesc, _varyingBuffer, dstDesc,
_varyingStencilTables, _varyingStencilTable,
instance, _deviceContext); instance, _deviceContext);
} else { } else {
// interleaved // interleaved
Evaluator::EvalStencils(_vertexBuffer, srcDesc, Evaluator::EvalStencils(_vertexBuffer, srcDesc,
_vertexBuffer, dstDesc, _vertexBuffer, dstDesc,
_varyingStencilTables, _varyingStencilTable,
instance, _deviceContext); instance, _deviceContext);
} }
} }
@ -374,8 +374,8 @@ public:
return _patchTable; return _patchTable;
} }
virtual Far::PatchTables const *GetFarPatchTables() const { virtual Far::PatchTable const *GetFarPatchTable() const {
return _farPatchTables; return _farPatchTable;
} }
virtual int GetNumVertices() const { return _numVertices; } virtual int GetNumVertices() const { return _numVertices; }
@ -408,85 +408,85 @@ private:
int level, MeshBitset bits) { int level, MeshBitset bits) {
assert(_refiner); assert(_refiner);
Far::StencilTablesFactory::Options options; Far::StencilTableFactory::Options options;
options.generateOffsets = true; options.generateOffsets = true;
options.generateIntermediateLevels = options.generateIntermediateLevels =
_refiner->IsUniform() ? false : true; _refiner->IsUniform() ? false : true;
Far::StencilTables const * vertexStencils = NULL; Far::StencilTable const * vertexStencils = NULL;
Far::StencilTables const * varyingStencils = NULL; Far::StencilTable const * varyingStencils = NULL;
if (numVertexElements>0) { if (numVertexElements>0) {
vertexStencils = Far::StencilTablesFactory::Create(*_refiner, vertexStencils = Far::StencilTableFactory::Create(*_refiner,
options); options);
} }
if (numVaryingElements>0) { if (numVaryingElements>0) {
options.interpolationMode = options.interpolationMode =
Far::StencilTablesFactory::INTERPOLATE_VARYING; Far::StencilTableFactory::INTERPOLATE_VARYING;
varyingStencils = Far::StencilTablesFactory::Create(*_refiner, varyingStencils = Far::StencilTableFactory::Create(*_refiner,
options); options);
} }
Far::PatchTablesFactory::Options poptions(level); Far::PatchTableFactory::Options poptions(level);
poptions.generateFVarTables = bits.test(MeshFVarData); poptions.generateFVarTables = bits.test(MeshFVarData);
poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch); poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
if (bits.test(MeshEndCapBSplineBasis)) { if (bits.test(MeshEndCapBSplineBasis)) {
poptions.SetEndCapType( poptions.SetEndCapType(
Far::PatchTablesFactory::Options::ENDCAP_BSPLINE_BASIS); Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
} else if (bits.test(MeshEndCapGregoryBasis)) { } else if (bits.test(MeshEndCapGregoryBasis)) {
poptions.SetEndCapType( poptions.SetEndCapType(
Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS); Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
// points on gregory basis endcap boundary can be shared among // points on gregory basis endcap boundary can be shared among
// adjacent patches to save some stencils. // adjacent patches to save some stencils.
poptions.shareEndCapPatchPoints = true; poptions.shareEndCapPatchPoints = true;
} else if (bits.test(MeshEndCapLegacyGregory)) { } else if (bits.test(MeshEndCapLegacyGregory)) {
poptions.SetEndCapType( 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 there's endcap stencils, merge it into regular stencils.
if (_farPatchTables->GetEndCapVertexStencilTables()) { if (_farPatchTable->GetEndCapVertexStencilTable()) {
// append stencils // append stencils
if (Far::StencilTables const *vertexStencilsWithEndCap = if (Far::StencilTable const *vertexStencilsWithEndCap =
Far::StencilTablesFactory::AppendEndCapStencilTables( Far::StencilTableFactory::AppendEndCapStencilTable(
*_refiner, *_refiner,
vertexStencils, vertexStencils,
_farPatchTables->GetEndCapVertexStencilTables())) { _farPatchTable->GetEndCapVertexStencilTable())) {
delete vertexStencils; delete vertexStencils;
vertexStencils = vertexStencilsWithEndCap; vertexStencils = vertexStencilsWithEndCap;
} }
if (varyingStencils) { if (varyingStencils) {
if (Far::StencilTables const *varyingStencilsWithEndCap = if (Far::StencilTable const *varyingStencilsWithEndCap =
Far::StencilTablesFactory::AppendEndCapStencilTables( Far::StencilTableFactory::AppendEndCapStencilTable(
*_refiner, *_refiner,
varyingStencils, varyingStencils,
_farPatchTables->GetEndCapVaryingStencilTables())) { _farPatchTable->GetEndCapVaryingStencilTable())) {
delete varyingStencils; delete varyingStencils;
varyingStencils = varyingStencilsWithEndCap; varyingStencils = varyingStencilsWithEndCap;
} }
} }
} }
_maxValence = _farPatchTables->GetMaxValence(); _maxValence = _farPatchTable->GetMaxValence();
_patchTable = PatchTable::Create(_farPatchTables, _deviceContext); _patchTable = PatchTable::Create(_farPatchTable, _deviceContext);
// numvertices = coarse verts + refined verts + gregory basis verts // numvertices = coarse verts + refined verts + gregory basis verts
_numVertices = vertexStencils->GetNumControlVertices() _numVertices = vertexStencils->GetNumControlVertices()
+ vertexStencils->GetNumStencils(); + vertexStencils->GetNumStencils();
// convert to device stenciltables if necessary. // convert to device stenciltable if necessary.
_vertexStencilTables = _vertexStencilTable =
convertToCompatibleStencilTables<StencilTables>( convertToCompatibleStencilTable<StencilTable>(
vertexStencils, _deviceContext); vertexStencils, _deviceContext);
_varyingStencilTables = _varyingStencilTable =
convertToCompatibleStencilTables<StencilTables>( convertToCompatibleStencilTable<StencilTable>(
varyingStencils, _deviceContext); varyingStencils, _deviceContext);
// FIXME: we do extra copyings for Far::Stencils. // FIXME: we do extra copyings for Far::Stencils.
@ -510,7 +510,7 @@ private:
} }
Far::TopologyRefiner * _refiner; Far::TopologyRefiner * _refiner;
Far::PatchTables * _farPatchTables; Far::PatchTable * _farPatchTable;
int _numVertices; int _numVertices;
int _maxValence; int _maxValence;
@ -521,8 +521,8 @@ private:
VertexBufferDescriptor _vertexDesc; VertexBufferDescriptor _vertexDesc;
VertexBufferDescriptor _varyingDesc; VertexBufferDescriptor _varyingDesc;
StencilTables const * _vertexStencilTables; StencilTable const * _vertexStencilTable;
StencilTables const * _varyingStencilTables; StencilTable const * _varyingStencilTable;
EvaluatorCache * _evaluatorCache; EvaluatorCache * _evaluatorCache;
PatchTable *_patchTable; PatchTable *_patchTable;

View File

@ -40,15 +40,7 @@
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
// Forward declaration of friend classes:
namespace Far {
class TopologyRefiner;
class PatchTablesFactory;
}
namespace Vtr { namespace Vtr {
class Refinement;
class FVarRefinement;
}
// //
// FVarLevel: // FVarLevel:
@ -82,17 +74,8 @@ namespace Vtr {
// Everything is being declared public for now to facilitate access until its // Everything is being declared public for now to facilitate access until its
// clearer how this functionality will be provided. // clearer how this functionality will be provided.
// //
namespace Vtr {
class FVarLevel { class FVarLevel {
protected: public:
friend class Level;
friend class Refinement;
friend class FVarRefinement;
friend class Far::TopologyRefiner;
friend class Far::PatchTablesFactory;
protected:
// //
// Component tags -- trying to minimize the types needed here: // Component tags -- trying to minimize the types needed here:
// //
@ -171,7 +154,7 @@ protected:
typedef ConstLocalIndexArray ConstSiblingArray; typedef ConstLocalIndexArray ConstSiblingArray;
typedef LocalIndexArray SiblingArray; typedef LocalIndexArray SiblingArray;
protected: public:
FVarLevel(Level const& level); FVarLevel(Level const& level);
~FVarLevel(); ~FVarLevel();
@ -250,7 +233,8 @@ protected:
void print() const; void print() const;
void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector<Sibling>& fvSiblings) const; void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector<Sibling>& fvSiblings) const;
protected: // Members temporarily public pending re-assessment of friends:
public:
Level const & _level; Level const & _level;
// Linear interpolation options vary between channels: // Linear interpolation options vary between channels:

View File

@ -40,12 +40,7 @@
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
// namespace Vtr {
// Forward declaration of friend classes:
//
namespace Far {
class TopologyRefiner;
}
// //
// FVarRefinement: // FVarRefinement:
@ -60,14 +55,8 @@ namespace Far {
// the refinement between Levels serves most purposes and all that is required // 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. // in addition is a mapping from values in the child FVarLevel to the parent.
// //
namespace Vtr {
class FVarRefinement { class FVarRefinement {
protected: public:
friend class Refinement;
friend class Far::TopologyRefiner;
protected:
FVarRefinement(Refinement const& refinement, FVarLevel& parent, FVarLevel& child); FVarRefinement(Refinement const& refinement, FVarLevel& parent, FVarLevel& child);
~FVarRefinement(); ~FVarRefinement();
@ -96,7 +85,8 @@ protected:
void propagateValueCreases(); void propagateValueCreases();
void reclassifySemisharpValues(); void reclassifySemisharpValues();
protected: // Members temporarily public pending re-assessment of friends:
public:
// //
// Identify the Refinement, its Levels and assigned FVarLevels for more // Identify the Refinement, its Levels and assigned FVarLevels for more
// immediate access -- child FVarLevel is non-const as it is to be assigned: // immediate access -- child FVarLevel is non-const as it is to be assigned:

View File

@ -40,20 +40,9 @@
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
// Forward declarations for friends:
namespace Far {
template <class MESH> class TopologyRefinerFactory;
class TopologyRefinerFactoryBase;
class TopologyRefiner;
class PatchTablesFactory;
}
namespace Vtr { namespace Vtr {
class Refinement; class Refinement;
class QuadRefinement;
class TriRefinement;
class FVarRefinement;
class FVarLevel; class FVarLevel;
// //
@ -63,13 +52,12 @@ class FVarLevel;
// level can be used as the base level of another subdivision hierarchy and can // 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 // be considered a complete mesh independent of its ancestors. It currently
// does contain a "depth" member -- as some inferences can then be made about // 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 // the topology (i.e. all quads or all tris if not level 0).
// under consideration (e.g. a "regular" flag would serve the same purpose, and
// level 0 may even be regular).
// //
// This class is intended for private use within the library. So really its // This class is intended for private use within the library. There are still
// interface should be fully protected and only those library classes that need // opportunities to specialize levels -- e.g. those supporing N-sided faces vs
// it will be declared as friends, e.g. Refinement. // 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 // 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 // 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 Far layer essentially store 5 of these 6 in a permuted form -- we add
// the face-edges here to simplify refinement. // 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 { class Level {
@ -262,7 +218,7 @@ public:
public: public:
// Debugging aides -- unclear what will persist... // Debugging aides:
enum TopologyError { enum TopologyError {
TOPOLOGY_MISSING_EDGE_FACES=0, TOPOLOGY_MISSING_EDGE_FACES=0,
TOPOLOGY_MISSING_EDGE_VERTS, TOPOLOGY_MISSING_EDGE_VERTS,
@ -295,8 +251,7 @@ public:
void print(const Refinement* parentRefinement = 0) const; void print(const Refinement* parentRefinement = 0) const;
public: public:
// High-level topology queries -- these are likely to be moved elsewhere, but here // High-level topology queries -- these may be moved elsewhere:
// is the best place for them for now...
bool isSingleCreasePatch(Index face, float* sharpnessOut=NULL, int* rotationOut=NULL) const; 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 gatherTriRegularCornerVertexPatchPoints( Index fIndex, Index patchVerts[], int cornerVertInFace) const;
int gatherTriRegularCornerEdgePatchPoints( Index fIndex, Index patchVerts[], int cornerEdgeInFace) const; int gatherTriRegularCornerEdgePatchPoints( Index fIndex, Index patchVerts[], int cornerEdgeInFace) const;
protected: public:
friend class Refinement;
friend class QuadRefinement;
friend class TriRefinement;
friend class FVarRefinement;
friend class FVarLevel;
template <class MESH> friend class Far::TopologyRefinerFactory;
friend class Far::TopologyRefinerFactoryBase;
friend class Far::TopologyRefiner;
friend class Far::PatchTablesFactory;
// Sizing methods used to construct a level to populate: // Sizing methods used to construct a level to populate:
void resizeFaces( int numFaces); void resizeFaces( int numFaces);
void resizeFaceVertices(int numFaceVertsTotal); void resizeFaceVertices(int numFaceVertsTotal);
@ -418,13 +361,14 @@ protected:
void resizeVertexEdges(Index vertIndex, int count); void resizeVertexEdges(Index vertIndex, int count);
void trimVertexEdges( 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, // Initial plans were to have a few specific classes properly construct the
// e.g. the Refinement class. There is now clearly a need to have some class // topology from scratch, e.g. the Refinement class and a Factory class for
// construct full topology given only a simple face-vertex list. That can be done // the base level, by populating all topological relations. The need to have
// externally (either a Factory outside Vtr or another Vtr construction helper), but // a class construct full topology given only a simple face-vertex list, made
// until we decide where, the required implementation is defined here. // it necessary to write code to define and orient all relations -- and most
// of that seemed best placed here.
// //
bool completeTopologyFromFaceVertices(); bool completeTopologyFromFaceVertices();
Index findEdge(Index v0, Index v1, ConstIndexArray v0Edges) const; Index findEdge(Index v0, Index v1, ConstIndexArray v0Edges) const;
@ -437,7 +381,8 @@ protected:
IndexArray shareFaceVertCountsAndOffsets() const; 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 // 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 // affected by them in its construction, they are not associated with it -- a Level

View File

@ -39,14 +39,8 @@
namespace OpenSubdiv { namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION { namespace OPENSUBDIV_VERSION {
namespace Far {
class TopologyRefiner;
class PatchTablesFactory;
}
namespace Vtr { namespace Vtr {
class SparseSelector;
class FVarRefinement; class FVarRefinement;
// //
@ -60,7 +54,7 @@ class FVarRefinement;
// of topological splits that the supported subdivisions schemes collectively require, i.e. those // 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 // 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 // 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. // 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 // 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]; } Index getChildFaceBaseFace(Index f) const { return _childFaceBaseFaceIndex[f]; }
// //
// Non-public methods: // Modifiers intended for internal/protected use:
// //
protected: public:
friend class FVarRefinement;
friend class SparseSelector;
friend class Far::TopologyRefiner;
friend class Far::PatchTablesFactory;
IndexArray getFaceChildFaces(Index parentFace); IndexArray getFaceChildFaces(Index parentFace);
IndexArray getFaceChildEdges(Index parentFace); IndexArray getFaceChildEdges(Index parentFace);
IndexArray getEdgeChildEdges(Index parentEdge); IndexArray getEdgeChildEdges(Index parentEdge);
protected: public:
// //
// Tags have now been added per-component in Level, but there is additional need to tag // 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 // 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 unsigned char _indexInParent : 2; // index of child wrt parent: 0-3, or iterative if N > 4
}; };
// // Remaining methods should really be protected -- for use by subclasses...
// Remaining methods should remain protected -- for use by subclasses... public:
//
protected:
// //
// Methods involved in constructing the parent-to-child mapping -- when the // Methods involved in constructing the parent-to-child mapping -- when the
// refinement is sparse, additional methods are needed to identify the selection: // refinement is sparse, additional methods are needed to identify the selection:
@ -309,12 +294,12 @@ protected:
// //
void subdivideFVarChannels(); 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 // 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... // 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: // Defined on construction:
Level const * _parent; Level const * _parent;

View File

@ -70,10 +70,11 @@ GetReorderedHbrVertexData(
{ // Populate base level { // Populate base level
// note : topological ordering is identical between Hbr and Vtr // note : topological ordering is identical between Hbr and Vtr
// for the base level // for the base level
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
int nfaces = refiner.GetNumFaces(0), int nfaces = refBaseLevel.GetNumFaces(),
nedges = refiner.GetNumEdges(0), nedges = refBaseLevel.GetNumEdges(),
nverts = refiner.GetNumVertices(0); nverts = refBaseLevel.GetNumVertices();
maps[0].faces.resize(nfaces, 0); maps[0].faces.resize(nfaces, 0);
maps[0].edges.resize(nedges, 0); maps[0].edges.resize(nedges, 0);
@ -85,7 +86,7 @@ GetReorderedHbrVertexData(
for (int edge = 0; edge <nedges; ++edge) { for (int edge = 0; edge <nedges; ++edge) {
ConstIndexArray vtrVerts = refiner.GetEdgeVertices(0, edge); ConstIndexArray vtrVerts = refBaseLevel.GetEdgeVertices(edge);
Hvertex const * v0 = hmesh.GetVertex(vtrVerts[0]), Hvertex const * v0 = hmesh.GetVertex(vtrVerts[0]),
* v1 = hmesh.GetVertex(vtrVerts[1]); * v1 = hmesh.GetVertex(vtrVerts[1]);
@ -110,16 +111,19 @@ GetReorderedHbrVertexData(
LevelMap & previous = maps[level-1], LevelMap & previous = maps[level-1],
& current = maps[level]; & current = maps[level];
current.faces.resize(refiner.GetNumFaces(level), 0); OpenSubdiv::Far::TopologyLevel const & refLevel = refiner.GetLevel(level);
current.edges.resize(refiner.GetNumEdges(level), 0); OpenSubdiv::Far::TopologyLevel const & refPrevLevel = refiner.GetLevel(level-1);
current.verts.resize(refiner.GetNumVertices(level), 0);
for (int face=0; face < refiner.GetNumFaces(level-1); ++face) { current.faces.resize(refLevel.GetNumFaces(), 0);
current.edges.resize(refLevel.GetNumEdges(), 0);
current.verts.resize(refLevel.GetNumVertices(), 0);
for (int face=0; face < refPrevLevel.GetNumFaces(); ++face) {
// populate child faces // populate child faces
Hface * f = previous.faces[face]; Hface * f = previous.faces[face];
ConstIndexArray childFaces = refiner.GetFaceChildFaces(level-1, face); ConstIndexArray childFaces = refPrevLevel.GetFaceChildFaces(face);
for (int i=0; i<childFaces.size(); ++i) { for (int i=0; i<childFaces.size(); ++i) {
current.faces[childFaces[i]] = f->GetChild(i); current.faces[childFaces[i]] = f->GetChild(i);
} }
@ -127,33 +131,33 @@ GetReorderedHbrVertexData(
// populate child face-verts -- when present (none for Loop subdivision) // populate child face-verts -- when present (none for Loop subdivision)
if (!schemeIsLoop) { if (!schemeIsLoop) {
Hvertex * v = f->Subdivide(); Hvertex * v = f->Subdivide();
Index childVert = refiner.GetFaceChildVertex(level-1, face); Index childVert = refPrevLevel.GetFaceChildVertex(face);
assert(v->GetParentFace()); assert(v->GetParentFace());
current.verts[childVert] = v; 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 // populate child edge-verts
Index childVert = refiner.GetEdgeChildVertex(level-1,edge); Index childVert = refPrevLevel.GetEdgeChildVertex(edge);
Hhalfedge * e = previous.edges[edge]; Hhalfedge * e = previous.edges[edge];
Hvertex * v = e->Subdivide(); Hvertex * v = e->Subdivide();
assert(v->GetParentEdge()); assert(v->GetParentEdge());
current.verts[childVert] = v; 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 // populate child vert-verts
Index childVert = refiner.GetVertexChildVertex(level-1, vert); Index childVert = refPrevLevel.GetVertexChildVertex(vert);
Hvertex * v = previous.verts[vert]->Subdivide(); Hvertex * v = previous.verts[vert]->Subdivide();
current.verts[childVert] = v; current.verts[childVert] = v;
assert(v->GetParentVertex()); assert(v->GetParentVertex());
} }
// populate child edges // 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]], Hvertex const * v0 = current.verts[vtrVerts[0]],
* v1 = current.verts[vtrVerts[1]]; * v1 = current.verts[vtrVerts[1]];
@ -166,7 +170,7 @@ GetReorderedHbrVertexData(
assert(e); assert(e);
current.edges[edge] = e; current.edges[edge] = e;
} }
ecount += refiner.GetNumEdges(level-1); ecount += refPrevLevel.GetNumEdges();
} }
} }
}; };

View File

@ -46,7 +46,7 @@ InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner,
fvarWidth = 2; fvarWidth = 2;
int numValuesTotal = refiner.GetNumFVarValuesTotal(channel), int numValuesTotal = refiner.GetNumFVarValuesTotal(channel),
numValues0 = refiner.GetNumFVarValues(0, channel); numValues0 = refiner.GetLevel(0).GetNumFVarValues(channel);
if (shape.uvs.empty() or numValuesTotal<=0) { if (shape.uvs.empty() or numValuesTotal<=0) {
return; return;
@ -57,7 +57,7 @@ InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner,
std::vector<FVarVertex> buffer(numValuesTotal); std::vector<FVarVertex> buffer(numValuesTotal);
int maxlevel = refiner.GetMaxLevel(), 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)); memcpy(&buffer[0], &shape.uvs[0], shape.uvs.size()*sizeof(float));

View File

@ -155,14 +155,14 @@ InterpolateVtrVertexData(const char *shapeStr, Scheme scheme, int maxlevel,
// populate coarse mesh positions // populate coarse mesh positions
data.resize(refiner->GetNumVerticesTotal()); data.resize(refiner->GetNumVerticesTotal());
for (int i=0; i<refiner->GetNumVertices(0); i++) { for (int i=0; i<refiner->GetLevel(0).GetNumVertices(); i++) {
data[i].SetPosition(shape->verts[i*3+0], data[i].SetPosition(shape->verts[i*3+0],
shape->verts[i*3+1], shape->verts[i*3+1],
shape->verts[i*3+2]); shape->verts[i*3+2]);
} }
T * verts = &data[0]; T * verts = &data[0];
refiner->Interpolate(verts, verts+refiner->GetNumVertices(0)); refiner->Interpolate(verts, verts+refiner->GetLevel(0).GetNumVertices());
delete shape; delete shape;
return refiner; return refiner;
@ -204,7 +204,7 @@ TopologyRefinerFactory<Shape>::assignComponentTopology(
Far::TopologyRefiner & refiner, Shape const & shape) { Far::TopologyRefiner & refiner, Shape const & shape) {
{ // Face relations: { // Face relations:
int nfaces = refiner.GetNumFaces(0); int nfaces = refiner.GetLevel(0).GetNumFaces();
for (int i=0, ofs=0; i < nfaces; ++i) { for (int i=0, ofs=0; i < nfaces; ++i) {
@ -235,7 +235,7 @@ TopologyRefinerFactory<Shape>::assignFaceVaryingTopology(
// UV layyout (we only parse 1 channel) // UV layyout (we only parse 1 channel)
if (not shape.faceuvs.empty()) { if (not shape.faceuvs.empty()) {
int nfaces = refiner.GetNumFaces(0), int nfaces = refiner.GetLevel(0).GetNumFaces(),
channel = refiner.createBaseFVarChannel( (int)shape.uvs.size()/2 ); channel = refiner.createBaseFVarChannel( (int)shape.uvs.size()/2 );
for (int i=0, ofs=0; i < nfaces; ++i) { for (int i=0, ofs=0; i < nfaces; ++i) {
@ -273,7 +273,7 @@ TopologyRefinerFactory<Shape>::assignComponentTags(
for (int j=0; j<(int)t->intargs.size()-1; j += 2) { 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) { if (edge==OpenSubdiv::Vtr::INDEX_INVALID) {
printf("cannot find edge for crease tag (%d,%d)\n", t->intargs[j], t->intargs[j+1] ); printf("cannot find edge for crease tag (%d,%d)\n", t->intargs[j], t->intargs[j+1] );
return false; return false;
@ -287,7 +287,7 @@ TopologyRefinerFactory<Shape>::assignComponentTags(
for (int j=0; j<(int)t->intargs.size(); ++j) { for (int j=0; j<(int)t->intargs.size(); ++j) {
int vertex = t->intargs[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 ); printf("cannot find vertex for corner tag (%d)\n", vertex );
return false; return false;
} else { } else {

View File

@ -52,7 +52,7 @@ GLFWwindow* g_window=0;
#include <osd/cpuGLVertexBuffer.h> #include <osd/cpuGLVertexBuffer.h>
#include <far/stencilTablesFactory.h> #include <far/stencilTableFactory.h>
#include "../../regression/common/cmp_utils.h" #include "../../regression/common/cmp_utils.h"
#include "../../regression/common/hbr_utils.h" #include "../../regression/common/hbr_utils.h"
@ -246,19 +246,19 @@ checkVertexBuffer(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void static void
buildStencilTables( buildStencilTable(
const FarTopologyRefiner &refiner, const FarTopologyRefiner &refiner,
Far::StencilTables const **vertexStencils, Far::StencilTable const **vertexStencils,
Far::StencilTables const **varyingStencils) Far::StencilTable const **varyingStencils)
{ {
Far::StencilTablesFactory::Options soptions; Far::StencilTableFactory::Options soptions;
soptions.generateOffsets = true; soptions.generateOffsets = true;
soptions.generateIntermediateLevels = true; soptions.generateIntermediateLevels = true;
*vertexStencils = Far::StencilTablesFactory::Create(refiner, soptions); *vertexStencils = Far::StencilTableFactory::Create(refiner, soptions);
soptions.interpolationMode = Far::StencilTablesFactory::INTERPOLATE_VARYING; soptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_VARYING;
*varyingStencils = Far::StencilTablesFactory::Create(refiner, soptions); *varyingStencils = Far::StencilTableFactory::Create(refiner, soptions);
} }
@ -269,9 +269,9 @@ checkMeshCPU( FarTopologyRefiner *refiner,
const std::vector<xyzVV>& coarseverts, const std::vector<xyzVV>& coarseverts,
xyzmesh * refmesh) { xyzmesh * refmesh) {
Far::StencilTables const *vertexStencils; Far::StencilTable const *vertexStencils;
Far::StencilTables const *varyingStencils; Far::StencilTable const *varyingStencils;
buildStencilTables(*refiner, &vertexStencils, &varyingStencils); buildStencilTable(*refiner, &vertexStencils, &varyingStencils);
assert(coarseverts.size() == (size_t)refiner->GetNumVerticesTotal()); assert(coarseverts.size() == (size_t)refiner->GetNumVerticesTotal());
@ -284,7 +284,7 @@ checkMeshCPU( FarTopologyRefiner *refiner,
vb, vb,
Osd::VertexBufferDescriptor(0, 3, 3), Osd::VertexBufferDescriptor(0, 3, 3),
vb, vb,
Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3), Osd::VertexBufferDescriptor(refiner->GetLevel(0).GetNumVertices()*3, 3, 3),
vertexStencils); vertexStencils);
int result = checkVertexBuffer(*refiner, refmesh, vb->BindCpuBuffer(), int result = checkVertexBuffer(*refiner, refmesh, vb->BindCpuBuffer(),
@ -303,9 +303,9 @@ checkMeshCPUGL(FarTopologyRefiner *refiner,
const std::vector<xyzVV>& coarseverts, const std::vector<xyzVV>& coarseverts,
xyzmesh * refmesh) { xyzmesh * refmesh) {
Far::StencilTables const *vertexStencils; Far::StencilTable const *vertexStencils;
Far::StencilTables const *varyingStencils; Far::StencilTable const *varyingStencils;
buildStencilTables(*refiner, &vertexStencils, &varyingStencils); buildStencilTable(*refiner, &vertexStencils, &varyingStencils);
Osd::CpuGLVertexBuffer *vb = Osd::CpuGLVertexBuffer::Create(3, Osd::CpuGLVertexBuffer *vb = Osd::CpuGLVertexBuffer::Create(3,
refiner->GetNumVerticesTotal()); refiner->GetNumVerticesTotal());
@ -316,7 +316,7 @@ checkMeshCPUGL(FarTopologyRefiner *refiner,
vb, vb,
Osd::VertexBufferDescriptor(0, 3, 3), Osd::VertexBufferDescriptor(0, 3, 3),
vb, vb,
Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3), Osd::VertexBufferDescriptor(refiner->GetLevel(0).GetNumVertices()*3, 3, 3),
vertexStencils); vertexStencils);
int result = checkVertexBuffer(*refiner, refmesh, int result = checkVertexBuffer(*refiner, refmesh,

View File

@ -149,23 +149,25 @@ int main(int, char **) {
{ // Output OBJ of the highest level refined ----------- { // Output OBJ of the highest level refined -----------
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
// Print vertex positions // Print vertex positions
for (int level=0, firstVert=0; level<=maxlevel; ++level) { for (int level=0, firstVert=0; level<=maxlevel; ++level) {
if (level==maxlevel) { if (level==maxlevel) {
for (int vert=0; vert<refiner->GetNumVertices(maxlevel); ++vert) { for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
float const * pos = verts[firstVert+vert].GetPosition(); float const * pos = verts[firstVert+vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]); printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
} }
} else { } else {
firstVert += refiner->GetNumVertices(level); firstVert += refiner->GetLevel(level).GetNumVertices();
} }
} }
// Print faces // Print faces
for (int face=0; face<refiner->GetNumFaces(maxlevel); ++face) { for (int face=0; face<refLastLevel.GetNumFaces(); ++face) {
Far::ConstIndexArray fverts = refiner->GetFaceVertices(maxlevel, face); Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face);
// all refined Catmark faces should be quads // all refined Catmark faces should be quads
assert(fverts.size()==4); assert(fverts.size()==4);

View File

@ -454,23 +454,25 @@ int main(int, char **) {
{ // Output OBJ of the highest level refined ----------- { // Output OBJ of the highest level refined -----------
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
// Print vertex positions // Print vertex positions
for (int level=0, firstVert=0; level<=maxlevel; ++level) { for (int level=0, firstVert=0; level<=maxlevel; ++level) {
if (level==maxlevel) { if (level==maxlevel) {
for (int vert=0; vert<refiner->GetNumVertices(maxlevel); ++vert) { for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
float const * pos = verts[firstVert+vert].GetPosition(); float const * pos = verts[firstVert+vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]); printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
} }
} else { } else {
firstVert += refiner->GetNumVertices(level); firstVert += refiner->GetLevel(level).GetNumVertices();
} }
} }
// Print faces // Print faces
for (int face=0; face<refiner->GetNumFaces(maxlevel); ++face) { for (int face=0; face<refLastLevel.GetNumFaces(); ++face) {
Far::ConstIndexArray fverts = refiner->GetFaceVertices(maxlevel, face); Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face);
// all refined Catmark faces should be quads // all refined Catmark faces should be quads
assert(fverts.size()==4); assert(fverts.size()==4);

View File

@ -339,7 +339,7 @@ FarTopologyRefinerFactory<OsdHbrConverter>::assignComponentTopology(
OsdHbrConverter::EdgeMap & edges = const_cast<OsdHbrConverter &>(conv).GetEdges(); OsdHbrConverter::EdgeMap & edges = const_cast<OsdHbrConverter &>(conv).GetEdges();
{ // Face relations: { // Face relations:
int nfaces = refiner.GetNumFaces(/*level*/0); int nfaces = refiner.GetLevel(0).GetNumFaces();
for (int i=0; i < nfaces; ++i) { for (int i=0; i < nfaces; ++i) {
IndexArray dstFaceVerts = refiner.setBaseFaceVertices(i); IndexArray dstFaceVerts = refiner.setBaseFaceVertices(i);
@ -377,7 +377,7 @@ FarTopologyRefinerFactory<OsdHbrConverter>::assignComponentTopology(
} }
{ // Vert relations { // Vert relations
for (int i=0; i<refiner.GetNumVertices(/*level*/0); ++i) { for (int i=0; i<refiner.GetLevel(0).GetNumVertices(); ++i) {
OsdHbrVertex const * v = hmesh.GetVertex(i); OsdHbrVertex const * v = hmesh.GetVertex(i);
@ -451,7 +451,7 @@ FarTopologyRefinerFactory<OsdHbrConverter>::assignComponentTags(
} }
// Initialize vertex sharpness // Initialize vertex sharpness
for (int i=0; i<refiner.GetNumVertices(/*level*/0); ++i) { for (int i=0; i<refiner.GetLevel(0).GetNumVertices(); ++i) {
refiner.setBaseVertexSharpness(i, hmesh.GetVertex(i)->GetSharpness()); refiner.setBaseVertexSharpness(i, hmesh.GetVertex(i)->GetSharpness());
} }

View File

@ -166,11 +166,11 @@ int main(int, char **) {
// particles at the location of the refined vertices (don't forget to // particles at the location of the refined vertices (don't forget to
// turn shading on in the viewport to see the colors) // 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 // Position the 'verts' pointer to the first vertex of our 'maxlevel' level
for (int level=0; level<maxlevel; ++level) { for (int level=0; level<maxlevel; ++level) {
verts += refiner->GetNumVertices(level); verts += refiner->GetLevel(level).GetNumVertices();
} }
// Output particle positions // Output particle positions

View File

@ -214,7 +214,7 @@ int main(int, char **) {
// Allocate & interpolate the 'face-varying' primvar data // Allocate & interpolate the 'face-varying' primvar data
int channel = 0, int channel = 0,
nCoarseFVVerts = refiner->GetNumFVarValues(0, channel); nCoarseFVVerts = refiner->GetLevel(0).GetNumFVarValues(channel);
std::vector<FVarVertex> fvBuffer(refiner->GetNumFVarValuesTotal(channel)); std::vector<FVarVertex> fvBuffer(refiner->GetNumFVarValuesTotal(channel));
FVarVertex * fvVerts = &fvBuffer[0]; FVarVertex * fvVerts = &fvBuffer[0];
@ -229,16 +229,18 @@ int main(int, char **) {
{ // Output OBJ of the highest level refined ----------- { // Output OBJ of the highest level refined -----------
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
// Print vertex positions // Print vertex positions
for (int level=0, firstVert=0; level<=maxlevel; ++level) { for (int level=0, firstVert=0; level<=maxlevel; ++level) {
if (level==maxlevel) { if (level==maxlevel) {
for (int vert=0; vert<refiner->GetNumVertices(level); ++vert) { for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
float const * pos = verts[firstVert+vert].GetPosition(); float const * pos = verts[firstVert+vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]); printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
} }
} else { } else {
firstVert += refiner->GetNumVertices(level); firstVert += refiner->GetLevel(level).GetNumVertices();
} }
} }
@ -246,21 +248,21 @@ int main(int, char **) {
for (int level=0, firstVert=0; level<=maxlevel; ++level) { for (int level=0, firstVert=0; level<=maxlevel; ++level) {
if (level==maxlevel) { if (level==maxlevel) {
for (int vert=0; vert<refiner->GetNumFVarValues(level, channel); ++vert) { for (int vert=0; vert<refLastLevel.GetNumFVarValues(channel); ++vert) {
FVarVertex const & uv = fvVerts[firstVert+vert]; FVarVertex const & uv = fvVerts[firstVert+vert];
printf("vt %f %f\n", uv.u, uv.v); printf("vt %f %f\n", uv.u, uv.v);
} }
} else { } else {
firstVert += refiner->GetNumFVarValues(level, channel); firstVert += refiner->GetLevel(level).GetNumFVarValues(channel);
} }
} }
// Print faces // Print faces
for (int face=0; face<refiner->GetNumFaces(maxlevel); ++face) { for (int face=0; face<refLastLevel.GetNumFaces(); ++face) {
Far::ConstIndexArray fverts = refiner->GetFaceVertices(maxlevel, face), Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face),
fvverts = refiner->GetFVarFaceValues(maxlevel, face, channel); fvverts = refLastLevel.GetFVarFaceValues(face, channel);
// all refined Catmark faces should be quads // all refined Catmark faces should be quads
assert(fverts.size()==4 and fvverts.size()==4); assert(fverts.size()==4 and fvverts.size()==4);

View File

@ -26,13 +26,13 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Tutorial description: // 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. // factorized stencils to interpolate vertex primvar data buffers.
// //
#include <opensubdiv/far/topologyRefinerFactory.h> #include <opensubdiv/far/topologyRefinerFactory.h>
#include <opensubdiv/far/stencilTables.h> #include <opensubdiv/far/stencilTable.h>
#include <opensubdiv/far/stencilTablesFactory.h> #include <opensubdiv/far/stencilTableFactory.h>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
@ -118,17 +118,17 @@ int main(int, char **) {
refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel)); 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. // note: we only want stencils for the highest refinement level.
Far::StencilTablesFactory::Options options; Far::StencilTableFactory::Options options;
options.generateIntermediateLevels=false; options.generateIntermediateLevels=false;
options.generateOffsets=true; options.generateOffsets=true;
Far::StencilTables const * stencilTables = Far::StencilTable const * stencilTable =
Far::StencilTablesFactory::Create(*refiner, options); Far::StencilTableFactory::Create(*refiner, options);
// Allocate vertex primvar buffer (1 stencil for each vertex) // Allocate vertex primvar buffer (1 stencil for each vertex)
int nstencils = stencilTables->GetNumStencils(); int nstencils = stencilTable->GetNumStencils();
std::vector<Vertex> vertexBuffer(nstencils); std::vector<Vertex> vertexBuffer(nstencils);
@ -141,7 +141,7 @@ int main(int, char **) {
// Apply stencils on the control vertex data to update the primvar data // Apply stencils on the control vertex data to update the primvar data
// of the refined vertices. // of the refined vertices.
stencilTables->UpdateValues(controlValues, &vertexBuffer[0]); stencilTable->UpdateValues(controlValues, &vertexBuffer[0]);
} }
{ // Visualization with Maya : print a MEL script that generates particles { // Visualization with Maya : print a MEL script that generates particles
@ -156,7 +156,7 @@ int main(int, char **) {
} }
delete refiner; delete refiner;
delete stencilTables; delete stencilTable;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -27,13 +27,13 @@
// Tutorial description: // Tutorial description:
// //
// This tutorial shows how to create and manipulate both 'vertex' and 'varying' // 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. // vertex colors.
// //
#include <opensubdiv/far/topologyRefinerFactory.h> #include <opensubdiv/far/topologyRefinerFactory.h>
#include <opensubdiv/far/stencilTables.h> #include <opensubdiv/far/stencilTable.h>
#include <opensubdiv/far/stencilTablesFactory.h> #include <opensubdiv/far/stencilTableFactory.h>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
@ -121,10 +121,10 @@ int main(int, char **) {
int maxlevel = 4; int maxlevel = 4;
refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel)); 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 // Use the Far::StencilTable factory to create discrete stencil table
Far::StencilTablesFactory::Options options; Far::StencilTableFactory::Options options;
options.generateIntermediateLevels=false; // only the highest refinement level. options.generateIntermediateLevels=false; // only the highest refinement level.
options.generateOffsets=true; options.generateOffsets=true;
@ -133,10 +133,10 @@ int main(int, char **) {
// //
// Create stencils table for 'vertex' interpolation // Create stencils table for 'vertex' interpolation
options.interpolationMode=Far::StencilTablesFactory::INTERPOLATE_VERTEX; options.interpolationMode=Far::StencilTableFactory::INTERPOLATE_VERTEX;
Far::StencilTables const * vertexStencils = Far::StencilTable const * vertexStencils =
Far::StencilTablesFactory::Create(*refiner, options); Far::StencilTableFactory::Create(*refiner, options);
assert(nverts==vertexStencils->GetNumStencils()); assert(nverts==vertexStencils->GetNumStencils());
// Allocate vertex primvar buffer (1 stencil for each vertex) // Allocate vertex primvar buffer (1 stencil for each vertex)
@ -150,10 +150,10 @@ int main(int, char **) {
// //
// Create stencils table for 'varying' interpolation // Create stencils table for 'varying' interpolation
options.interpolationMode=Far::StencilTablesFactory::INTERPOLATE_VARYING; options.interpolationMode=Far::StencilTableFactory::INTERPOLATE_VARYING;
Far::StencilTables const * varyingStencils = Far::StencilTable const * varyingStencils =
Far::StencilTablesFactory::Create(*refiner, options); Far::StencilTableFactory::Create(*refiner, options);
assert(nverts==varyingStencils->GetNumStencils()); assert(nverts==varyingStencils->GetNumStencils());
// Allocate varying primvar buffer (1 stencil for each vertex) // Allocate varying primvar buffer (1 stencil for each vertex)

View File

@ -41,7 +41,7 @@
// //
#include <opensubdiv/far/topologyRefinerFactory.h> #include <opensubdiv/far/topologyRefinerFactory.h>
#include <opensubdiv/far/patchTablesFactory.h> #include <opensubdiv/far/patchTableFactory.h>
#include <opensubdiv/far/endCapGregoryBasisPatchFactory.h> #include <opensubdiv/far/endCapGregoryBasisPatchFactory.h>
#include <opensubdiv/far/patchMap.h> #include <opensubdiv/far/patchMap.h>
#include <opensubdiv/far/ptexIndices.h> #include <opensubdiv/far/ptexIndices.h>
@ -155,14 +155,14 @@ int main(int, char **) {
refiner->Interpolate(&verts[0], &verts[g_nverts]); 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 // surface limit
Far::EndCapGregoryBasisPatchFactory endcapFactory(*refiner); Far::EndCapGregoryBasisPatchFactory endcapFactory(*refiner);
Far::PatchTables const * patchTables = Far::PatchTable const * patchTable =
Far::PatchTablesFactory::Create(*refiner, Far::PatchTablesFactory::Options()); Far::PatchTableFactory::Create(*refiner, Far::PatchTableFactory::Options());
// Create a Far::PatchMap to help locating patches in the table // 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. // Create a Far::PtexIndices to help find indices of ptex faces.
Far::PtexIndices ptexIndices(*refiner); Far::PtexIndices ptexIndices(*refiner);
@ -185,14 +185,14 @@ int main(int, char **) {
t = (float)rand()/(float)RAND_MAX; t = (float)rand()/(float)RAND_MAX;
// Locate the patch corresponding to the face ptex idx and (s,t) // 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); patchmap.FindPatch(face, s, t);
assert(handle); assert(handle);
// Evaluate the patch weights, identify the CVs and compute the limit frame: // 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]; LimitFrame & dst = samples[count];
dst.Clear(); dst.Clear();

View File

@ -26,12 +26,12 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Tutorial description: // 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 // We initalize a Far::TopologyRefiner initalized with a cube and apply uniform
// refinement. We then use a Far::StencilTablesFactory to generate stencil // refinement. We then use a Far::StencilTableFactory to generate a stencil
// tables. We set the factory Options to not factorize intermediate levels, // table. We set the factory Options to not factorize intermediate levels,
// thus giving tables of "cascading" stencils. // thus giving a table of "cascading" stencils.
// //
// We then apply the stencils to the vertex position primvar data, and insert // 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 // a hierarchical edit at level 1. This edit is smoothed by the application
@ -42,8 +42,8 @@
// //
#include <opensubdiv/far/topologyRefinerFactory.h> #include <opensubdiv/far/topologyRefinerFactory.h>
#include <opensubdiv/far/stencilTables.h> #include <opensubdiv/far/stencilTable.h>
#include <opensubdiv/far/stencilTablesFactory.h> #include <opensubdiv/far/stencilTableFactory.h>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
@ -131,17 +131,17 @@ int main(int, char **) {
int maxlevel = 4; int maxlevel = 4;
refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel)); 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 // note: we want stencils for the each refinement level
// "cascade" mode is achieved by setting "factorizeIntermediateLevels" // "cascade" mode is achieved by setting "factorizeIntermediateLevels"
// to false // to false
Far::StencilTablesFactory::Options options; Far::StencilTableFactory::Options options;
options.generateIntermediateLevels=true; options.generateIntermediateLevels=true;
options.factorizeIntermediateLevels=false; options.factorizeIntermediateLevels=false;
options.generateOffsets=true; options.generateOffsets=true;
Far::StencilTables const * stencilTables = Far::StencilTable const * stencilTable =
Far::StencilTablesFactory::Create(*refiner, options); Far::StencilTableFactory::Create(*refiner, options);
std::vector<Vertex> vertexBuffer(refiner->GetNumVerticesTotal()-g_nverts); std::vector<Vertex> 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 int start = 0, end = 0; // stencils batches for each level of subdivision
for (int level=0; level<maxlevel; ++level) { for (int level=0; level<maxlevel; ++level) {
int nverts = refiner->GetNumVertices(level+1); int nverts = refiner->GetLevel(level+1).GetNumVertices();
Vertex const * srcVerts = reinterpret_cast<Vertex *>(g_verts); Vertex const * srcVerts = reinterpret_cast<Vertex *>(g_verts);
if (level>0) { if (level>0) {
@ -160,7 +160,7 @@ int main(int, char **) {
start = end; start = end;
end += nverts; end += nverts;
stencilTables->UpdateValues(srcVerts, destVerts, start, end); stencilTable->UpdateValues(srcVerts, destVerts, start, end);
// apply 2 hierarchical edits on level 1 vertices // apply 2 hierarchical edits on level 1 vertices
if (level==1) { if (level==1) {
@ -180,9 +180,11 @@ int main(int, char **) {
// Print vertex positions // Print vertex positions
for (int level=1, firstvert=0; level<=maxlevel; ++level) { for (int level=1, firstvert=0; level<=maxlevel; ++level) {
Far::TopologyLevel const & refLevel = refiner->GetLevel(level);
printf("g level_%d\n", level); printf("g level_%d\n", level);
int nverts = refiner->GetNumVertices(level); int nverts = refLevel.GetNumVertices();
for (int vert=0; vert<nverts; ++vert) { for (int vert=0; vert<nverts; ++vert) {
float const * pos = verts[vert].GetPosition(); float const * pos = verts[vert].GetPosition();
printf("v %f %f %f\n", pos[0], pos[1], pos[2]); printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
@ -190,9 +192,9 @@ int main(int, char **) {
verts += nverts; verts += nverts;
// Print faces // Print faces
for (int face=0; face<refiner->GetNumFaces(level); ++face) { for (int face=0; face<refLevel.GetNumFaces(); ++face) {
Far::ConstIndexArray fverts = refiner->GetFaceVertices(level, face); Far::ConstIndexArray fverts = refLevel.GetFaceVertices(face);
// all refined Catmark faces should be quads // all refined Catmark faces should be quads
assert(fverts.size()==4); assert(fverts.size()==4);
@ -208,7 +210,7 @@ int main(int, char **) {
} }
delete refiner; delete refiner;
delete stencilTables; delete stencilTable;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -31,7 +31,7 @@
// //
#include <opensubdiv/far/topologyRefinerFactory.h> #include <opensubdiv/far/topologyRefinerFactory.h>
#include <opensubdiv/far/stencilTablesFactory.h> #include <opensubdiv/far/stencilTableFactory.h>
#include <opensubdiv/osd/cpuEvaluator.h> #include <opensubdiv/osd/cpuEvaluator.h>
#include <opensubdiv/osd/cpuVertexBuffer.h> #include <opensubdiv/osd/cpuVertexBuffer.h>
@ -75,22 +75,22 @@ int main(int, char **) {
// //
// Setup phase // Setup phase
// //
Far::StencilTables const * stencilTables = NULL; Far::StencilTable const * stencilTable = NULL;
{ // Setup Context { // Setup Context
Far::TopologyRefiner const * refiner = createTopologyRefiner(maxlevel); 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 tutorials)
Far::StencilTablesFactory::Options options; Far::StencilTableFactory::Options options;
options.generateOffsets=true; options.generateOffsets=true;
options.generateIntermediateLevels=false; options.generateIntermediateLevels=false;
stencilTables = Far::StencilTablesFactory::Create(*refiner, options); stencilTable = Far::StencilTableFactory::Create(*refiner, options);
nCoarseVerts = refiner->GetNumVertices(0); nCoarseVerts = refiner->GetLevel(0).GetNumVertices();
nRefinedVerts = stencilTables->GetNumStencils(); nRefinedVerts = stencilTable->GetNumStencils();
// We are done with Far: cleanup tables // We are done with Far: cleanup table
delete refiner; delete refiner;
} }
@ -113,7 +113,7 @@ int main(int, char **) {
// Launch the computation // Launch the computation
Osd::CpuEvaluator::EvalStencils(vbuffer, srcDesc, Osd::CpuEvaluator::EvalStencils(vbuffer, srcDesc,
vbuffer, dstDesc, vbuffer, dstDesc,
stencilTables); stencilTable);
} }
{ // Visualization with Maya : print a MEL script that generates particles { // Visualization with Maya : print a MEL script that generates particles
@ -128,7 +128,7 @@ int main(int, char **) {
printf("-c 1;\n"); printf("-c 1;\n");
} }
delete stencilTables; delete stencilTable;
delete vbuffer; delete vbuffer;
} }