mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-15 00:11:07 +00:00
Merge branch 'upstream-dev' into dev
This commit is contained in:
commit
0a6a47159e
@ -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.
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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.
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -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**
|
||||||
|
@ -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);
|
||||||
|
@ -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>(
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -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];
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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 =
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
||||||
|
@ -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 ) );
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
@ -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 */
|
@ -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()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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 */
|
@ -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
|
|
453
opensubdiv/far/stencilBuilder.cpp
Normal file
453
opensubdiv/far/stencilBuilder.cpp
Normal 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
|
||||||
|
|
110
opensubdiv/far/stencilBuilder.h
Normal file
110
opensubdiv/far/stencilBuilder.h
Normal 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
|
@ -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
|
482
opensubdiv/far/stencilTableFactory.cpp
Normal file
482
opensubdiv/far/stencilTableFactory.cpp
Normal 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
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -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
|
|
@ -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:
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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];
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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*/) {
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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; }
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user