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
|
||||
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
|
||||
data, after it has been serialized and factorized. This representation is
|
||||
embodied in the `Far::PatchTables <#far-patchtables>`__ and the
|
||||
`Far::StencilTables <#far-patchtables>`__ classes.
|
||||
embodied in the `Far::PatchTable <#far-patchtable>`__ and the
|
||||
`Far::StencilTable <#far-patchtable>`__ classes.
|
||||
|
||||
*Far* is also a fully featured API. Typically *Far* tabular data is targeted at
|
||||
*Osd*, where it can be processed by an implementation optimized for a specific
|
||||
@ -87,8 +87,8 @@ Far::TopologyRefiner
|
||||
TopologyRefiner is the building block for many other useful classes in
|
||||
OpenSubdiv, but its purpose is more specific. It is intended to store the
|
||||
topology of an arbitrarily refined subdivision hierarchy to support the
|
||||
construction of `stencil tables <#patch-tables>`__, `patch tables
|
||||
<#patch-tables>`__, etc.
|
||||
construction of `stencil table <#patch-table>`__, `patch table
|
||||
<#patch-table>`__, etc.
|
||||
|
||||
Aside from public access to topology, TopologyRefiner has public refinement
|
||||
methods (currently *RefineUniform()* and *RefineAdapative()*) where simple
|
||||
@ -185,14 +185,14 @@ A common base class has been created for the factory class, i.e.:
|
||||
both to provide common code independent of <MESH> and also potentially to
|
||||
protect core code from unwanted specialization.
|
||||
|
||||
Far::PatchTables
|
||||
Far::PatchTable
|
||||
================
|
||||
|
||||
|
||||
The patch tables are a serialized topology representation. This container is
|
||||
generated using *Far::PatchTablesFactory* from an instance
|
||||
The patch table is a serialized topology representation. This container is
|
||||
generated using *Far::PatchTableFactory* from an instance
|
||||
*Far::TopologyRefiner* after a refinement has been applied. The
|
||||
FarPatchTablesFactory traverses the data-structures of the TopologyRefiner and
|
||||
FarPatchTableFactory traverses the data-structures of the TopologyRefiner and
|
||||
serializes the sub-faces into collections of bi-linear and bi-cubic patches, as
|
||||
dictated by the refinement mode (uniform or adaptive). The patches are then
|
||||
sorted into arrays based on their types.
|
||||
@ -216,13 +216,13 @@ description of the patches in the array. This includes the patches *type*,
|
||||
*pattern* and *rotation*.
|
||||
|
||||
The PatchArray *ArrayRange* provides the indices necessary to track the records
|
||||
of individual patches in the tables.
|
||||
of individual patches in the table.
|
||||
|
||||
Patch Types
|
||||
***********
|
||||
|
||||
The following are the different patch types that can be represented in the
|
||||
PatchTables:
|
||||
PatchTable:
|
||||
|
||||
+-------------------------------------------------------------------------+
|
||||
| |
|
||||
@ -285,11 +285,11 @@ Patch Transitions
|
||||
.. include:: under_development.rst
|
||||
|
||||
|
||||
Far::StencilTables
|
||||
Far::StencilTable
|
||||
==================
|
||||
|
||||
The base container for stencil data is the StencilTables class. As with most
|
||||
other Far entities, it has an associated StencilTablesFactory that requires a
|
||||
The base container for stencil data is the StencilTable class. As with most
|
||||
other Far entities, it has an associated StencilTableFactory that requires a
|
||||
TopologyRefiner:
|
||||
|
||||
Advantages
|
||||
@ -321,7 +321,7 @@ iteration interpolates the new vertices by applying polynomial weights to a
|
||||
|
||||
The interpolation calculations for any given vertex can be broken down into
|
||||
sequences of multiply-add operations applied to the supporting vertices.
|
||||
Stencil tables encode a factorization of these weighted sums : each stencils is
|
||||
Stencil table encodes a factorization of these weighted sums : each stencils is
|
||||
created by combining the list of control vertices from the 1-ring.
|
||||
|
||||
With iterative subdivision, each refinement step is dependent upon the previous
|
||||
@ -377,7 +377,7 @@ derivatives, so limit stencils carry a set of weights for tangent vectors.
|
||||
.. image:: images/far_stencil0.png
|
||||
:align: center
|
||||
|
||||
Once the stencil tables have been generated, limit stencils are the most direct
|
||||
Once the stencil table has been generated, limit stencils are the most direct
|
||||
and efficient method of evaluation of specific locations on the limit of a
|
||||
subdivision surface, starting from the coarse vertices of the control cage.
|
||||
|
||||
|
@ -63,8 +63,8 @@
|
||||
<li><a href="far_overview.html">Far</a></li>
|
||||
<ul>
|
||||
<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-stenciltables">Stencil Tables</a></li>
|
||||
<li><a href="far_overview.html#far-patchtable">Patch Table</a></li>
|
||||
<li><a href="far_overview.html#far-stenciltable">Stencil Table</a></li>
|
||||
</ul>
|
||||
<li><a href="vtr_overview.html">Vtr</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**
|
||||
|
||||
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|
|
||||
|
|
||||
- | **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>`__
|
||||
|
|
||||
| **Tutorial 5**
|
||||
| This tutorial shows how to create and manipulate both 'vertex' and 'varying'
|
||||
FarStencilTables to interpolate 2 primvar data buffers: vertex positions and
|
||||
FarStencilTable to interpolate 2 primvar data buffers: vertex positions and
|
||||
vertex colors. `[code] <far_tutorial_5.html>`__
|
||||
|
|
||||
| **Tutorial 6**
|
||||
| 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|
|
||||
|
|
||||
| **Tutorial 7**
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef 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
|
||||
float const * getAdaptivePatchColor(OpenSubdiv::Far::PatchDescriptor const & desc);
|
||||
|
@ -236,12 +236,14 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner * refiner,
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
|
||||
// calc normal vectors
|
||||
int nverts = refiner->GetNumVertices(0),
|
||||
nfaces = refiner->GetNumFaces(0);
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
|
||||
int nverts = refBaseLevel.GetNumVertices(),
|
||||
nfaces = refBaseLevel.GetNumFaces();
|
||||
|
||||
for (int face = 0; face < nfaces; ++face) {
|
||||
|
||||
IndexArray fverts = refiner->GetFaceVertices(0, face);
|
||||
IndexArray fverts = refBaseLevel.GetFaceVertices(face);
|
||||
|
||||
float const * p0 = &pos[fverts[0]*3],
|
||||
* p1 = &pos[fverts[1]*3],
|
||||
@ -704,12 +706,13 @@ createOsdMesh(int level, int kernel) {
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
|
||||
// create cage edge index
|
||||
int nedges = refiner->GetNumEdges(0);
|
||||
int nedges = refBaseLevel.GetNumEdges();
|
||||
std::vector<int> edgeIndices(nedges*2);
|
||||
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+1]=verts[1];
|
||||
}
|
||||
@ -734,7 +737,7 @@ createOsdMesh(int level, int kernel) {
|
||||
|
||||
if (g_kernel == kCPU) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -746,7 +749,7 @@ createOsdMesh(int level, int kernel) {
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -758,7 +761,7 @@ createOsdMesh(int level, int kernel) {
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -771,7 +774,7 @@ createOsdMesh(int level, int kernel) {
|
||||
} else if(kernel == kCL) {
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLStencilTable,
|
||||
Osd::CLEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
CLD3D11DeviceContext>(
|
||||
@ -785,7 +788,7 @@ createOsdMesh(int level, int kernel) {
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (g_kernel == kCUDA) {
|
||||
g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer,
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaStencilTable,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -797,7 +800,7 @@ createOsdMesh(int level, int kernel) {
|
||||
} else if (g_kernel == kDirectCompute) {
|
||||
static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer,
|
||||
Osd::D3D11StencilTables,
|
||||
Osd::D3D11StencilTable,
|
||||
Osd::D3D11ComputeEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
|
@ -277,22 +277,24 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
int nedges = refiner->GetNumEdges(0),
|
||||
nverts = refiner->GetNumVertices(0);
|
||||
Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
|
||||
int nedges = refBaseLevel.GetNumEdges(),
|
||||
nverts = refBaseLevel.GetNumVertices();
|
||||
|
||||
g_coarseEdges.resize(nedges*2);
|
||||
g_coarseEdgeSharpness.resize(nedges);
|
||||
g_coarseVertexSharpness.resize(nverts);
|
||||
|
||||
for(int i=0; i<nedges; ++i) {
|
||||
IndexArray verts = refiner->GetEdgeVertices(0, i);
|
||||
IndexArray verts = refBaseLevel.GetEdgeVertices(i);
|
||||
g_coarseEdges[i*2 ]=verts[0];
|
||||
g_coarseEdges[i*2+1]=verts[1];
|
||||
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i);
|
||||
g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
|
||||
}
|
||||
|
||||
for(int i=0; i<nverts; ++i) {
|
||||
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i);
|
||||
g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
|
||||
}
|
||||
|
||||
g_orgPositions=shape->verts;
|
||||
@ -320,7 +322,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
|
||||
if (g_kernel == kCPU) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -332,7 +334,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -344,7 +346,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -357,7 +359,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
} else if(kernel == kCL) {
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLStencilTable,
|
||||
Osd::CLEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
CLD3D11DeviceContext>(
|
||||
@ -371,7 +373,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (g_kernel == kCUDA) {
|
||||
g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer,
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaStencilTable,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -383,7 +385,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
} else if (g_kernel == kDirectCompute) {
|
||||
static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer,
|
||||
Osd::D3D11StencilTables,
|
||||
Osd::D3D11StencilTable,
|
||||
Osd::D3D11ComputeEvaluator,
|
||||
Osd::D3D11PatchTable,
|
||||
ID3D11DeviceContext>(
|
||||
@ -403,7 +405,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
if (g_endCap == kEndCapLegacyGregory) {
|
||||
g_legacyGregoryPatchTable =
|
||||
Osd::D3D11LegacyGregoryPatchTable::Create(
|
||||
g_mesh->GetFarPatchTables(), g_pd3dDeviceContext);
|
||||
g_mesh->GetFarPatchTable(), g_pd3dDeviceContext);
|
||||
}
|
||||
|
||||
// compute model bounding
|
||||
@ -827,7 +829,7 @@ display() {
|
||||
g_mesh->GetPatchTable()->GetPatchIndexBuffer(), DXGI_FORMAT_R32_UINT, 0);
|
||||
|
||||
// patch drawing
|
||||
int patchCount[12]; // [Type] (see far/patchTables.h)
|
||||
int patchCount[12]; // [Type] (see far/patchTable.h)
|
||||
int numTotalPatches = 0;
|
||||
int numDrawCalls = 0;
|
||||
|
||||
|
@ -50,9 +50,9 @@ GLFWmonitor* g_primary=0;
|
||||
|
||||
#include <far/gregoryBasis.h>
|
||||
#include <far/endCapGregoryBasisPatchFactory.h>
|
||||
#include <far/patchTablesFactory.h>
|
||||
#include <far/stencilTables.h>
|
||||
#include <far/stencilTablesFactory.h>
|
||||
#include <far/patchTableFactory.h>
|
||||
#include <far/stencilTable.h>
|
||||
#include <far/stencilTableFactory.h>
|
||||
|
||||
#include <common/vtr_utils.h>
|
||||
|
||||
@ -212,7 +212,7 @@ createVertNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
|
||||
if (refiner.IsUniform()) {
|
||||
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 {
|
||||
|
||||
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);
|
||||
g_font->Print3D(vertexBuffer[vert].GetPos(), buf, 1);
|
||||
}
|
||||
@ -245,16 +245,17 @@ createEdgeNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
firstvert = 0;
|
||||
|
||||
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];
|
||||
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);
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const verts =
|
||||
refiner.GetEdgeVertices(maxlevel, i);
|
||||
OpenSubdiv::Far::ConstIndexArray const verts = refLastLevel.GetEdgeVertices(i);
|
||||
assert(verts.size()==2);
|
||||
|
||||
center.AddWithWeight(vertexBuffer[firstvert+verts[0]], 0.5f);
|
||||
@ -266,7 +267,7 @@ createEdgeNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
}
|
||||
|
||||
if (sharpness) {
|
||||
float sharpness = refiner.GetEdgeSharpness(maxlevel, i);
|
||||
float sharpness = refLastLevel.GetEdgeSharpness(i);
|
||||
if (sharpness>0.0f) {
|
||||
snprintf(buf, 16, "%g", sharpness);
|
||||
g_font->Print3D(center.GetPos(), buf, std::min(8,(int)sharpness+4));
|
||||
@ -289,15 +290,16 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
firstvert = 0;
|
||||
|
||||
for (int i=0; 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);
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const verts =
|
||||
refiner.GetFaceVertices(maxlevel, face);
|
||||
OpenSubdiv::Far::ConstIndexArray const verts = refLastLevel.GetFaceVertices(face);
|
||||
|
||||
float weight = 1.0f / (float)verts.size();
|
||||
|
||||
@ -310,19 +312,20 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
}
|
||||
} else {
|
||||
int maxlevel = refiner.GetMaxLevel(),
|
||||
// patch = refiner.GetNumFaces(0),
|
||||
firstvert = refiner.GetNumVertices(0);
|
||||
// patch = refiner.GetLevel(0).GetNumFaces(),
|
||||
firstvert = refiner.GetLevel(0).GetNumVertices();
|
||||
|
||||
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 */) {
|
||||
|
||||
Vertex center(0.0f, 0.0f, 0.0f);
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const verts =
|
||||
refiner.GetFaceVertices(level, face);
|
||||
OpenSubdiv::Far::ConstIndexArray const verts = refLevel.GetFaceVertices(face);
|
||||
|
||||
float weight = 1.0f / (float)verts.size();
|
||||
|
||||
@ -332,7 +335,7 @@ createFaceNumbers(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
snprintf(buf, 16, "%d", face);
|
||||
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
|
||||
static void
|
||||
createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
createPatchNumbers(OpenSubdiv::Far::PatchTable const & patchTable,
|
||||
std::vector<Vertex> const & vertexBuffer) {
|
||||
|
||||
if (not g_currentPatch)
|
||||
@ -350,8 +353,8 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
patchArray = -1;
|
||||
|
||||
// Find PatchArray containing our patch
|
||||
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
|
||||
int npatches = patchTables.GetNumPatches(array);
|
||||
for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
|
||||
int npatches = patchTable.GetNumPatches(array);
|
||||
if (patchID >= npatches) {
|
||||
patchID -= npatches;
|
||||
} else {
|
||||
@ -363,10 +366,10 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
return;
|
||||
}
|
||||
|
||||
g_currentPatchDesc = patchTables.GetPatchArrayDescriptor(patchArray);
|
||||
g_currentPatchDesc = patchTable.GetPatchArrayDescriptor(patchArray);
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const cvs =
|
||||
patchTables.GetPatchVertices(patchArray, patchID);
|
||||
patchTable.GetPatchVertices(patchArray, patchID);
|
||||
|
||||
static char buf[16];
|
||||
for (int i=0; i<cvs.size(); ++i) {
|
||||
@ -378,7 +381,7 @@ createPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
//------------------------------------------------------------------------------
|
||||
// generate display vert IDs for the selected Far FVar patch
|
||||
static void
|
||||
createFVarPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
createFVarPatchNumbers(OpenSubdiv::Far::PatchTable const & patchTable,
|
||||
std::vector<Vertex> const & fvarBuffer) {
|
||||
|
||||
static int channel = 0;
|
||||
@ -386,20 +389,20 @@ createFVarPatchNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
int patch = g_currentPatch-1;
|
||||
static char buf[16];
|
||||
|
||||
if (patch>=0 and patch<patchTables.GetNumPatchesTotal()) {
|
||||
if (patch>=0 and patch<patchTable.GetNumPatchesTotal()) {
|
||||
|
||||
OpenSubdiv::Far::PatchTables::PatchHandle handle;
|
||||
OpenSubdiv::Far::PatchTable::PatchHandle handle;
|
||||
handle.patchIndex = patch;
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const cvs =
|
||||
patchTables.GetFVarPatchValues(channel, handle);
|
||||
patchTable.GetFVarPatchValues(channel, handle);
|
||||
|
||||
for (int i=0; i<cvs.size(); ++i) {
|
||||
snprintf(buf, 16, "%d", i);
|
||||
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
|
||||
createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
OpenSubdiv::Far::PatchTable const & patchTable,
|
||||
std::vector<Vertex> const & fvarBuffer) {
|
||||
|
||||
assert(not fvarBuffer.empty());
|
||||
@ -420,14 +423,14 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
if (g_FarDrawFVarVerts) {
|
||||
GLMesh::Options options;
|
||||
options.vertColorMode = GLMesh::VERTCOLOR_BY_LEVEL;
|
||||
fvarVerts.InitializeFVar(options, refiner, &patchTables, channel, 0, (float *)(&fvarBuffer[0]));
|
||||
fvarVerts.InitializeFVar(options, refiner, &patchTable, channel, 0, (float *)(&fvarBuffer[0]));
|
||||
}
|
||||
|
||||
if (g_FarDrawFVarPatches) {
|
||||
|
||||
// generate uniform tessellation for patches
|
||||
int tessFactor = g_FarDrawFVarPatchTess,
|
||||
npatches = patchTables.GetNumPatchesTotal(),
|
||||
npatches = patchTable.GetNumPatchesTotal(),
|
||||
nvertsperpatch = (tessFactor) * (tessFactor),
|
||||
nverts = npatches * nvertsperpatch;
|
||||
|
||||
@ -439,7 +442,7 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
std::vector<Vertex> verts(nverts);
|
||||
memset(&verts[0], 0, verts.size()*sizeof(Vertex));
|
||||
|
||||
OpenSubdiv::Far::PatchTables::PatchHandle handle;
|
||||
OpenSubdiv::Far::PatchTable::PatchHandle handle;
|
||||
|
||||
Vertex * vert = &verts[0];
|
||||
for (int patch=0; patch<npatches; ++patch) {
|
||||
@ -447,14 +450,14 @@ createFVarPatches(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
for (int j=0; j<tessFactor; ++j, ++vert) {
|
||||
handle.patchIndex = patch;
|
||||
// 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;
|
||||
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 void
|
||||
createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
createGregoryBasis(OpenSubdiv::Far::PatchTable const & patchTable,
|
||||
std::vector<Vertex> const & vertexBuffer) {
|
||||
|
||||
typedef OpenSubdiv::Far::PatchDescriptor PatchDescriptor;
|
||||
|
||||
int npatches = 0;
|
||||
int patchArray = 0;
|
||||
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
|
||||
if (patchTables.GetPatchArrayDescriptor(array).GetType()==
|
||||
for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
|
||||
if (patchTable.GetPatchArrayDescriptor(array).GetType()==
|
||||
PatchDescriptor::GREGORY_BASIS) {
|
||||
npatches = patchTables.GetNumPatches(array);
|
||||
npatches = patchTable.GetNumPatches(array);
|
||||
patchArray = array;
|
||||
break;
|
||||
}
|
||||
@ -496,7 +499,7 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
* indices = &edgeindices[patch * 40];
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const cvs =
|
||||
patchTables.GetPatchVertices(patchArray, patch);
|
||||
patchTable.GetPatchVertices(patchArray, patch);
|
||||
|
||||
for (int i=0; i<20; ++i) {
|
||||
vpe[i] = 2;
|
||||
@ -536,7 +539,7 @@ createGregoryBasis(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
//------------------------------------------------------------------------------
|
||||
// generate display IDs for Far faces
|
||||
static void
|
||||
createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
createPtexNumbers(OpenSubdiv::Far::PatchTable const & patchTable,
|
||||
std::vector<Vertex> const & vertexBuffer) {
|
||||
|
||||
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
|
||||
@ -546,15 +549,15 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
static int regular[4] = {5, 6, 9, 10},
|
||||
gregory[4] = {0, 1, 2, 3};
|
||||
|
||||
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
|
||||
for (int array=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
|
||||
|
||||
for (int patch=0; patch<(int)patchTables.GetNumPatches(array); ++patch) {
|
||||
for (int patch=0; patch<(int)patchTable.GetNumPatches(array); ++patch) {
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const cvs =
|
||||
patchTables.GetPatchVertices(array, patch);
|
||||
patchTable.GetPatchVertices(array, patch);
|
||||
|
||||
int * remap = 0;
|
||||
switch (patchTables.GetPatchArrayDescriptor(array).GetType()) {
|
||||
switch (patchTable.GetPatchArrayDescriptor(array).GetType()) {
|
||||
case Descriptor::REGULAR: remap = regular; break;
|
||||
case Descriptor::GREGORY:
|
||||
case Descriptor::GREGORY_BOUNDARY:
|
||||
@ -568,7 +571,7 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
|
||||
center.AddWithWeight(vertexBuffer[cvs[remap[k]]], 0.25f);
|
||||
}
|
||||
|
||||
snprintf(buf, 16, "%d", patchTables.GetPatchParam(array, patch).faceIndex);
|
||||
snprintf(buf, 16, "%d", patchTable.GetPatchParam(array, patch).faceIndex);
|
||||
g_font->Print3D(center.GetPos(), buf, 1);
|
||||
}
|
||||
}
|
||||
@ -606,35 +609,35 @@ createFarGLMesh(Shape * shape, int maxlevel) {
|
||||
int numTotalVerts = refiner->GetNumVerticesTotal();
|
||||
|
||||
//
|
||||
// Patch tables
|
||||
// Patch table
|
||||
//
|
||||
std::vector<Vertex> fvarBuffer;
|
||||
Far::PatchTables * patchTables = 0;
|
||||
Far::PatchTable * patchTable = 0;
|
||||
bool createFVarWire = g_FarDrawFVarPatches or g_FarDrawFVarVerts;
|
||||
|
||||
if (g_Adaptive) {
|
||||
Far::PatchTablesFactory::Options options;
|
||||
Far::PatchTableFactory::Options options;
|
||||
options.generateFVarTables = createFVarWire;
|
||||
options.shareEndCapPatchPoints = false;
|
||||
|
||||
patchTables =
|
||||
Far::PatchTablesFactory::Create(*refiner, options);
|
||||
patchTable =
|
||||
Far::PatchTableFactory::Create(*refiner, options);
|
||||
|
||||
// increase vertex buffer for the additional endcap verts
|
||||
if (patchTables->GetEndCapVertexStencilTables()) {
|
||||
numTotalVerts += patchTables->GetEndCapVertexStencilTables()->GetNumStencils();
|
||||
if (patchTable->GetEndCapVertexStencilTable()) {
|
||||
numTotalVerts += patchTable->GetEndCapVertexStencilTable()->GetNumStencils();
|
||||
}
|
||||
|
||||
g_numPatches = patchTables->GetNumPatchesTotal();
|
||||
g_maxValence = patchTables->GetMaxValence();
|
||||
g_numPatches = patchTable->GetNumPatchesTotal();
|
||||
g_maxValence = patchTable->GetMaxValence();
|
||||
|
||||
if (createFVarWire) {
|
||||
|
||||
// interpolate fvar values
|
||||
|
||||
//Far::FVarPatchTables const * fvarTables =
|
||||
// patchTables->GetFVarPatchTables();
|
||||
//assert(fvarTables);
|
||||
//Far::FVarPatchTable const * fvarTable =
|
||||
// patchTable->GetFVarPatchTable();
|
||||
//assert(fvarTable);
|
||||
|
||||
int channel = 0;
|
||||
|
||||
@ -642,7 +645,7 @@ createFarGLMesh(Shape * shape, int maxlevel) {
|
||||
fvarBuffer.resize(refiner->GetNumFVarValuesTotal(channel), 0);
|
||||
Vertex * values = &fvarBuffer[0];
|
||||
|
||||
int nCoarseValues = refiner->GetNumFVarValues(0);
|
||||
int nCoarseValues = refiner->GetLevel(0).GetNumFVarValues(channel);
|
||||
|
||||
for (int i=0; i<nCoarseValues; ++i) {
|
||||
float const * ptr = &shape->uvs[i*2];
|
||||
@ -672,29 +675,29 @@ createFarGLMesh(Shape * shape, int maxlevel) {
|
||||
//
|
||||
// Stencil interpolation
|
||||
//
|
||||
Far::StencilTables const * stencilTables = 0;
|
||||
Far::StencilTablesFactory::Options options;
|
||||
Far::StencilTable const * stencilTable = 0;
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateOffsets=true;
|
||||
options.generateIntermediateLevels=true;
|
||||
stencilTables = Far::StencilTablesFactory::Create(*refiner, options);
|
||||
stencilTable = Far::StencilTableFactory::Create(*refiner, options);
|
||||
|
||||
// append endpatch stencils if needed
|
||||
if (patchTables and patchTables->GetEndCapVertexStencilTables()) {
|
||||
if (Far::StencilTables const * stencilTablesWithEndCap =
|
||||
Far::StencilTablesFactory::AppendEndCapStencilTables(
|
||||
*refiner, stencilTables,
|
||||
patchTables->GetEndCapVertexStencilTables())) {
|
||||
delete stencilTables;
|
||||
stencilTables = stencilTablesWithEndCap;
|
||||
if (patchTable and patchTable->GetEndCapVertexStencilTable()) {
|
||||
if (Far::StencilTable const * stencilTableWithEndCap =
|
||||
Far::StencilTableFactory::AppendEndCapStencilTable(
|
||||
*refiner, stencilTable,
|
||||
patchTable->GetEndCapVertexStencilTable())) {
|
||||
delete stencilTable;
|
||||
stencilTable = stencilTableWithEndCap;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// apply stencils
|
||||
//
|
||||
stencilTables->UpdateValues(verts, verts + ncoarseverts);
|
||||
stencilTable->UpdateValues(verts, verts + ncoarseverts);
|
||||
|
||||
delete stencilTables;
|
||||
delete stencilTable;
|
||||
} else {
|
||||
//
|
||||
// TopologyRefiner interpolation
|
||||
@ -722,21 +725,21 @@ createFarGLMesh(Shape * shape, int maxlevel) {
|
||||
createFaceNumbers(*refiner, vertexBuffer);
|
||||
}
|
||||
|
||||
if (g_FarDrawPtexIDs and patchTables) {
|
||||
createPtexNumbers(*patchTables, vertexBuffer);
|
||||
if (g_FarDrawPtexIDs and patchTable) {
|
||||
createPtexNumbers(*patchTable, vertexBuffer);
|
||||
}
|
||||
|
||||
if (g_Adaptive) {
|
||||
createPatchNumbers(*patchTables, vertexBuffer);
|
||||
createPatchNumbers(*patchTable, vertexBuffer);
|
||||
}
|
||||
|
||||
if (g_Adaptive and g_FarDrawGregogyBasis) {
|
||||
createGregoryBasis(*patchTables, vertexBuffer);
|
||||
createGregoryBasis(*patchTable, vertexBuffer);
|
||||
}
|
||||
|
||||
if (g_Adaptive and createFVarWire) {
|
||||
createFVarPatches(*refiner, *patchTables, fvarBuffer);
|
||||
createFVarPatchNumbers(*patchTables, fvarBuffer);
|
||||
createFVarPatches(*refiner, *patchTable, fvarBuffer);
|
||||
createFVarPatchNumbers(*patchTable, fvarBuffer);
|
||||
}
|
||||
|
||||
createEdgeNumbers(*refiner, vertexBuffer, g_FarDrawEdgeIDs!=0, g_FarDrawEdgeSharpness!=0);
|
||||
@ -746,7 +749,7 @@ createFarGLMesh(Shape * shape, int maxlevel) {
|
||||
options.edgeColorMode=g_Adaptive ? GLMesh::EDGECOLOR_BY_PATCHTYPE : GLMesh::EDGECOLOR_BY_SHARPNESS;
|
||||
options.faceColorMode=g_Adaptive ? GLMesh::FACECOLOR_BY_PATCHTYPE :GLMesh::FACECOLOR_SOLID;
|
||||
|
||||
g_far_glmesh.Initialize(options, *refiner, patchTables, (float *)&verts[0]);
|
||||
g_far_glmesh.Initialize(options, *refiner, patchTable, (float *)&verts[0]);
|
||||
if (g_Adaptive) {
|
||||
g_far_glmesh.SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
} else {
|
||||
@ -759,7 +762,7 @@ createFarGLMesh(Shape * shape, int maxlevel) {
|
||||
g_far_glmesh.InitializeDeviceBuffers();
|
||||
|
||||
delete refiner;
|
||||
delete patchTables;
|
||||
delete patchTable;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -243,10 +243,10 @@ GLMesh::Initialize(Options /* options */,
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
GLMesh::Initialize(Options options, TopologyRefiner const & refiner,
|
||||
PatchTables const * patchTables, float const * vertexData) {
|
||||
PatchTable const * patchTable, float const * vertexData) {
|
||||
|
||||
if (patchTables) {
|
||||
initializeBuffers(options, refiner, *patchTables, vertexData);
|
||||
if (patchTable) {
|
||||
initializeBuffers(options, refiner, *patchTable, vertexData);
|
||||
} else {
|
||||
initializeBuffers(options, refiner, vertexData);
|
||||
}
|
||||
@ -265,15 +265,18 @@ GLMesh::initializeBuffers(Options options,
|
||||
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
|
||||
int maxlevel = refiner.GetMaxLevel(),
|
||||
nverts = refiner.GetNumVertices(maxlevel),
|
||||
nedges = refiner.GetNumEdges(maxlevel),
|
||||
nfaces = refiner.GetNumFaces(maxlevel),
|
||||
int maxlevel = refiner.GetMaxLevel();
|
||||
|
||||
OpenSubdiv::Far::TopologyLevel const & refLastLevel = refiner.GetLevel(maxlevel);
|
||||
|
||||
int nverts = refLastLevel.GetNumVertices(),
|
||||
nedges = refLastLevel.GetNumEdges(),
|
||||
nfaces = refLastLevel.GetNumFaces(),
|
||||
firstvert = 0;
|
||||
|
||||
|
||||
for (int i=0; i<maxlevel; ++i) {
|
||||
firstvert += refiner.GetNumVertices(i);
|
||||
firstvert += refiner.GetLevel(i).GetNumVertices();
|
||||
}
|
||||
|
||||
float const * vertData = &vertexData[firstvert*3];
|
||||
@ -287,31 +290,33 @@ GLMesh::initializeBuffers(Options options,
|
||||
// set colors
|
||||
if (options.vertColorMode==VERTCOLOR_BY_LEVEL) {
|
||||
|
||||
for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) {
|
||||
for (int vert=0; vert<refiner.GetNumVertices(level); ++vert, ofs+=6) {
|
||||
for (int level=0, ofs=3; level<=maxlevel; ++level) {
|
||||
for (int vert=0; vert<refiner.GetLevel(level).GetNumVertices(); ++vert, ofs+=6) {
|
||||
setColorByLevel(level, &vbo[ofs]);
|
||||
}
|
||||
}
|
||||
} else if (options.vertColorMode==VERTCOLOR_BY_SHARPNESS) {
|
||||
|
||||
for (int vert=0, ofs=3; vert<refiner.GetNumVertices(maxlevel); ++vert, ofs+=6) {
|
||||
setColorBySharpness(refiner.GetVertexSharpness(maxlevel, vert), &vbo[ofs]);
|
||||
for (int vert=0, ofs=3; vert<refLastLevel.GetNumVertices(); ++vert, ofs+=6) {
|
||||
setColorBySharpness(refLastLevel.GetVertexSharpness(vert), &vbo[ofs]);
|
||||
}
|
||||
} else if (options.vertColorMode==VERTCOLOR_BY_PARENT_TYPE) {
|
||||
|
||||
int ofs=3;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@ -337,7 +342,7 @@ GLMesh::initializeBuffers(Options options,
|
||||
eao[edge*2 ] = edge*2;
|
||||
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],
|
||||
* v1 = v0+6;
|
||||
@ -353,7 +358,7 @@ GLMesh::initializeBuffers(Options options,
|
||||
setColorByLevel(maxlevel, v1+3);
|
||||
} else if (options.edgeColorMode==EDGECOLOR_BY_SHARPNESS) {
|
||||
|
||||
float sharpness = refiner.GetEdgeSharpness(maxlevel, edge);
|
||||
float sharpness = refLastLevel.GetEdgeSharpness(edge);
|
||||
setColorBySharpness(sharpness, v0+3);
|
||||
setColorBySharpness(sharpness, v1+3);
|
||||
} else {
|
||||
@ -372,7 +377,7 @@ GLMesh::initializeBuffers(Options options,
|
||||
|
||||
memcpy(&vbo[0], vertData, nverts*sizeof(float)*3);
|
||||
|
||||
int nfaceverts = refiner.GetNumFaceVertices(maxlevel);
|
||||
int nfaceverts = refLastLevel.GetNumFaceVertices();
|
||||
|
||||
std::vector<int> & eao = _eao[COMP_FACE];
|
||||
eao.resize(nfaceverts);
|
||||
@ -381,7 +386,7 @@ GLMesh::initializeBuffers(Options options,
|
||||
|
||||
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) {
|
||||
eao[ofs++] = fverts[vert];
|
||||
}
|
||||
@ -408,7 +413,7 @@ setEdge(std::vector<float> & vbo, int edge, float const * vertData, int v0, int
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner,
|
||||
PatchTables const * patchTables, int channel, int tessFactor, float const * fvarData) {
|
||||
PatchTable const * patchTable, int channel, int tessFactor, float const * fvarData) {
|
||||
|
||||
int nverts = refiner.GetNumFVarValuesTotal(channel);
|
||||
|
||||
@ -421,7 +426,7 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner,
|
||||
if (options.vertColorMode==VERTCOLOR_BY_LEVEL) {
|
||||
|
||||
for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) {
|
||||
for (int vert=0; 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());
|
||||
setColorByLevel(level, &vbo[ofs]);
|
||||
}
|
||||
@ -437,7 +442,7 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner,
|
||||
if (tessFactor>0) {
|
||||
// edge color component ------------------------------
|
||||
|
||||
int npatches = patchTables->GetNumPatchesTotal(),
|
||||
int npatches = patchTable->GetNumPatchesTotal(),
|
||||
nvertsperpatch = (tessFactor) * (tessFactor),
|
||||
nedgesperpatch = (tessFactor-1) * (tessFactor*2+tessFactor-1),
|
||||
//nverts = npatches * nvertsperpatch,
|
||||
@ -475,14 +480,14 @@ GLMesh::InitializeFVar(Options options, TopologyRefiner const & refiner,
|
||||
*ptr++ = tessFactor * (tessFactor-1) + i+1;
|
||||
}
|
||||
|
||||
OpenSubdiv::Far::PatchTables::PatchHandle handle;
|
||||
OpenSubdiv::Far::PatchTable::PatchHandle handle;
|
||||
for (int patch=0, offset=0; patch<npatches; ++patch) {
|
||||
|
||||
if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) {
|
||||
|
||||
handle.patchIndex = patch;
|
||||
OpenSubdiv::Far::PatchDescriptor::Type type =
|
||||
patchTables->GetFVarPatchType(channel, handle);
|
||||
patchTable->GetFVarPatchType(channel, handle);
|
||||
|
||||
if (OpenSubdiv::Far::PatchDescriptor::IsAdaptive(type)) {
|
||||
color = getAdaptivePatchColor(
|
||||
@ -591,7 +596,7 @@ getRingSize(OpenSubdiv::Far::PatchDescriptor desc) {
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
PatchTables const & patchTables, float const * vertexData) {
|
||||
PatchTable const & patchTable, float const * vertexData) {
|
||||
|
||||
int nverts = refiner.GetNumVerticesTotal();
|
||||
|
||||
@ -604,7 +609,7 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
if (options.vertColorMode==VERTCOLOR_BY_LEVEL) {
|
||||
|
||||
for (int level=0, ofs=3; level<=refiner.GetMaxLevel(); ++level) {
|
||||
for (int vert=0; vert<refiner.GetNumVertices(level); ++vert, ofs+=6) {
|
||||
for (int vert=0; vert<refiner.GetLevel(level).GetNumVertices(); ++vert, ofs+=6) {
|
||||
assert(ofs<(int)vbo.size());
|
||||
setColorByLevel(level, &vbo[ofs]);
|
||||
}
|
||||
@ -623,11 +628,11 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
|
||||
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];
|
||||
vbo.resize(nedges * 2 * 6);
|
||||
@ -641,10 +646,10 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
|
||||
float const * color=solidColor;
|
||||
|
||||
for (int array=0, edge=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
|
||||
for (int array=0, edge=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
|
||||
|
||||
OpenSubdiv::Far::PatchDescriptor desc =
|
||||
patchTables.GetPatchArrayDescriptor(array);
|
||||
patchTable.GetPatchArrayDescriptor(array);
|
||||
|
||||
if (options.edgeColorMode==EDGECOLOR_BY_PATCHTYPE) {
|
||||
color = getAdaptivePatchColor(desc);
|
||||
@ -652,10 +657,10 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
|
||||
int ncvs = getRingSize(desc);
|
||||
|
||||
for (int patch=0; patch<patchTables.GetNumPatches(array); ++patch) {
|
||||
for (int patch=0; patch<patchTable.GetNumPatches(array); ++patch) {
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const cvs =
|
||||
patchTables.GetPatchVertices(array, patch);
|
||||
patchTable.GetPatchVertices(array, patch);
|
||||
|
||||
int const * edgeList=getEdgeList(ncvs);
|
||||
|
||||
@ -674,7 +679,7 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
|
||||
{ // face color component ------------------------------
|
||||
|
||||
int nfaces = patchTables.GetNumPatchesTotal();
|
||||
int nfaces = patchTable.GetNumPatchesTotal();
|
||||
|
||||
std::vector<float> & vbo = _vbo[COMP_FACE];
|
||||
vbo.resize(nverts*3);
|
||||
@ -686,17 +691,17 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
_faceColors.resize(nfaces*4, 1.0f);
|
||||
|
||||
// default to solid color
|
||||
for (int array=0, face=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
|
||||
for (int array=0, face=0; array<(int)patchTable.GetNumPatchArrays(); ++array) {
|
||||
|
||||
OpenSubdiv::Far::PatchDescriptor desc =
|
||||
patchTables.GetPatchArrayDescriptor(array);
|
||||
patchTable.GetPatchArrayDescriptor(array);
|
||||
|
||||
//int ncvs = getRingSize(desc);
|
||||
|
||||
for (int patch=0; patch<patchTables.GetNumPatches(array); ++patch, ++face) {
|
||||
for (int patch=0; patch<patchTable.GetNumPatches(array); ++patch, ++face) {
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray const cvs =
|
||||
patchTables.GetPatchVertices(array, patch);
|
||||
patchTable.GetPatchVertices(array, patch);
|
||||
|
||||
if (desc.GetType()==Descriptor::REGULAR) {
|
||||
eao[face*4 ] = cvs[ 5];
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include <common/vtr_utils.h>
|
||||
#include <common/hbr_utils.h>
|
||||
#include <far/patchTables.h>
|
||||
#include <far/patchTable.h>
|
||||
|
||||
#include "../common/glUtils.h"
|
||||
|
||||
@ -193,13 +193,13 @@ public:
|
||||
// Far initialization
|
||||
typedef OpenSubdiv::Far::TopologyRefiner TopologyRefiner;
|
||||
|
||||
typedef OpenSubdiv::Far::PatchTables PatchTables;
|
||||
typedef OpenSubdiv::Far::PatchTable PatchTable;
|
||||
|
||||
void Initialize(Options options, TopologyRefiner const & refiner,
|
||||
PatchTables const * patchTables, float const * vertexData);
|
||||
PatchTable const * patchTable, float const * vertexData);
|
||||
|
||||
void InitializeFVar(Options options, TopologyRefiner const & refiner,
|
||||
PatchTables const * patchTables, int channel, int tessFactor, float const * fvarData);
|
||||
PatchTable const * patchTable, int channel, int tessFactor, float const * fvarData);
|
||||
|
||||
void InitializeDeviceBuffers();
|
||||
|
||||
@ -229,7 +229,7 @@ private:
|
||||
float const * vertexData);
|
||||
|
||||
void initializeBuffers(Options options, TopologyRefiner const & refiner,
|
||||
PatchTables const & patchTables, float const * vertexData);
|
||||
PatchTable const & patchTable, float const * vertexData);
|
||||
|
||||
void clearBuffers();
|
||||
|
||||
|
@ -50,8 +50,8 @@ GLFWmonitor* g_primary=0;
|
||||
#include <far/gregoryBasis.h>
|
||||
#include <far/endCapGregoryBasisPatchFactory.h>
|
||||
#include <far/topologyRefiner.h>
|
||||
#include <far/stencilTablesFactory.h>
|
||||
#include <far/patchTablesFactory.h>
|
||||
#include <far/stencilTableFactory.h>
|
||||
#include <far/patchTableFactory.h>
|
||||
#include <far/patchMap.h>
|
||||
|
||||
#include <far/error.h>
|
||||
@ -60,6 +60,7 @@ GLFWmonitor* g_primary=0;
|
||||
#include "../common/stopwatch.h"
|
||||
#include "../common/simple_math.h"
|
||||
#include "../common/glHud.h"
|
||||
#include "../common/glUtils.h"
|
||||
|
||||
#include "init_shapes.h"
|
||||
#include "particles.h"
|
||||
@ -71,10 +72,6 @@ GLFWmonitor* g_primary=0;
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -91,9 +88,11 @@ std::vector<float> g_coarseEdgeSharpness;
|
||||
std::vector<float> g_coarseVertexSharpness;
|
||||
|
||||
enum DrawMode { kRANDOM=0,
|
||||
kUV=1,
|
||||
kVARYING=2,
|
||||
kFACEVARYING=3 };
|
||||
kUV,
|
||||
kVARYING,
|
||||
kNORMAL,
|
||||
kSHADE,
|
||||
kFACEVARYING };
|
||||
|
||||
int g_running = 1,
|
||||
g_width = 1024,
|
||||
@ -146,6 +145,18 @@ GLuint g_cageEdgeVAO = 0,
|
||||
|
||||
GLhud g_hud;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct Program {
|
||||
GLuint program;
|
||||
GLuint uniformModelViewMatrix;
|
||||
GLuint uniformProjectionMatrix;
|
||||
GLuint uniformDrawMode;
|
||||
GLuint attrPosition;
|
||||
GLuint attrColor;
|
||||
GLuint attrTangentU;
|
||||
GLuint attrTangentV;
|
||||
} g_defaultProgram;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
createRandomColors(int nverts, int stride, float * colors) {
|
||||
@ -167,22 +178,24 @@ createCoarseMesh(OpenSubdiv::Far::TopologyRefiner const & refiner) {
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
int nedges = refiner.GetNumEdges(0),
|
||||
nverts = refiner.GetNumVertices(0);
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
|
||||
|
||||
int nedges = refBaseLevel.GetNumEdges(),
|
||||
nverts = refBaseLevel.GetNumVertices();
|
||||
|
||||
g_coarseEdges.resize(nedges*2);
|
||||
g_coarseEdgeSharpness.resize(nedges);
|
||||
g_coarseVertexSharpness.resize(nverts);
|
||||
|
||||
for(int i=0; i<nedges; ++i) {
|
||||
IndexArray verts = refiner.GetEdgeVertices(0, i);
|
||||
IndexArray verts = refBaseLevel.GetEdgeVertices(i);
|
||||
g_coarseEdges[i*2 ]=verts[0];
|
||||
g_coarseEdges[i*2+1]=verts[1];
|
||||
g_coarseEdgeSharpness[i]=refiner.GetEdgeSharpness(0, i);
|
||||
g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
|
||||
}
|
||||
|
||||
for(int i=0; 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
|
||||
@ -193,26 +206,28 @@ createCoarseMesh(OpenSubdiv::Far::TopologyRefiner const & refiner) {
|
||||
//------------------------------------------------------------------------------
|
||||
Far::TopologyRefiner * g_topologyRefiner = 0;
|
||||
|
||||
Osd::CpuVertexBuffer * g_vertexData = 0,
|
||||
* g_varyingData = 0;
|
||||
Far::StencilTable const * g_vertexStencils = NULL;
|
||||
Far::StencilTable const * g_varyingStencils = NULL;
|
||||
|
||||
Far::StencilTables const * g_vertexStencils = NULL;
|
||||
Far::StencilTables const * g_varyingStencils = NULL;
|
||||
|
||||
Far::PatchTables const * g_patchTables = NULL;
|
||||
Far::PatchTable const * g_patchTable = 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 ),
|
||||
g_odesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 6 ),
|
||||
g_vdesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 6 ),
|
||||
g_fvidesc( /*offset*/ 0, /*legnth*/ 2, /*stride*/ 2 ),
|
||||
g_fvodesc( /*offset*/ 3, /*legnth*/ 2, /*stride*/ 6 );
|
||||
Osd::VertexBufferDescriptor g_idesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 3),
|
||||
g_odesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 6),
|
||||
g_vdesc(/*offset*/ 3, /*legnth*/ 3, /*stride*/ 6),
|
||||
g_duDesc(/*offset*/ 0, /*legnth*/ 3, /*stride*/ 6),
|
||||
g_dvDesc(/*offset*/ 3, /*legnth*/ 3, /*stride*/ 6),
|
||||
g_fvidesc(/*offset*/ 0, /*legnth*/ 2, /*stride*/ 2),
|
||||
g_fvodesc(/*offset*/ 3, /*legnth*/ 2, /*stride*/ 6);
|
||||
|
||||
// input vertex data (coarse + refined)
|
||||
Osd::CpuVertexBuffer * g_vertexData = 0;
|
||||
Osd::CpuVertexBuffer * g_varyingData = 0;
|
||||
|
||||
Osd::CpuGLVertexBuffer * g_Q=0,
|
||||
* g_dQs=0,
|
||||
* g_dQt=0;
|
||||
// output vertex data (limit locations)
|
||||
Osd::CpuGLVertexBuffer * g_outVertexData = NULL;
|
||||
Osd::CpuGLVertexBuffer * g_outDerivatives = NULL;
|
||||
|
||||
STParticles * g_particles=0;
|
||||
|
||||
@ -245,7 +260,7 @@ updateGeom() {
|
||||
if (! g_topologyRefiner) return;
|
||||
|
||||
// note that for patch eval we need coarse+refined combined buffer.
|
||||
int nCoarseVertices = g_topologyRefiner->GetNumVertices(0);
|
||||
int nCoarseVertices = g_topologyRefiner->GetLevel(0).GetNumVertices();
|
||||
Osd::CpuEvaluator::EvalStencils(g_vertexData,
|
||||
Osd::VertexBufferDescriptor(0, 3, 3),
|
||||
g_vertexData,
|
||||
@ -280,7 +295,7 @@ updateGeom() {
|
||||
g_patchCoords.clear();
|
||||
for (int i = 0; i < g_particles->GetNumParticles(); ++i) {
|
||||
STParticles::Position const &position = g_particles->GetPositions()[i];
|
||||
Far::PatchTables::PatchHandle const *handle =
|
||||
Far::PatchTable::PatchHandle const *handle =
|
||||
g_patchMap->FindPatch(position.ptexIndex, position.s, position.t);
|
||||
if (handle) {
|
||||
g_patchCoords.push_back(Osd::PatchCoord(
|
||||
@ -289,20 +304,44 @@ updateGeom() {
|
||||
}
|
||||
|
||||
// Evaluate the positions of the samples on the limit surface
|
||||
g_nsamplesFound = Osd::CpuEvaluator::EvalPatches(g_vertexData, g_idesc,
|
||||
g_Q, g_odesc,
|
||||
g_patchCoords,
|
||||
g_patchTables, NULL);
|
||||
|
||||
// varying
|
||||
if (g_drawMode == kVARYING) {
|
||||
Osd::CpuEvaluator::EvalPatches(g_varyingData, g_idesc,
|
||||
g_Q, g_vdesc,
|
||||
g_patchCoords,
|
||||
g_patchTables, NULL);
|
||||
if (g_drawMode == kNORMAL || g_drawMode == kSHADE) {
|
||||
// evaluate positions and derivatives
|
||||
g_nsamplesFound = Osd::CpuEvaluator::EvalPatches(
|
||||
g_vertexData, g_idesc,
|
||||
g_outVertexData, g_odesc,
|
||||
g_outDerivatives, g_duDesc,
|
||||
g_outDerivatives, g_dvDesc,
|
||||
(int)g_patchCoords.size(),
|
||||
&g_patchCoords[0],
|
||||
g_patchTable, NULL);
|
||||
} else {
|
||||
// evaluate positions
|
||||
g_nsamplesFound = Osd::CpuEvaluator::EvalPatches(
|
||||
g_vertexData, g_idesc,
|
||||
g_outVertexData, g_odesc,
|
||||
(int)g_patchCoords.size(),
|
||||
&g_patchCoords[0],
|
||||
g_patchTable, NULL);
|
||||
}
|
||||
|
||||
g_Q->BindVBO();
|
||||
// color
|
||||
if (g_drawMode == kUV) {
|
||||
// store patchCoords as colors
|
||||
float *p = g_outVertexData->BindCpuBuffer() + g_vdesc.offset;
|
||||
for (int i = 0; i < (int)g_patchCoords.size(); ++i) {
|
||||
p[0] = g_patchCoords[i].s;
|
||||
p[1] = g_patchCoords[i].t;
|
||||
p[2] = 0;
|
||||
p += g_vdesc.stride;
|
||||
}
|
||||
} else if (g_drawMode == kVARYING) {
|
||||
// XXX: is this really varying?
|
||||
Osd::CpuEvaluator::EvalPatches(g_varyingData, g_idesc,
|
||||
g_outVertexData, g_vdesc,
|
||||
(int)g_patchCoords.size(),
|
||||
&g_patchCoords[0],
|
||||
g_patchTable, NULL);
|
||||
}
|
||||
|
||||
s.Stop();
|
||||
|
||||
@ -349,46 +388,46 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Far::TopologyRefiner::AdaptiveOptions options(level);
|
||||
g_topologyRefiner->RefineAdaptive(options);
|
||||
|
||||
// Generate stencil tables to update the bi-cubic patches control
|
||||
// Generate stencil table to update the bi-cubic patches control
|
||||
// vertices after they have been re-posed (both for vertex & varying
|
||||
// interpolation)
|
||||
Far::StencilTablesFactory::Options soptions;
|
||||
Far::StencilTableFactory::Options soptions;
|
||||
soptions.generateOffsets=true;
|
||||
soptions.generateIntermediateLevels=true;
|
||||
|
||||
Far::StencilTables const * vertexStencils =
|
||||
Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions);
|
||||
Far::StencilTable const * vertexStencils =
|
||||
Far::StencilTableFactory::Create(*g_topologyRefiner, soptions);
|
||||
|
||||
soptions.interpolationMode = Far::StencilTablesFactory::INTERPOLATE_VARYING;
|
||||
Far::StencilTables const * varyingStencils =
|
||||
Far::StencilTablesFactory::Create(*g_topologyRefiner, soptions);
|
||||
soptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_VARYING;
|
||||
Far::StencilTable const * varyingStencils =
|
||||
Far::StencilTableFactory::Create(*g_topologyRefiner, soptions);
|
||||
|
||||
// Generate bi-cubic patch tables for the limit surface
|
||||
Far::PatchTablesFactory::Options poptions;
|
||||
// Generate bi-cubic patch table for the limit surface
|
||||
Far::PatchTableFactory::Options poptions;
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
|
||||
Far::PatchTables const * patchTables =
|
||||
Far::PatchTablesFactory::Create(*g_topologyRefiner, poptions);
|
||||
Far::PatchTable const * patchTable =
|
||||
Far::PatchTableFactory::Create(*g_topologyRefiner, poptions);
|
||||
|
||||
// append endcap stencils
|
||||
if (Far::StencilTables const *endCapVertexStencilTables =
|
||||
patchTables->GetEndCapVertexStencilTables()) {
|
||||
Far::StencilTables const *tables =
|
||||
Far::StencilTablesFactory::AppendEndCapStencilTables(
|
||||
if (Far::StencilTable const *endCapVertexStencilTable =
|
||||
patchTable->GetEndCapVertexStencilTable()) {
|
||||
Far::StencilTable const *table =
|
||||
Far::StencilTableFactory::AppendEndCapStencilTable(
|
||||
*g_topologyRefiner,
|
||||
vertexStencils, endCapVertexStencilTables);
|
||||
vertexStencils, endCapVertexStencilTable);
|
||||
delete vertexStencils;
|
||||
vertexStencils = tables;
|
||||
vertexStencils = table;
|
||||
}
|
||||
if (Far::StencilTables const *endCapVaryingStencilTables =
|
||||
patchTables->GetEndCapVaryingStencilTables()) {
|
||||
Far::StencilTables const *tables =
|
||||
Far::StencilTablesFactory::AppendEndCapStencilTables(
|
||||
if (Far::StencilTable const *endCapVaryingStencilTable =
|
||||
patchTable->GetEndCapVaryingStencilTable()) {
|
||||
Far::StencilTable const *table =
|
||||
Far::StencilTableFactory::AppendEndCapStencilTable(
|
||||
*g_topologyRefiner,
|
||||
varyingStencils, endCapVaryingStencilTables);
|
||||
varyingStencils, endCapVaryingStencilTable);
|
||||
delete varyingStencils;
|
||||
varyingStencils = tables;
|
||||
varyingStencils = table;
|
||||
}
|
||||
|
||||
// total number of vertices = coarse verts + refined verts + gregory basis verts
|
||||
@ -400,12 +439,12 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
if (g_varyingStencils) delete g_varyingStencils;
|
||||
g_varyingStencils = varyingStencils;
|
||||
|
||||
if (g_patchTables) delete g_patchTables;
|
||||
g_patchTables = patchTables;
|
||||
if (g_patchTable) delete g_patchTable;
|
||||
g_patchTable = patchTable;
|
||||
|
||||
// Create a far patch map
|
||||
if (g_patchMap) delete g_patchMap;
|
||||
g_patchMap = new Far::PatchMap(*g_patchTables);
|
||||
g_patchMap = new Far::PatchMap(*g_patchTable);
|
||||
}
|
||||
|
||||
{ // Create vertex primvar buffer for the CVs
|
||||
@ -422,45 +461,22 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
}
|
||||
|
||||
// Create output buffers for the limit samples (position & tangents)
|
||||
delete g_Q;
|
||||
g_Q = Osd::CpuGLVertexBuffer::Create(6, g_nparticles);
|
||||
memset( g_Q->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float));
|
||||
delete g_outVertexData;
|
||||
g_outVertexData = Osd::CpuGLVertexBuffer::Create(6, g_nparticles);
|
||||
memset(g_outVertexData->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float));
|
||||
if (g_drawMode==kRANDOM) {
|
||||
createRandomColors(g_nparticles, 6, g_Q->BindCpuBuffer()+3);
|
||||
createRandomColors(g_nparticles, 6, g_outVertexData->BindCpuBuffer()+3);
|
||||
}
|
||||
|
||||
delete g_dQs;
|
||||
g_dQs = Osd::CpuGLVertexBuffer::Create(3,g_nparticles);
|
||||
memset( g_dQs->BindCpuBuffer(), 0, g_nparticles*3*sizeof(float));
|
||||
|
||||
delete g_dQt;
|
||||
g_dQt = Osd::CpuGLVertexBuffer::Create(3,g_nparticles);
|
||||
memset( g_dQt->BindCpuBuffer(), 0, g_nparticles*3*sizeof(float));
|
||||
delete g_outDerivatives;
|
||||
g_outDerivatives = Osd::CpuGLVertexBuffer::Create(6, g_nparticles);
|
||||
memset(g_outDerivatives->BindCpuBuffer(), 0, g_nparticles*6*sizeof(float));
|
||||
}
|
||||
|
||||
updateGeom();
|
||||
|
||||
// Bind g_Q as a GL_POINTS VBO
|
||||
glBindVertexArray(g_samplesVAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_Q->BindVBO());
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct Program {
|
||||
GLuint program;
|
||||
GLuint uniformModelViewProjectionMatrix;
|
||||
GLuint attrPosition;
|
||||
GLuint attrColor;
|
||||
} g_defaultProgram;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
checkGLErrors(std::string const & where = "") {
|
||||
@ -473,16 +489,6 @@ checkGLErrors(std::string const & where = "") {
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static GLuint
|
||||
compileShader(GLenum shaderType, const char *source) {
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
checkGLErrors("compileShader");
|
||||
return shader;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool
|
||||
linkDefaultProgram() {
|
||||
@ -497,31 +503,47 @@ linkDefaultProgram() {
|
||||
GLSL_VERSION_DEFINE
|
||||
"in vec3 position;\n"
|
||||
"in vec3 color;\n"
|
||||
"in vec3 tangentU;\n"
|
||||
"in vec3 tangentV;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"uniform mat4 ModelViewProjectionMatrix;\n"
|
||||
"out vec3 normal;\n"
|
||||
"uniform mat4 ModelViewMatrix;\n"
|
||||
"uniform mat4 ProjectionMatrix;\n"
|
||||
"void main() {\n"
|
||||
" fragColor = vec4(color, 1);\n"
|
||||
" gl_Position = ModelViewProjectionMatrix * "
|
||||
// XXX: fix the normal transform
|
||||
" normal = (ModelViewMatrix * vec4(normalize(cross(tangentU, tangentV)), 0)).xyz;\n"
|
||||
" gl_Position = ProjectionMatrix * ModelViewMatrix * "
|
||||
" vec4(position, 1);\n"
|
||||
"}\n";
|
||||
|
||||
static const char *fsSrc =
|
||||
GLSL_VERSION_DEFINE
|
||||
"in vec4 fragColor;\n"
|
||||
"in vec3 normal;\n"
|
||||
"uniform int DrawMode;\n"
|
||||
"out vec4 color;\n"
|
||||
"void main() {\n"
|
||||
" color = fragColor;\n"
|
||||
" if (DrawMode == 3) {\n"
|
||||
" color = vec4(normal*0.5+vec3(0.5), 1);\n"
|
||||
" } else if (DrawMode == 4) {\n"
|
||||
" color = vec4(vec3(1)*dot(normal, vec3(0,0,1)), 1);\n"
|
||||
" } else {\n"
|
||||
" color = fragColor;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vsSrc);
|
||||
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fsSrc);
|
||||
GLuint vertexShader = GLUtils::CompileShader(GL_VERTEX_SHADER, vsSrc);
|
||||
GLuint fragmentShader = GLUtils::CompileShader(GL_FRAGMENT_SHADER, fsSrc);
|
||||
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
|
||||
glBindAttribLocation(program, 0, "position");
|
||||
glBindAttribLocation(program, 1, "color");
|
||||
glBindAttribLocation(program, 2, "tangentU");
|
||||
glBindAttribLocation(program, 3, "tangentV");
|
||||
glBindFragDataLocation(program, 0, "color");
|
||||
|
||||
glLinkProgram(program);
|
||||
@ -539,10 +561,16 @@ linkDefaultProgram() {
|
||||
}
|
||||
|
||||
g_defaultProgram.program = program;
|
||||
g_defaultProgram.uniformModelViewProjectionMatrix =
|
||||
glGetUniformLocation(program, "ModelViewProjectionMatrix");
|
||||
g_defaultProgram.uniformModelViewMatrix =
|
||||
glGetUniformLocation(program, "ModelViewMatrix");
|
||||
g_defaultProgram.uniformProjectionMatrix =
|
||||
glGetUniformLocation(program, "ProjectionMatrix");
|
||||
g_defaultProgram.uniformDrawMode =
|
||||
glGetUniformLocation(program, "DrawMode");
|
||||
g_defaultProgram.attrPosition = glGetAttribLocation(program, "position");
|
||||
g_defaultProgram.attrColor = glGetAttribLocation(program, "color");
|
||||
g_defaultProgram.attrTangentU = glGetAttribLocation(program, "tangentU");
|
||||
g_defaultProgram.attrTangentV = glGetAttribLocation(program, "tangentV");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -562,8 +590,11 @@ static void
|
||||
drawCageEdges() {
|
||||
|
||||
glUseProgram(g_defaultProgram.program);
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix,
|
||||
1, GL_FALSE, g_transformData.ModelViewProjectionMatrix);
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix,
|
||||
1, GL_FALSE, g_transformData.ModelViewMatrix);
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix,
|
||||
1, GL_FALSE, g_transformData.ProjectionMatrix);
|
||||
glUniform1i(g_defaultProgram.uniformDrawMode, 0);
|
||||
|
||||
std::vector<float> vbo;
|
||||
vbo.reserve(g_coarseEdges.size() * 6);
|
||||
@ -588,6 +619,8 @@ drawCageEdges() {
|
||||
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrPosition);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrColor);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
glVertexAttribPointer(g_defaultProgram.attrPosition,
|
||||
3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
glVertexAttribPointer(g_defaultProgram.attrColor,
|
||||
@ -604,8 +637,11 @@ static void
|
||||
drawCageVertices() {
|
||||
|
||||
glUseProgram(g_defaultProgram.program);
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix,
|
||||
1, GL_FALSE, g_transformData.ModelViewProjectionMatrix);
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix,
|
||||
1, GL_FALSE, g_transformData.ModelViewMatrix);
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix,
|
||||
1, GL_FALSE, g_transformData.ProjectionMatrix);
|
||||
glUniform1i(g_defaultProgram.uniformDrawMode, 0);
|
||||
|
||||
int numPoints = (int)g_positions.size()/3;
|
||||
std::vector<float> vbo;
|
||||
@ -642,6 +678,8 @@ drawCageVertices() {
|
||||
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrPosition);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrColor);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
glVertexAttribPointer(g_defaultProgram.attrPosition,
|
||||
3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
glVertexAttribPointer(g_defaultProgram.attrColor,
|
||||
@ -658,19 +696,43 @@ drawCageVertices() {
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
drawSamples() {
|
||||
|
||||
glUseProgram(g_defaultProgram.program);
|
||||
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix,
|
||||
1, GL_FALSE, g_transformData.ModelViewProjectionMatrix);
|
||||
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix,
|
||||
1, GL_FALSE, g_transformData.ModelViewMatrix);
|
||||
glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix,
|
||||
1, GL_FALSE, g_transformData.ProjectionMatrix);
|
||||
glUniform1i(g_defaultProgram.uniformDrawMode, g_drawMode);
|
||||
|
||||
glBindVertexArray(g_samplesVAO);
|
||||
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrPosition);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrColor);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_outVertexData->BindVBO());
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_outDerivatives->BindVBO());
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (float*)12);
|
||||
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrPosition);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrColor);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
|
||||
glPointSize(2.0f);
|
||||
glDrawArrays(GL_POINTS, 0, g_nparticles);
|
||||
glPointSize(1.0f);
|
||||
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrPosition);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrColor);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
glUseProgram(0);
|
||||
@ -728,7 +790,8 @@ display() {
|
||||
g_fpsTimer.Start();
|
||||
|
||||
g_hud.DrawString(10, -150, "Particle Speed ([) (]): %.1f", g_particles->GetSpeed());
|
||||
g_hud.DrawString(10, -120, "# Samples : (%d/%d)", g_nsamplesFound, g_Q->GetNumVertices());
|
||||
g_hud.DrawString(10, -120, "# Samples : (%d/%d)",
|
||||
g_nsamplesFound, g_outVertexData->GetNumVertices());
|
||||
g_hud.DrawString(10, -100, "Compute : %.3f ms", g_computeTime);
|
||||
g_hud.DrawString(10, -80, "Eval : %.3f ms", g_evalTime * 1000.f);
|
||||
g_hud.DrawString(10, -60, "GPU Draw : %.3f ms", drawGpuTime);
|
||||
@ -944,6 +1007,8 @@ initHUD() {
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Random", kRANDOM, g_drawMode==kRANDOM);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "(u,v)", kUV, g_drawMode==kUV);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Varying", kVARYING, g_drawMode==kVARYING);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Normal", kNORMAL, g_drawMode==kNORMAL);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Shade", kSHADE, g_drawMode==kSHADE);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "FaceVarying", kFACEVARYING, g_drawMode==kFACEVARYING);
|
||||
|
||||
for (int i = 1; i < 11; ++i) {
|
||||
|
@ -70,14 +70,15 @@ STParticles::STParticles(Refiner const & refiner, int nparticles, bool centered)
|
||||
{ // initialize topology adjacency
|
||||
_adjacency.resize(nptexfaces);
|
||||
|
||||
int nfaces = refiner.GetNumFaces(0),
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
|
||||
|
||||
int nfaces = refBaseLevel.GetNumFaces(),
|
||||
adjfaces[4],
|
||||
adjedges[4];
|
||||
|
||||
for (int face=0, ptexface=0; face<nfaces; ++face) {
|
||||
|
||||
OpenSubdiv::Far::ConstIndexArray fverts =
|
||||
refiner.GetFaceVertices(0, face);
|
||||
OpenSubdiv::Far::ConstIndexArray fverts = refBaseLevel.GetFaceVertices(face);
|
||||
|
||||
if (fverts.size()==4) {
|
||||
ptexIndices.GetAdjacency(refiner, face, 0, adjfaces, adjedges);
|
||||
|
@ -167,11 +167,11 @@ struct FVarData
|
||||
glDeleteTextures(1, &textureBuffer);
|
||||
textureBuffer = 0;
|
||||
}
|
||||
void Create(OpenSubdiv::Far::PatchTables const *patchTables,
|
||||
void Create(OpenSubdiv::Far::PatchTable const *patchTable,
|
||||
int fvarWidth, std::vector<float> const & fvarSrcData) {
|
||||
Release();
|
||||
OpenSubdiv::Far::ConstIndexArray indices =
|
||||
patchTables->GetFVarPatchesValues(0);
|
||||
patchTable->GetFVarPatchesValues(0);
|
||||
|
||||
// expand fvardata to per-patch array
|
||||
std::vector<float> data;
|
||||
@ -280,13 +280,15 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
|
||||
|
||||
// calc normal vectors
|
||||
int nverts = (int)pos.size()/3;
|
||||
|
||||
int nfaces = refiner.GetNumFaces(0);
|
||||
int nfaces = refBaseLevel.GetNumFaces();
|
||||
for (int face = 0; face < nfaces; ++face) {
|
||||
|
||||
IndexArray fverts = refiner.GetFaceVertices(0, face);
|
||||
IndexArray fverts = refBaseLevel.GetFaceVertices(face);
|
||||
|
||||
assert(fverts.size()>=2);
|
||||
|
||||
@ -366,22 +368,23 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark)
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
int nedges = refiner->GetNumEdges(0),
|
||||
nverts = refiner->GetNumVertices(0);
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
int nedges = refBaseLevel.GetNumEdges(),
|
||||
nverts = refBaseLevel.GetNumVertices();
|
||||
|
||||
g_coarseEdges.resize(nedges*2);
|
||||
g_coarseEdgeSharpness.resize(nedges);
|
||||
g_coarseVertexSharpness.resize(nverts);
|
||||
|
||||
for(int i=0; i<nedges; ++i) {
|
||||
IndexArray verts = refiner->GetEdgeVertices(0, i);
|
||||
IndexArray verts = refBaseLevel.GetEdgeVertices(i);
|
||||
g_coarseEdges[i*2 ]=verts[0];
|
||||
g_coarseEdges[i*2+1]=verts[1];
|
||||
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i);
|
||||
g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
|
||||
}
|
||||
|
||||
for(int i=0; i<nverts; ++i) {
|
||||
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i);
|
||||
g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
|
||||
}
|
||||
|
||||
g_orgPositions=shape->verts;
|
||||
@ -404,7 +407,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark)
|
||||
|
||||
delete g_mesh;
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Far::StencilTable,
|
||||
OpenSubdiv::Osd::CpuEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -417,7 +420,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark)
|
||||
InterpolateFVarData(*refiner, *shape, fvarData);
|
||||
|
||||
// set fvardata to texture buffer
|
||||
g_fvarData.Create(g_mesh->GetFarPatchTables(),
|
||||
g_fvarData.Create(g_mesh->GetFarPatchTable(),
|
||||
shape->GetFVarWidth(), fvarData);
|
||||
|
||||
delete shape;
|
||||
|
@ -232,7 +232,7 @@ createOsdMesh(std::string const &kernel,
|
||||
{
|
||||
if (kernel == "CPU") {
|
||||
return new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -242,7 +242,7 @@ createOsdMesh(std::string const &kernel,
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == "OPENMP") {
|
||||
return new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -253,7 +253,7 @@ createOsdMesh(std::string const &kernel,
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == "TBB") {
|
||||
return new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -264,7 +264,7 @@ createOsdMesh(std::string const &kernel,
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if(kernel == "CL") {
|
||||
return new Osd::Mesh<Osd::CLGLVertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLStencilTable,
|
||||
Osd::CLEvaluator,
|
||||
Osd::GLPatchTable,
|
||||
CLDeviceContext>(
|
||||
@ -278,7 +278,7 @@ createOsdMesh(std::string const &kernel,
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if(kernel == "CUDA") {
|
||||
return new Osd::Mesh<Osd::CudaGLVertexBuffer,
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaStencilTable,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -289,7 +289,7 @@ createOsdMesh(std::string const &kernel,
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
} else if(kernel == "XFB") {
|
||||
return new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesTBO,
|
||||
Osd::GLStencilTableTBO,
|
||||
Osd::GLXFBEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -300,7 +300,7 @@ createOsdMesh(std::string const &kernel,
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
} else if(kernel == "GLSL") {
|
||||
return new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesSSBO,
|
||||
Osd::GLStencilTableSSBO,
|
||||
Osd::GLComputeEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
|
@ -238,7 +238,7 @@ createOsdMesh() {
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
||||
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Far::StencilTable,
|
||||
OpenSubdiv::Osd::CpuEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner, 3, 0, g_level, bits);
|
||||
|
@ -322,13 +322,15 @@ calcNormals(OpenSubdiv::Far::TopologyRefiner * refiner,
|
||||
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
|
||||
// calc normal vectors
|
||||
int nverts = refiner->GetNumVertices(0),
|
||||
nfaces = refiner->GetNumFaces(0);
|
||||
int nverts = refBaseLevel.GetNumVertices(),
|
||||
nfaces = refBaseLevel.GetNumFaces();
|
||||
|
||||
for (int face = 0; face < nfaces; ++face) {
|
||||
|
||||
IndexArray fverts = refiner->GetFaceVertices(0, face);
|
||||
IndexArray fverts = refBaseLevel.GetFaceVertices(face);
|
||||
|
||||
float const * p0 = &pos[fverts[0]*3],
|
||||
* p1 = &pos[fverts[1]*3],
|
||||
@ -907,10 +909,12 @@ createOsdMesh(int level, int kernel) {
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
|
||||
// create cage edge index
|
||||
int nedges = refiner->GetNumEdges(0);
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
|
||||
int nedges = refBaseLevel.GetNumEdges();
|
||||
std::vector<int> edgeIndices(nedges*2);
|
||||
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+1]=verts[1];
|
||||
}
|
||||
@ -935,7 +939,7 @@ createOsdMesh(int level, int kernel) {
|
||||
|
||||
if (kernel == kCPU) {
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Far::StencilTable,
|
||||
OpenSubdiv::Osd::CpuEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -945,7 +949,7 @@ createOsdMesh(int level, int kernel) {
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Far::StencilTable,
|
||||
OpenSubdiv::Osd::OmpEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -956,7 +960,7 @@ createOsdMesh(int level, int kernel) {
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Far::StencilTable,
|
||||
OpenSubdiv::Osd::TbbEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -968,7 +972,7 @@ createOsdMesh(int level, int kernel) {
|
||||
} else if (kernel == kCL) {
|
||||
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CLGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CLStencilTables,
|
||||
OpenSubdiv::Osd::CLStencilTable,
|
||||
OpenSubdiv::Osd::CLEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable,
|
||||
CLDeviceContext>(
|
||||
@ -982,7 +986,7 @@ createOsdMesh(int level, int kernel) {
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (kernel == kCUDA) {
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CudaGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CudaStencilTables,
|
||||
OpenSubdiv::Osd::CudaStencilTable,
|
||||
OpenSubdiv::Osd::CudaEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -994,7 +998,7 @@ createOsdMesh(int level, int kernel) {
|
||||
} else if (kernel == kGLSL) {
|
||||
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLXFBEvaluator> glXFBEvaluatorCache;
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
|
||||
OpenSubdiv::Osd::GLStencilTablesTBO,
|
||||
OpenSubdiv::Osd::GLStencilTableTBO,
|
||||
OpenSubdiv::Osd::GLXFBEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -1007,7 +1011,7 @@ createOsdMesh(int level, int kernel) {
|
||||
} else if (kernel == kGLSLCompute) {
|
||||
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLComputeEvaluator> glComputeEvaluatorCache;
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
|
||||
OpenSubdiv::Osd::GLStencilTablesSSBO,
|
||||
OpenSubdiv::Osd::GLStencilTableSSBO,
|
||||
OpenSubdiv::Osd::GLComputeEvaluator,
|
||||
OpenSubdiv::Osd::GLPatchTable>(
|
||||
refiner,
|
||||
|
@ -43,7 +43,7 @@ GLFWwindow* g_window=0;
|
||||
GLFWmonitor* g_primary=0;
|
||||
|
||||
#include <far/error.h>
|
||||
#include <far/stencilTables.h>
|
||||
#include <far/stencilTable.h>
|
||||
#include <far/ptexIndices.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
@ -891,31 +891,31 @@ rebuildTopology() {
|
||||
if (g_kernel == kCPU) {
|
||||
g_scene = new Scene<Osd::CpuEvaluator,
|
||||
Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables>(g_options);
|
||||
Far::StencilTable>(g_options);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (g_kernel == kOPENMP) {
|
||||
g_scene = new Scene<Osd::OmpEvaluator,
|
||||
Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables>(g_options);
|
||||
Far::StencilTable>(g_options);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (g_kernel == kTBB) {
|
||||
g_scene = new Scene<Osd::TbbEvaluator,
|
||||
Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables>(g_options);
|
||||
Far::StencilTable>(g_options);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (g_kernel == kCUDA) {
|
||||
g_scene = new Scene<Osd::CudaEvaluator,
|
||||
Osd::CudaGLVertexBuffer,
|
||||
Osd::CudaStencilTables>(g_options);
|
||||
Osd::CudaStencilTable>(g_options);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (g_kernel == kCL) {
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_scene = new Scene<Osd::CLEvaluator,
|
||||
Osd::CLGLVertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLStencilTable,
|
||||
CLDeviceContext>(g_options, &clEvaluatorCache,
|
||||
&g_clDeviceContext);
|
||||
#endif
|
||||
@ -924,14 +924,14 @@ rebuildTopology() {
|
||||
static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
|
||||
g_scene = new Scene<Osd::GLXFBEvaluator,
|
||||
Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesTBO>(g_options, &glXFBEvaluatorCache);
|
||||
Osd::GLStencilTableTBO>(g_options, &glXFBEvaluatorCache);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
} else if (g_kernel == kGLSLCompute) {
|
||||
static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
|
||||
g_scene = new Scene<Osd::GLComputeEvaluator,
|
||||
Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesSSBO>(g_options, &glComputeEvaluatorCache);
|
||||
Osd::GLStencilTableSSBO>(g_options, &glComputeEvaluatorCache);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -29,17 +29,17 @@
|
||||
|
||||
template <class EVALUATOR,
|
||||
class VERTEX_BUFFER,
|
||||
class STENCIL_TABLES,
|
||||
class STENCIL_TABLE,
|
||||
class DEVICE_CONTEXT=void>
|
||||
class MeshRefiner {
|
||||
public:
|
||||
typedef EVALUATOR Evaluator;
|
||||
typedef STENCIL_TABLES StencilTables;
|
||||
typedef STENCIL_TABLE StencilTable;
|
||||
typedef DEVICE_CONTEXT DeviceContext;
|
||||
typedef OpenSubdiv::Osd::EvaluatorCacheT<Evaluator> EvaluatorCache;
|
||||
|
||||
MeshRefiner(OpenSubdiv::Far::StencilTables const * vertexStencils, //XXX: takes ownership
|
||||
OpenSubdiv::Far::StencilTables const * varyingStencils,
|
||||
MeshRefiner(OpenSubdiv::Far::StencilTable const * vertexStencils, //XXX: takes ownership
|
||||
OpenSubdiv::Far::StencilTable const * varyingStencils,
|
||||
int numControlVertices,
|
||||
EvaluatorCache * evaluatorCache = NULL,
|
||||
DeviceContext * deviceContext = NULL)
|
||||
@ -49,9 +49,9 @@ public:
|
||||
_numControlVertices = numControlVertices;
|
||||
_numVertices = numControlVertices + vertexStencils->GetNumStencils();
|
||||
|
||||
_vertexStencils = OpenSubdiv::Osd::convertToCompatibleStencilTables<StencilTables>(
|
||||
_vertexStencils = OpenSubdiv::Osd::convertToCompatibleStencilTable<StencilTable>(
|
||||
vertexStencils, deviceContext);
|
||||
_varyingStencils = OpenSubdiv::Osd::convertToCompatibleStencilTables<StencilTables>(
|
||||
_varyingStencils = OpenSubdiv::Osd::convertToCompatibleStencilTable<StencilTable>(
|
||||
varyingStencils, deviceContext);
|
||||
}
|
||||
|
||||
@ -137,8 +137,8 @@ private:
|
||||
int _numVertices;
|
||||
int _numControlVertices;
|
||||
|
||||
StencilTables const *_vertexStencils;
|
||||
StencilTables const *_varyingStencils;
|
||||
StencilTable const *_vertexStencils;
|
||||
StencilTable const *_varyingStencils;
|
||||
EvaluatorCache * _evaluatorCache;
|
||||
DeviceContext *_deviceContext;
|
||||
};
|
||||
|
@ -91,8 +91,8 @@ public:
|
||||
}
|
||||
|
||||
virtual size_t createMeshRefiner(
|
||||
OpenSubdiv::Far::StencilTables const * vertexStencils,
|
||||
OpenSubdiv::Far::StencilTables const * varyingStencils,
|
||||
OpenSubdiv::Far::StencilTable const * vertexStencils,
|
||||
OpenSubdiv::Far::StencilTable const * varyingStencils,
|
||||
int numControlVertices) {
|
||||
|
||||
MeshRefinerType *meshRefiner =
|
||||
|
@ -24,8 +24,8 @@
|
||||
|
||||
#include <limits>
|
||||
#include <common/vtr_utils.h>
|
||||
#include <far/patchTablesFactory.h>
|
||||
#include <far/stencilTablesFactory.h>
|
||||
#include <far/patchTableFactory.h>
|
||||
#include <far/stencilTableFactory.h>
|
||||
#include "sceneBase.h"
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
@ -47,7 +47,7 @@ SceneBase::~SceneBase() {
|
||||
|
||||
void
|
||||
SceneBase::AddTopology(Shape const *shape, int level, bool varying) {
|
||||
Far::PatchTables const * patchTable = NULL;
|
||||
Far::PatchTable const * patchTable = NULL;
|
||||
int numVerts = createStencilTable(shape, level, varying, &patchTable);
|
||||
|
||||
// centering rest position
|
||||
@ -92,7 +92,7 @@ SceneBase::AddTopology(Shape const *shape, int level, bool varying) {
|
||||
|
||||
int
|
||||
SceneBase::createStencilTable(Shape const *shape, int level, bool varying,
|
||||
OpenSubdiv::Far::PatchTables const **patchTablesOut) {
|
||||
OpenSubdiv::Far::PatchTable const **patchTableOut) {
|
||||
|
||||
Far::TopologyRefiner * refiner = 0;
|
||||
{
|
||||
@ -115,61 +115,61 @@ SceneBase::createStencilTable(Shape const *shape, int level, bool varying,
|
||||
refiner->RefineUniform(options);
|
||||
}
|
||||
|
||||
Far::StencilTables const * vertexStencils=0, * varyingStencils=0;
|
||||
Far::StencilTable const * vertexStencils=0, * varyingStencils=0;
|
||||
{
|
||||
Far::StencilTablesFactory::Options options;
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateOffsets = true;
|
||||
options.generateIntermediateLevels = _options.adaptive;
|
||||
|
||||
vertexStencils = Far::StencilTablesFactory::Create(*refiner, options);
|
||||
vertexStencils = Far::StencilTableFactory::Create(*refiner, options);
|
||||
|
||||
if (varying) {
|
||||
varyingStencils = Far::StencilTablesFactory::Create(*refiner, options);
|
||||
varyingStencils = Far::StencilTableFactory::Create(*refiner, options);
|
||||
}
|
||||
|
||||
assert(vertexStencils);
|
||||
}
|
||||
|
||||
Far::PatchTables const * patchTables = NULL;
|
||||
Far::PatchTable const * patchTable = NULL;
|
||||
{
|
||||
Far::PatchTablesFactory::Options poptions(level);
|
||||
Far::PatchTableFactory::Options poptions(level);
|
||||
if (_options.endCap == kEndCapBSplineBasis) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTablesFactory::Options::ENDCAP_BSPLINE_BASIS);
|
||||
Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
|
||||
} else {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
}
|
||||
patchTables = Far::PatchTablesFactory::Create(*refiner, poptions);
|
||||
patchTable = Far::PatchTableFactory::Create(*refiner, poptions);
|
||||
}
|
||||
*patchTablesOut = patchTables;
|
||||
*patchTableOut = patchTable;
|
||||
|
||||
// append gregory vertices into stencils
|
||||
{
|
||||
if (Far::StencilTables const *vertexStencilsWithEndCap =
|
||||
Far::StencilTablesFactory::AppendEndCapStencilTables(
|
||||
if (Far::StencilTable const *vertexStencilsWithEndCap =
|
||||
Far::StencilTableFactory::AppendEndCapStencilTable(
|
||||
*refiner,
|
||||
vertexStencils,
|
||||
patchTables->GetEndCapVertexStencilTables())) {
|
||||
patchTable->GetEndCapVertexStencilTable())) {
|
||||
delete vertexStencils;
|
||||
vertexStencils = vertexStencilsWithEndCap;
|
||||
}
|
||||
if (varyingStencils) {
|
||||
if (Far::StencilTables const *varyingStencilsWithEndCap =
|
||||
Far::StencilTablesFactory::AppendEndCapStencilTables(
|
||||
if (Far::StencilTable const *varyingStencilsWithEndCap =
|
||||
Far::StencilTableFactory::AppendEndCapStencilTable(
|
||||
*refiner,
|
||||
varyingStencils,
|
||||
patchTables->GetEndCapVaryingStencilTables())) {
|
||||
patchTable->GetEndCapVaryingStencilTable())) {
|
||||
delete varyingStencils;
|
||||
varyingStencils = varyingStencilsWithEndCap;
|
||||
}
|
||||
}
|
||||
}
|
||||
int numControlVertices = refiner->GetNumVertices(0);
|
||||
int numControlVertices = refiner->GetLevel(0).GetNumVertices();
|
||||
|
||||
_stencilTableSize = createMeshRefiner(vertexStencils, varyingStencils,
|
||||
numControlVertices);
|
||||
// note: refiner takes ownerships of vertexStencils/ varyingStencils, patchTables
|
||||
// note: refiner takes ownerships of vertexStencils/ varyingStencils, patchTable
|
||||
|
||||
delete refiner;
|
||||
return numControlVertices + vertexStencils->GetNumStencils();
|
||||
@ -214,9 +214,9 @@ SceneBase::CreateIndexBuffer() {
|
||||
|
||||
int numTopologies = (int)_topologies.size();
|
||||
for (int i = 0; i < numTopologies; ++i) {
|
||||
Far::PatchTables const *patchTables = _patchTables[i];
|
||||
Far::PatchTable const *patchTable = _patchTables[i];
|
||||
|
||||
int nPatchArrays = patchTables->GetNumPatchArrays();
|
||||
int nPatchArrays = patchTable->GetNumPatchArrays();
|
||||
|
||||
_topologies[i].patchArrays.clear();
|
||||
|
||||
@ -224,21 +224,21 @@ SceneBase::CreateIndexBuffer() {
|
||||
for (int j = 0; j < nPatchArrays; ++j) {
|
||||
|
||||
SceneBase::PatchArray patchArray;
|
||||
patchArray.desc = patchTables->GetPatchArrayDescriptor(j);
|
||||
patchArray.numPatches = patchTables->GetNumPatches(j);
|
||||
patchArray.desc = patchTable->GetPatchArrayDescriptor(j);
|
||||
patchArray.numPatches = patchTable->GetNumPatches(j);
|
||||
patchArray.indexOffset = (int)buffer.size();
|
||||
patchArray.primitiveIDOffset = (int)ppBuffer.size()/3;
|
||||
|
||||
_topologies[i].patchArrays.push_back(patchArray);
|
||||
|
||||
// indices
|
||||
Far::ConstIndexArray indices = patchTables->GetPatchArrayVertices(j);
|
||||
Far::ConstIndexArray indices = patchTable->GetPatchArrayVertices(j);
|
||||
for (int k = 0; k < indices.size(); ++k) {
|
||||
buffer.push_back(indices[k]);
|
||||
}
|
||||
|
||||
// patchParams
|
||||
Far::ConstPatchParamArray patchParams = patchTables->GetPatchParams(j);
|
||||
Far::ConstPatchParamArray patchParams = patchTable->GetPatchParams(j);
|
||||
// XXX: needs sharpness interface for patcharray or put sharpness into patchParam.
|
||||
for (int k = 0; k < patchParams.size(); ++k) {
|
||||
float sharpness = 0.0;
|
||||
@ -248,26 +248,26 @@ SceneBase::CreateIndexBuffer() {
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// XXX: we'll remove below APIs from Far::PatchTables.
|
||||
// XXX: we'll remove below APIs from Far::PatchTable.
|
||||
// use GetPatchParams(patchArray) instead as above.
|
||||
|
||||
// patch param (all in one)
|
||||
Far::PatchParamTable const &patchParamTables =
|
||||
patchTables->GetPatchParamTable();
|
||||
Far::PatchParamTable const &patchParamTable =
|
||||
patchTable->GetPatchParamTable();
|
||||
std::vector<int> const &sharpnessIndexTable =
|
||||
patchTables->GetSharpnessIndexTable();
|
||||
patchTable->GetSharpnessIndexTable();
|
||||
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) {
|
||||
float sharpness = 0.0;
|
||||
if (i < (int)sharpnessIndexTable.size()) {
|
||||
sharpness = sharpnessIndexTable[i] >= 0 ?
|
||||
sharpnessValues[sharpnessIndexTable[i]] : 0.0f;
|
||||
}
|
||||
ppBuffer.push_back(patchParamTables[i].faceIndex);
|
||||
ppBuffer.push_back(patchParamTables[i].bitField.field);
|
||||
ppBuffer.push_back(patchParamTable[i].faceIndex);
|
||||
ppBuffer.push_back(patchParamTable[i].bitField.field);
|
||||
ppBuffer.push_back(*((unsigned int *)&sharpness));
|
||||
}
|
||||
#endif
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define OPENSUBDIV_EXAMPLES_GL_SHARE_TOPOLOGY_SCENE_BASE_H
|
||||
|
||||
#include <far/patchDescriptor.h>
|
||||
#include <far/patchTables.h>
|
||||
#include <far/patchTable.h>
|
||||
#include <osd/vertexDescriptor.h>
|
||||
#include <osd/opengl.h>
|
||||
|
||||
@ -135,20 +135,20 @@ public:
|
||||
|
||||
protected:
|
||||
int createStencilTable(Shape const *shape, int level, bool varying,
|
||||
OpenSubdiv::Far::PatchTables const **patchTableOut);
|
||||
OpenSubdiv::Far::PatchTable const **patchTableOut);
|
||||
|
||||
void buildBatches();
|
||||
|
||||
virtual size_t createMeshRefiner(
|
||||
OpenSubdiv::Far::StencilTables const * vertexStencils,
|
||||
OpenSubdiv::Far::StencilTables const * varyingStencils,
|
||||
OpenSubdiv::Far::StencilTable const * vertexStencils,
|
||||
OpenSubdiv::Far::StencilTable const * varyingStencils,
|
||||
int numControlVertices) = 0;
|
||||
|
||||
Options _options;
|
||||
|
||||
std::vector<Object> _objects;
|
||||
std::vector<Topology> _topologies;
|
||||
std::vector<OpenSubdiv::Far::PatchTables const *> _patchTables;
|
||||
std::vector<OpenSubdiv::Far::PatchTable const *> _patchTables;
|
||||
GLuint _indexBuffer;
|
||||
GLuint _patchParamTexture;
|
||||
BatchVector _batches;
|
||||
|
@ -48,9 +48,9 @@ GLFWmonitor* g_primary=0;
|
||||
#include "../common/glUtils.h"
|
||||
#include "../common/glHud.h"
|
||||
|
||||
#include <far/patchTablesFactory.h>
|
||||
#include <far/patchTableFactory.h>
|
||||
#include <far/ptexIndices.h>
|
||||
#include <far/stencilTablesFactory.h>
|
||||
#include <far/stencilTableFactory.h>
|
||||
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
@ -136,7 +136,7 @@ GLhud g_hud;
|
||||
int g_currentShape = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Far::LimitStencilTables const * g_controlStencils;
|
||||
Far::LimitStencilTable const * g_controlStencils;
|
||||
|
||||
// Control vertex positions (P(xyz))
|
||||
Osd::CpuVertexBuffer * g_controlValues=0;
|
||||
@ -271,7 +271,7 @@ static void
|
||||
createMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
|
||||
typedef Far::ConstIndexArray IndexArray;
|
||||
typedef Far::LimitStencilTablesFactory::LocationArray LocationArray;
|
||||
typedef Far::LimitStencilTableFactory::LocationArray LocationArray;
|
||||
|
||||
Shape const * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme);
|
||||
|
||||
@ -284,22 +284,24 @@ createMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
int nedges = refiner->GetNumEdges(0),
|
||||
nverts = refiner->GetNumVertices(0);
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
|
||||
int nedges = refBaseLevel.GetNumEdges(),
|
||||
nverts = refBaseLevel.GetNumVertices();
|
||||
|
||||
g_coarseEdges.resize(nedges*2);
|
||||
g_coarseEdgeSharpness.resize(nedges);
|
||||
g_coarseVertexSharpness.resize(nverts);
|
||||
|
||||
for(int i=0; i<nedges; ++i) {
|
||||
IndexArray verts = refiner->GetEdgeVertices(0, i);
|
||||
IndexArray verts = refBaseLevel.GetEdgeVertices(i);
|
||||
g_coarseEdges[i*2 ]=verts[0];
|
||||
g_coarseEdges[i*2+1]=verts[1];
|
||||
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i);
|
||||
g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
|
||||
}
|
||||
|
||||
for(int i=0; i<nverts; ++i) {
|
||||
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i);
|
||||
g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
|
||||
}
|
||||
|
||||
g_orgPositions=shape->verts;
|
||||
@ -338,7 +340,7 @@ createMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
}
|
||||
|
||||
delete g_controlStencils;
|
||||
g_controlStencils = Far::LimitStencilTablesFactory::Create(*refiner, locs);
|
||||
g_controlStencils = Far::LimitStencilTableFactory::Create(*refiner, locs);
|
||||
|
||||
delete [] u;
|
||||
delete [] v;
|
||||
|
@ -283,11 +283,11 @@ struct FVarData
|
||||
glDeleteTextures(1, &textureBuffer);
|
||||
textureBuffer = 0;
|
||||
}
|
||||
void Create(OpenSubdiv::Far::PatchTables const *patchTables,
|
||||
void Create(OpenSubdiv::Far::PatchTable const *patchTable,
|
||||
int fvarWidth, std::vector<float> const & fvarSrcData) {
|
||||
Release();
|
||||
OpenSubdiv::Far::ConstIndexArray indices =
|
||||
patchTables->GetFVarPatchesValues(0);
|
||||
patchTable->GetFVarPatchesValues(0);
|
||||
|
||||
// expand fvardata to per-patch array
|
||||
std::vector<float> data;
|
||||
@ -555,22 +555,24 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
int nedges = refiner->GetNumEdges(0),
|
||||
nverts = refiner->GetNumVertices(0);
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
|
||||
int nedges = refBaseLevel.GetNumEdges(),
|
||||
nverts = refBaseLevel.GetNumVertices();
|
||||
|
||||
g_coarseEdges.resize(nedges*2);
|
||||
g_coarseEdgeSharpness.resize(nedges);
|
||||
g_coarseVertexSharpness.resize(nverts);
|
||||
|
||||
for(int i=0; i<nedges; ++i) {
|
||||
IndexArray verts = refiner->GetEdgeVertices(0, i);
|
||||
IndexArray verts = refBaseLevel.GetEdgeVertices(i);
|
||||
g_coarseEdges[i*2 ]=verts[0];
|
||||
g_coarseEdges[i*2+1]=verts[1];
|
||||
g_coarseEdgeSharpness[i]=refiner->GetEdgeSharpness(0, i);
|
||||
g_coarseEdgeSharpness[i]=refBaseLevel.GetEdgeSharpness(i);
|
||||
}
|
||||
|
||||
for(int i=0; i<nverts; ++i) {
|
||||
g_coarseVertexSharpness[i]=refiner->GetVertexSharpness(0, i);
|
||||
g_coarseVertexSharpness[i]=refBaseLevel.GetVertexSharpness(i);
|
||||
}
|
||||
|
||||
g_orgPositions=shape->verts;
|
||||
@ -602,7 +604,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
|
||||
if (kernel == kCPU) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -612,7 +614,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -623,7 +625,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Far::StencilTable,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -636,7 +638,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
// CLKernel
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::CLGLVertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLStencilTable,
|
||||
Osd::CLEvaluator,
|
||||
Osd::GLPatchTable,
|
||||
CLDeviceContext>(
|
||||
@ -650,7 +652,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if(kernel == kCUDA) {
|
||||
g_mesh = new Osd::Mesh<Osd::CudaGLVertexBuffer,
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaStencilTable,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -662,7 +664,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
} else if(kernel == kGLSL) {
|
||||
static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesTBO,
|
||||
Osd::GLStencilTableTBO,
|
||||
Osd::GLXFBEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -675,7 +677,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
} else if(kernel == kGLSLCompute) {
|
||||
static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesSSBO,
|
||||
Osd::GLStencilTableSSBO,
|
||||
Osd::GLComputeEvaluator,
|
||||
Osd::GLPatchTable>(
|
||||
refiner,
|
||||
@ -697,7 +699,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
InterpolateFVarData(*refiner, *shape, fvarData);
|
||||
|
||||
// set fvardata to texture buffer
|
||||
g_fvarData.Create(g_mesh->GetFarPatchTables(),
|
||||
g_fvarData.Create(g_mesh->GetFarPatchTable(),
|
||||
shape->GetFVarWidth(), fvarData);
|
||||
}
|
||||
|
||||
@ -706,7 +708,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
g_legacyGregoryPatchTable = NULL;
|
||||
if (g_endCap == kEndCapLegacyGregory) {
|
||||
g_legacyGregoryPatchTable =
|
||||
Osd::GLLegacyGregoryPatchTable::Create(g_mesh->GetFarPatchTables());
|
||||
Osd::GLLegacyGregoryPatchTable::Create(g_mesh->GetFarPatchTable());
|
||||
}
|
||||
|
||||
if (not doAnim) {
|
||||
@ -1320,7 +1322,7 @@ display() {
|
||||
g_mesh->GetPatchTable()->GetPatchArrays();
|
||||
|
||||
// patch drawing
|
||||
int patchCount[13]; // [Type] (see far/patchTables.h)
|
||||
int patchCount[13]; // [Type] (see far/patchTable.h)
|
||||
int numTotalPatches = 0;
|
||||
int numDrawCalls = 0;
|
||||
memset(patchCount, 0, sizeof(patchCount));
|
||||
|
@ -77,6 +77,12 @@ static std::vector<ShapeDesc> g_defaultShapes;
|
||||
#include <shapes/catmark_hole_test4.h>
|
||||
#include <shapes/catmark_lefthanded.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_pyramid_creases0.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_chaikin0.h>
|
||||
#include <shapes/loop_chaikin1.h>
|
||||
#include <shapes/loop_pole8.h>
|
||||
#include <shapes/loop_pole64.h>
|
||||
#include <shapes/loop_pole360.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void initShapes() {
|
||||
@ -145,6 +154,12 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/ ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pole8", catmark_pole8, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pole64", catmark_pole64, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pole360", catmark_pole360, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) );
|
||||
@ -177,5 +192,8 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole8", loop_pole8, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole64", loop_pole64, kLoop ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("loop_pole360", loop_pole360, kLoop ) );
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -112,6 +112,9 @@ OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float sharpness;
|
||||
#endif
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
@ -119,6 +122,9 @@ void main()
|
||||
{
|
||||
outpt.v.position = ModelViewMatrix * position;
|
||||
outpt.v.patchCoord = vec4(0);
|
||||
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
outpt.sharpness = 0;
|
||||
#endif
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@
|
||||
|
||||
// OpenSubdiv includes
|
||||
#include <far/topologyRefinerFactory.h>
|
||||
#include <far/stencilTablesFactory.h>
|
||||
#include <far/stencilTableFactory.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
@ -523,8 +523,12 @@ convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
|
||||
int maxlevel = refiner.GetMaxLevel(),
|
||||
nfaces = refiner.GetNumFaces(maxlevel);
|
||||
int maxlevel = refiner.GetMaxLevel();
|
||||
|
||||
OpenSubdiv::Far::TopologyLevel const & refLastLevel
|
||||
= refiner.GetLevel(maxlevel);
|
||||
|
||||
int nfaces = refLastLevel.GetNumFaces();
|
||||
|
||||
// Init Maya Data
|
||||
|
||||
@ -537,18 +541,18 @@ convertToMayaMeshData(OpenSubdiv::Far::TopologyRefiner const & refiner,
|
||||
// -- Face Connects
|
||||
MIntArray faceConnects(nfaces*4);
|
||||
for (int face=0, idx=0; face < nfaces; ++face) {
|
||||
IndexArray fverts = refiner.GetFaceVertices(maxlevel, face);
|
||||
IndexArray fverts = refLastLevel.GetFaceVertices(face);
|
||||
for (int vert=0; vert < fverts.size(); ++vert) {
|
||||
faceConnects[idx++] = fverts[vert];
|
||||
}
|
||||
}
|
||||
|
||||
// -- Points
|
||||
MFloatPointArray points(refiner.GetNumVertices(maxlevel));
|
||||
MFloatPointArray points(refLastLevel.GetNumVertices());
|
||||
Vertex const * v = &vertexBuffer.at(0);
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
int nverts = refiner.GetNumVertices(level);
|
||||
int nverts = refiner.GetLevel(level).GetNumVertices();
|
||||
if (level==maxlevel) {
|
||||
for (int vert=0; vert < nverts; ++vert, ++v) {
|
||||
points.set(vert, v->position[0], v->position[1], v->position[2]);
|
||||
@ -652,7 +656,7 @@ MayaPolySmooth::compute( const MPlug& plug, MDataBlock& data ) {
|
||||
reinterpret_cast<Vertex const *>(inMeshFn.getRawPoints(&status));
|
||||
|
||||
std::vector<Vertex> refinedVerts(
|
||||
refiner->GetNumVerticesTotal() - refiner->GetNumVertices(0));
|
||||
refiner->GetNumVerticesTotal() - refiner->GetLevel(0).GetNumVertices());
|
||||
|
||||
refiner->Interpolate(controlVerts, &refinedVerts.at(0));
|
||||
|
||||
@ -669,7 +673,7 @@ MayaPolySmooth::compute( const MPlug& plug, MDataBlock& data ) {
|
||||
|
||||
// Propagate objectGroups from inMesh to outMesh (for per-facet shading, etc)
|
||||
status = createSmoothMesh_objectGroups(inMeshFn, inMeshDat,
|
||||
newMeshData, subdivisionLevel, refiner->GetNumFaces(subdivisionLevel));
|
||||
newMeshData, subdivisionLevel, refiner->GetLevel(subdivisionLevel).GetNumFaces());
|
||||
|
||||
// Write to output plug
|
||||
MDataHandle outMeshH = data.outputValue(a_output, &status);
|
||||
|
@ -33,16 +33,17 @@ set(SOURCE_FILES
|
||||
patchBasis.cpp
|
||||
patchDescriptor.cpp
|
||||
patchMap.cpp
|
||||
patchTables.cpp
|
||||
patchTablesFactory.cpp
|
||||
patchTable.cpp
|
||||
patchTableFactory.cpp
|
||||
ptexIndices.cpp
|
||||
stencilTablesFactory.cpp
|
||||
stencilTableFactory.cpp
|
||||
stencilBuilder.cpp
|
||||
topologyRefiner.cpp
|
||||
topologyRefinerFactory.cpp
|
||||
)
|
||||
|
||||
set(PRIVATE_HEADER_FILES
|
||||
protoStencil.h
|
||||
stencilBuilder.h
|
||||
)
|
||||
|
||||
set(PUBLIC_HEADER_FILES
|
||||
@ -55,11 +56,11 @@ set(PUBLIC_HEADER_FILES
|
||||
patchDescriptor.h
|
||||
patchParam.h
|
||||
patchMap.h
|
||||
patchTables.h
|
||||
patchTablesFactory.h
|
||||
patchTable.h
|
||||
patchTableFactory.h
|
||||
ptexIndices.h
|
||||
stencilTables.h
|
||||
stencilTablesFactory.h
|
||||
stencilTable.h
|
||||
stencilTableFactory.h
|
||||
topologyLevel.h
|
||||
topologyRefiner.h
|
||||
topologyRefinerFactory.h
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "../far/gregoryBasis.h"
|
||||
#include "../far/endCapBSplineBasisPatchFactory.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTablesFactory.h"
|
||||
#include "../far/stencilTableFactory.h"
|
||||
#include "../far/topologyRefiner.h"
|
||||
|
||||
#include <cassert>
|
||||
|
@ -25,9 +25,8 @@
|
||||
#ifndef OPENSUBDIV3_FAR_END_CAP_BSPLINE_BASIS_PATCH_FACTORY_H
|
||||
#define OPENSUBDIV3_FAR_END_CAP_BSPLINE_BASIS_PATCH_FACTORY_H
|
||||
|
||||
#include "../far/patchTablesFactory.h"
|
||||
#include "../far/patchTableFactory.h"
|
||||
#include "../far/gregoryBasis.h"
|
||||
#include "../far/protoStencil.h"
|
||||
#include "../vtr/level.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
@ -39,7 +38,7 @@ class TopologyRefiner;
|
||||
|
||||
/// \brief A BSpline endcap factory
|
||||
///
|
||||
/// note: This is an internal use class in PatchTablesFactory, and
|
||||
/// note: This is an internal use class in PatchTableFactory, and
|
||||
/// will be replaced with SdcSchemeWorker for mask coefficients
|
||||
/// and Vtr::Level for topology traversal.
|
||||
///
|
||||
@ -70,19 +69,19 @@ public:
|
||||
ConstIndexArray GetPatchPoints(
|
||||
Vtr::Level const * level, Index faceIndex);
|
||||
|
||||
/// \brief Create a StencilTables for end patch points, relative to the max
|
||||
/// \brief Create a StencilTable for end patch points, relative to the max
|
||||
/// subdivision level.
|
||||
///
|
||||
StencilTables* CreateVertexStencilTables() const {
|
||||
return GregoryBasis::CreateStencilTables(_vertexStencils);
|
||||
StencilTable* CreateVertexStencilTable() const {
|
||||
return GregoryBasis::CreateStencilTable(_vertexStencils);
|
||||
}
|
||||
|
||||
/// \brief Create a StencilTables for end patch varying primvar.
|
||||
/// \brief Create a StencilTable for end patch varying primvar.
|
||||
/// This table is used as a convenient way to get varying primvars
|
||||
/// populated on end patch points along with positions.
|
||||
///
|
||||
StencilTables* CreateVaryingStencilTables() const {
|
||||
return GregoryBasis::CreateStencilTables(_varyingStencils);
|
||||
StencilTable* CreateVaryingStencilTable() const {
|
||||
return GregoryBasis::CreateStencilTable(_varyingStencils);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "../far/gregoryBasis.h"
|
||||
#include "../far/endCapGregoryBasisPatchFactory.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTablesFactory.h"
|
||||
#include "../far/stencilTableFactory.h"
|
||||
#include "../far/topologyRefiner.h"
|
||||
|
||||
#include <cassert>
|
||||
@ -37,21 +37,8 @@ namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
|
||||
|
||||
static inline bool
|
||||
checkMaxValence(Vtr::Level const & level) {
|
||||
if (level.getMaxValence()>EndCapGregoryBasisPatchFactory::GetMaxValence()) {
|
||||
// The proto-basis closed-form table limits valence to 'MAX_VALENCE'
|
||||
Error(FAR_RUNTIME_ERROR,
|
||||
"Vertex valence %d exceeds maximum %d supported",
|
||||
level.getMaxValence(), EndCapGregoryBasisPatchFactory::GetMaxValence());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// EndCapGregoryBasisPatchFactory for Vertex StencilTables
|
||||
// EndCapGregoryBasisPatchFactory for Vertex StencilTable
|
||||
//
|
||||
EndCapGregoryBasisPatchFactory::EndCapGregoryBasisPatchFactory(
|
||||
TopologyRefiner const & refiner, bool shareBoundaryVertices) :
|
||||
@ -62,12 +49,6 @@ EndCapGregoryBasisPatchFactory::EndCapGregoryBasisPatchFactory(
|
||||
assert(not refiner.IsUniform());
|
||||
}
|
||||
|
||||
int
|
||||
EndCapGregoryBasisPatchFactory::GetMaxValence() {
|
||||
|
||||
return GregoryBasis::MAX_VALENCE;
|
||||
}
|
||||
|
||||
//
|
||||
// Stateless EndCapGregoryBasisPatchFactory
|
||||
//
|
||||
@ -78,10 +59,6 @@ EndCapGregoryBasisPatchFactory::Create(TopologyRefiner const & refiner,
|
||||
// Gregory patches are end-caps: they only exist on max-level
|
||||
Vtr::Level const & level = refiner.getLevel(refiner.GetMaxLevel());
|
||||
|
||||
if (not checkMaxValence(level)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GregoryBasis::ProtoBasis basis(level, faceIndex, fvarChannel);
|
||||
GregoryBasis * result = new GregoryBasis;
|
||||
basis.Copy(result);
|
||||
@ -97,10 +74,6 @@ EndCapGregoryBasisPatchFactory::addPatchBasis(Index faceIndex,
|
||||
// Gregory patches only exist on the hight
|
||||
Vtr::Level const & level = _refiner->getLevel(_refiner->GetMaxLevel());
|
||||
|
||||
if (not checkMaxValence(level)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Gather the CVs that influence the Gregory patch and their relative
|
||||
// weights in a basis
|
||||
GregoryBasis::ProtoBasis basis(level, faceIndex);
|
||||
@ -139,7 +112,7 @@ EndCapGregoryBasisPatchFactory::addPatchBasis(Index faceIndex,
|
||||
ConstIndexArray
|
||||
EndCapGregoryBasisPatchFactory::GetPatchPoints(
|
||||
Vtr::Level const * level, Index faceIndex,
|
||||
PatchTablesFactory::PatchFaceTag const * levelPatchTags)
|
||||
PatchTableFactory::PatchFaceTag const * levelPatchTags)
|
||||
{
|
||||
// allocate indices (awkward)
|
||||
// assert(Vtr::INDEX_INVALID==0xFFFFFFFF);
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef OPENSUBDIV3_FAR_END_CAP_GREGORY_BASIS_PATCH_FACTORY_H
|
||||
#define OPENSUBDIV3_FAR_END_CAP_GREGORY_BASIS_PATCH_FACTORY_H
|
||||
|
||||
#include "../far/patchTablesFactory.h"
|
||||
#include "../far/patchTableFactory.h"
|
||||
#include "../far/gregoryBasis.h"
|
||||
#include "../vtr/level.h"
|
||||
|
||||
@ -38,7 +38,7 @@ class TopologyRefiner;
|
||||
|
||||
/// \brief A specialized factory to gather Gregory basis control vertices
|
||||
///
|
||||
/// note: This is an internal use class in PatchTablesFactory, and
|
||||
/// note: This is an internal use class in PatchTableFactory, and
|
||||
/// will be replaced with SdcSchemeWorker for mask coefficients
|
||||
/// and Vtr::Level for topology traversal.
|
||||
///
|
||||
@ -62,10 +62,6 @@ public:
|
||||
static GregoryBasis const * Create(TopologyRefiner const & refiner,
|
||||
Index faceIndex, int fvarChannel=-1);
|
||||
|
||||
/// \brief Returns the maximum valence of a vertex in the mesh that the
|
||||
/// Gregory patches can handle
|
||||
static int GetMaxValence();
|
||||
|
||||
public:
|
||||
|
||||
///
|
||||
@ -98,21 +94,21 @@ public:
|
||||
///
|
||||
ConstIndexArray GetPatchPoints(
|
||||
Vtr::Level const * level, Index faceIndex,
|
||||
PatchTablesFactory::PatchFaceTag const * levelPatchTags);
|
||||
PatchTableFactory::PatchFaceTag const * levelPatchTags);
|
||||
|
||||
/// \brief Create a StencilTables for end patch points, relative to the max
|
||||
/// \brief Create a StencilTable for end patch points, relative to the max
|
||||
/// subdivision level.
|
||||
///
|
||||
StencilTables* CreateVertexStencilTables() const {
|
||||
return GregoryBasis::CreateStencilTables(_vertexStencils);
|
||||
StencilTable* CreateVertexStencilTable() const {
|
||||
return GregoryBasis::CreateStencilTable(_vertexStencils);
|
||||
}
|
||||
|
||||
/// \brief Create a StencilTables for end patch varying primvar.
|
||||
/// \brief Create a StencilTable for end patch varying primvar.
|
||||
/// This table is used as a convenient way to get varying primvars
|
||||
/// populated on end patch points along with positions.
|
||||
///
|
||||
StencilTables* CreateVaryingStencilTables() const {
|
||||
return GregoryBasis::CreateStencilTables(_varyingStencils);
|
||||
StencilTable* CreateVaryingStencilTable() const {
|
||||
return GregoryBasis::CreateStencilTable(_varyingStencils);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/endCapLegacyGregoryPatchFactory.h"
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../far/topologyRefiner.h"
|
||||
#include "../vtr/level.h"
|
||||
|
||||
@ -41,10 +41,10 @@ EndCapLegacyGregoryPatchFactory::EndCapLegacyGregoryPatchFactory(
|
||||
ConstIndexArray
|
||||
EndCapLegacyGregoryPatchFactory::GetPatchPoints(
|
||||
Vtr::Level const * level, Index faceIndex,
|
||||
PatchTablesFactory::PatchFaceTag const * levelPatchTags,
|
||||
PatchTableFactory::PatchFaceTag const * levelPatchTags,
|
||||
int levelVertOffset) {
|
||||
|
||||
PatchTablesFactory::PatchFaceTag patchTag = levelPatchTags[faceIndex];
|
||||
PatchTableFactory::PatchFaceTag patchTag = levelPatchTags[faceIndex];
|
||||
|
||||
// Gregory Regular Patch (4 CVs + quad-offsets / valence tables)
|
||||
Vtr::ConstIndexArray faceVerts = level->getFaceVertices(faceIndex);
|
||||
@ -102,8 +102,8 @@ static void getQuadOffsets(
|
||||
void
|
||||
EndCapLegacyGregoryPatchFactory::Finalize(
|
||||
int maxValence,
|
||||
PatchTables::QuadOffsetsTable *quadOffsetsTable,
|
||||
PatchTables::VertexValenceTable *vertexValenceTable)
|
||||
PatchTable::QuadOffsetsTable *quadOffsetsTable,
|
||||
PatchTable::VertexValenceTable *vertexValenceTable)
|
||||
{
|
||||
// populate quad offsets
|
||||
|
||||
@ -116,18 +116,18 @@ EndCapLegacyGregoryPatchFactory::Finalize(
|
||||
|
||||
quadOffsetsTable->resize(numTotalGregoryPatches*4);
|
||||
|
||||
if (numTotalGregoryPatches > 0) {
|
||||
PatchTables::QuadOffsetsTable::value_type *p =
|
||||
if (numTotalGregoryPatches > 0) {
|
||||
PatchTable::QuadOffsetsTable::value_type *p =
|
||||
&((*quadOffsetsTable)[0]);
|
||||
for (size_t i = 0; i < numGregoryPatches; ++i) {
|
||||
getQuadOffsets(level, _gregoryFaceIndices[i], p);
|
||||
p += 4;
|
||||
}
|
||||
for (size_t i = 0; i < numGregoryBoundaryPatches; ++i) {
|
||||
getQuadOffsets(level, _gregoryBoundaryFaceIndices[i], p);
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < numGregoryPatches; ++i) {
|
||||
getQuadOffsets(level, _gregoryFaceIndices[i], p);
|
||||
p += 4;
|
||||
}
|
||||
for (size_t i = 0; i < numGregoryBoundaryPatches; ++i) {
|
||||
getQuadOffsets(level, _gregoryBoundaryFaceIndices[i], p);
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// populate vertex valences
|
||||
//
|
||||
@ -144,7 +144,7 @@ EndCapLegacyGregoryPatchFactory::Finalize(
|
||||
//
|
||||
const int SizePerVertex = 2*maxValence + 1;
|
||||
|
||||
PatchTables::VertexValenceTable & vTable = (*vertexValenceTable);
|
||||
PatchTable::VertexValenceTable & vTable = (*vertexValenceTable);
|
||||
vTable.resize(_refiner.GetNumVerticesTotal() * SizePerVertex);
|
||||
|
||||
int vOffset = 0;
|
||||
|
@ -25,19 +25,19 @@
|
||||
#ifndef OPENSUBDIV3_FAR_END_CAP_LEGACY_GREGORY_PATCH_FACTORY_H
|
||||
#define OPENSUBDIV3_FAR_END_CAP_LEGACY_GREGORY_PATCH_FACTORY_H
|
||||
|
||||
#include "../far/patchTablesFactory.h"
|
||||
#include "../far/patchTableFactory.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
class PatchTables;
|
||||
class PatchTable;
|
||||
class TopologyRefiner;
|
||||
|
||||
namespace Far {
|
||||
|
||||
/// \brief This factory generates legacy (OpenSubdiv 2.x) gregory patches.
|
||||
///
|
||||
/// note: This is an internal use class in PatchTablesFactory.
|
||||
/// note: This is an internal use class in PatchTableFactory.
|
||||
/// will be deprecated at some point.
|
||||
///
|
||||
class EndCapLegacyGregoryPatchFactory {
|
||||
@ -58,12 +58,12 @@ public:
|
||||
/// @param levelVertOffset relative offset of patch vertex indices
|
||||
///
|
||||
ConstIndexArray GetPatchPoints(Vtr::Level const * level, Index faceIndex,
|
||||
PatchTablesFactory::PatchFaceTag const * levelPatchTags,
|
||||
PatchTableFactory::PatchFaceTag const * levelPatchTags,
|
||||
int levelVertOffset);
|
||||
|
||||
void Finalize(int maxValence,
|
||||
PatchTables::QuadOffsetsTable *quadOffsetsTable,
|
||||
PatchTables::VertexValenceTable *vertexValenceTable);
|
||||
PatchTable::QuadOffsetsTable *quadOffsetsTable,
|
||||
PatchTable::VertexValenceTable *vertexValenceTable);
|
||||
|
||||
|
||||
private:
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "../far/gregoryBasis.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTablesFactory.h"
|
||||
#include "../far/stencilTableFactory.h"
|
||||
#include "../far/topologyRefiner.h"
|
||||
#include "../vtr/stackBuffer.h"
|
||||
|
||||
@ -129,10 +129,10 @@ inline float csf(Index n, Index j) {
|
||||
}
|
||||
}
|
||||
|
||||
GregoryBasis::ProtoBasis::ProtoBasis(
|
||||
Vtr::Level const & level, Index faceIndex, int fvarChannel) {
|
||||
|
||||
static float ef[MAX_VALENCE-3] = {
|
||||
inline float computeCoefficient(int valence) {
|
||||
// precomputed coefficient table up to valence 29
|
||||
static float efTable[] = {
|
||||
0, 0, 0,
|
||||
0.812816f, 0.500000f, 0.363644f, 0.287514f,
|
||||
0.238688f, 0.204544f, 0.179229f, 0.159657f,
|
||||
0.144042f, 0.131276f, 0.120632f, 0.111614f,
|
||||
@ -141,6 +141,16 @@ GregoryBasis::ProtoBasis::ProtoBasis(
|
||||
0.0669851f, 0.0641504f, 0.0615475f, 0.0591488f,
|
||||
0.0569311f, 0.0548745f, 0.0529621f
|
||||
};
|
||||
assert(valence > 0);
|
||||
if (valence < 30) return efTable[valence];
|
||||
|
||||
float t = 2.0f * float(M_PI) / float(valence);
|
||||
return 1.0f / (valence * (cosf(t) + 5.0f +
|
||||
sqrtf((cosf(t) + 9) * (cosf(t) + 1)))/16.0f);
|
||||
}
|
||||
|
||||
GregoryBasis::ProtoBasis::ProtoBasis(
|
||||
Vtr::Level const & level, Index faceIndex, int fvarChannel) {
|
||||
|
||||
Vtr::ConstIndexArray facePoints = (fvarChannel<0) ?
|
||||
level.getFaceVertices(faceIndex) :
|
||||
@ -248,8 +258,9 @@ GregoryBasis::ProtoBasis::ProtoBasis(
|
||||
e1[vid] += e * csf(ivalence-3, 2*i+1);
|
||||
}
|
||||
|
||||
e0[vid] *= ef[ivalence-3];
|
||||
e1[vid] *= ef[ivalence-3];
|
||||
float ef = computeCoefficient(ivalence);
|
||||
e0[vid] *= ef;
|
||||
e1[vid] *= ef;
|
||||
|
||||
if (valence<0) {
|
||||
|
||||
@ -381,8 +392,8 @@ GregoryBasis::ProtoBasis::ProtoBasis(
|
||||
}
|
||||
|
||||
/*static*/
|
||||
StencilTables *
|
||||
GregoryBasis::CreateStencilTables(PointsVector const &stencils) {
|
||||
StencilTable *
|
||||
GregoryBasis::CreateStencilTable(PointsVector const &stencils) {
|
||||
|
||||
int nStencils = (int)stencils.size();
|
||||
if (nStencils == 0) return NULL;
|
||||
@ -393,15 +404,15 @@ GregoryBasis::CreateStencilTables(PointsVector const &stencils) {
|
||||
}
|
||||
|
||||
// allocate destination
|
||||
StencilTables *stencilTables = new StencilTables();
|
||||
StencilTable *stencilTable = new StencilTable();
|
||||
|
||||
// XXX: do we need numControlVertices in stencilTables?
|
||||
stencilTables->_numControlVertices = 0;
|
||||
stencilTables->resize(nStencils, nElements);
|
||||
// XXX: do we need numControlVertices in stencilTable?
|
||||
stencilTable->_numControlVertices = 0;
|
||||
stencilTable->resize(nStencils, nElements);
|
||||
|
||||
int * sizes = &stencilTables->_sizes[0];
|
||||
Index * indices = &stencilTables->_indices[0];
|
||||
float * weights = &stencilTables->_weights[0];
|
||||
int * sizes = &stencilTable->_sizes[0];
|
||||
Index * indices = &stencilTable->_indices[0];
|
||||
float * weights = &stencilTable->_weights[0];
|
||||
|
||||
for (int i = 0; i < nStencils; ++i) {
|
||||
GregoryBasis::Point const &src = stencils[i];
|
||||
@ -415,9 +426,9 @@ GregoryBasis::CreateStencilTables(PointsVector const &stencils) {
|
||||
weights += size;
|
||||
++sizes;
|
||||
}
|
||||
stencilTables->generateOffsets();
|
||||
stencilTable->generateOffsets();
|
||||
|
||||
return stencilTables;
|
||||
return stencilTable;
|
||||
}
|
||||
|
||||
} // end namespace Far
|
||||
|
@ -25,8 +25,9 @@
|
||||
#ifndef OPENSUBDIV3_FAR_GREGORY_BASIS_H
|
||||
#define OPENSUBDIV3_FAR_GREGORY_BASIS_H
|
||||
|
||||
#include "../far/protoStencil.h"
|
||||
#include "../vtr/level.h"
|
||||
#include "../far/types.h"
|
||||
#include "../far/stencilTable.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
@ -59,7 +60,7 @@ public:
|
||||
template <class T, class U>
|
||||
void Evaluate(T const & controlValues, U values[20]) const {
|
||||
|
||||
Index const * indices = &_indices.at(0);
|
||||
Vtr::Index const * indices = &_indices.at(0);
|
||||
float const * weights = &_weights.at(0);
|
||||
|
||||
for (int i=0; i<20; ++i) {
|
||||
@ -70,16 +71,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static const int MAX_VALENCE = (30*2);
|
||||
static const int MAX_ELEMS = (16 + MAX_VALENCE);
|
||||
|
||||
// limit valence of 30 because we use a pre-computed closed-form 'ef' table
|
||||
// XXXtakahito: revisit here to determine appropriate size
|
||||
// or remove fixed size limit and use Sdc mask
|
||||
static int getNumMaxElements(int maxValence) {
|
||||
return (16 + maxValence);
|
||||
}
|
||||
|
||||
//
|
||||
// Basis point
|
||||
//
|
||||
@ -88,13 +79,19 @@ public:
|
||||
//
|
||||
class Point {
|
||||
public:
|
||||
static const int RESERVED_ENTRY_SIZE = 64;
|
||||
|
||||
Point() : _size(0) { }
|
||||
Point() : _size(0) {
|
||||
_indices.reserve(RESERVED_ENTRY_SIZE);
|
||||
_weights.reserve(RESERVED_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
Point(Index idx, float weight = 1.0f) {
|
||||
Point(Vtr::Index idx, float weight = 1.0f) {
|
||||
_indices.reserve(RESERVED_ENTRY_SIZE);
|
||||
_weights.reserve(RESERVED_ENTRY_SIZE);
|
||||
_size = 1;
|
||||
_indices[0] = idx;
|
||||
_weights[0] = weight;
|
||||
_indices.push_back(idx);
|
||||
_weights.push_back(weight);
|
||||
}
|
||||
|
||||
Point(Point const & other) {
|
||||
@ -105,24 +102,24 @@ public:
|
||||
return _size;
|
||||
}
|
||||
|
||||
Index const * GetIndices() const {
|
||||
return _indices;
|
||||
Vtr::Index const * GetIndices() const {
|
||||
return &_indices[0];
|
||||
}
|
||||
|
||||
float const * GetWeights() const {
|
||||
return _weights;
|
||||
return &_weights[0];
|
||||
}
|
||||
|
||||
Point & operator = (Point const & other) {
|
||||
_size = other._size;
|
||||
memcpy(_indices, other._indices, other._size*sizeof(Index));
|
||||
memcpy(_weights, other._weights, other._size*sizeof(float));
|
||||
_indices = other._indices;
|
||||
_weights = other._weights;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Point & operator += (Point const & other) {
|
||||
for (int i=0; i<other._size; ++i) {
|
||||
Index idx = findIndex(other._indices[i]);
|
||||
Vtr::Index idx = findIndex(other._indices[i]);
|
||||
_weights[idx] += other._weights[i];
|
||||
}
|
||||
return *this;
|
||||
@ -130,7 +127,7 @@ public:
|
||||
|
||||
Point & operator -= (Point const & other) {
|
||||
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];
|
||||
}
|
||||
return *this;
|
||||
@ -163,15 +160,15 @@ public:
|
||||
Point p(*this); return p-=other;
|
||||
}
|
||||
|
||||
void OffsetIndices(Index offset) {
|
||||
void OffsetIndices(Vtr::Index offset) {
|
||||
for (int i=0; i<_size; ++i) {
|
||||
_indices[i] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
void Copy(int ** size, Index ** indices, float ** weights) const {
|
||||
memcpy(*indices, _indices, _size*sizeof(Index));
|
||||
memcpy(*weights, _weights, _size*sizeof(float));
|
||||
void Copy(int ** size, Vtr::Index ** indices, float ** weights) const {
|
||||
memcpy(*indices, &_indices[0], _size*sizeof(Vtr::Index));
|
||||
memcpy(*weights, &_weights[0], _size*sizeof(float));
|
||||
**size = _size;
|
||||
*indices += _size;
|
||||
*weights += _size;
|
||||
@ -180,24 +177,21 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
int findIndex(Index idx) {
|
||||
int findIndex(Vtr::Index idx) {
|
||||
for (int i=0; i<_size; ++i) {
|
||||
if (_indices[i]==idx) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
_indices[_size]=idx;
|
||||
_weights[_size]=0.0f;
|
||||
_indices.push_back(idx);
|
||||
_weights.push_back(0.0f);
|
||||
++_size;
|
||||
return _size-1;
|
||||
}
|
||||
|
||||
int _size;
|
||||
// XXXX this would really be better with VLA where we only allocate
|
||||
// space based on the max vertex valence in the mesh, not the absolute
|
||||
// maximum supported by the closed-form tangents table.
|
||||
Index _indices[MAX_ELEMS];
|
||||
float _weights[MAX_ELEMS];
|
||||
std::vector<Vtr::Index> _indices;
|
||||
std::vector<float> _weights;
|
||||
};
|
||||
|
||||
//
|
||||
@ -208,11 +202,11 @@ public:
|
||||
//
|
||||
struct ProtoBasis {
|
||||
|
||||
ProtoBasis(Vtr::Level const & level, Index faceIndex, int fvarChannel=-1);
|
||||
ProtoBasis(Vtr::Level const & level, Vtr::Index faceIndex, int fvarChannel=-1);
|
||||
|
||||
int GetNumElements() const;
|
||||
|
||||
void Copy(int * sizes, Index * indices, float * weights) const;
|
||||
void Copy(int * sizes, Vtr::Index * indices, float * weights) const;
|
||||
void Copy(GregoryBasis* dest) const;
|
||||
|
||||
// Control Vertices based on :
|
||||
@ -248,13 +242,13 @@ public:
|
||||
|
||||
typedef std::vector<GregoryBasis::Point> PointsVector;
|
||||
|
||||
static StencilTables *CreateStencilTables(PointsVector const &stencils);
|
||||
static StencilTable *CreateStencilTable(PointsVector const &stencils);
|
||||
|
||||
private:
|
||||
|
||||
int _sizes[20];
|
||||
|
||||
std::vector<Index> _indices;
|
||||
std::vector<Vtr::Index> _indices;
|
||||
std::vector<float> _weights;
|
||||
};
|
||||
|
||||
|
@ -30,8 +30,8 @@ namespace OPENSUBDIV_VERSION {
|
||||
namespace Far {
|
||||
|
||||
// Constructor
|
||||
PatchMap::PatchMap( PatchTables const & patchTables ) {
|
||||
initialize( patchTables );
|
||||
PatchMap::PatchMap( PatchTable const & patchTable ) {
|
||||
initialize( patchTable );
|
||||
}
|
||||
|
||||
// sets all the children to point to the patch of index patchIdx
|
||||
@ -63,11 +63,11 @@ PatchMap::addChild( QuadTree & quadtree, QuadNode * parent, int quadrant ) {
|
||||
}
|
||||
|
||||
void
|
||||
PatchMap::initialize( PatchTables const & patchTables ) {
|
||||
PatchMap::initialize( PatchTable const & patchTable ) {
|
||||
|
||||
int nfaces = 0,
|
||||
narrays = (int)patchTables.GetNumPatchArrays(),
|
||||
npatches = (int)patchTables.GetNumPatchesTotal();
|
||||
narrays = (int)patchTable.GetNumPatchArrays(),
|
||||
npatches = (int)patchTable.GetNumPatchesTotal();
|
||||
|
||||
if (not narrays or not npatches)
|
||||
return;
|
||||
@ -77,11 +77,11 @@ PatchMap::initialize( PatchTables const & patchTables ) {
|
||||
|
||||
for (int parray=0, current=0; parray<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];
|
||||
|
||||
@ -107,9 +107,9 @@ PatchMap::initialize( PatchTables const & patchTables ) {
|
||||
// populate the quadtree from the FarPatchArrays sub-patches
|
||||
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;
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -38,7 +38,7 @@ namespace Far {
|
||||
|
||||
/// \brief An quadtree-based map connecting coarse faces to their sub-patches
|
||||
///
|
||||
/// PatchTables::PatchArrays contain lists of patches that represent the limit
|
||||
/// PatchTable::PatchArrays contain lists of patches that represent the limit
|
||||
/// surface of a mesh, sorted by their topological type. These arrays break the
|
||||
/// connection between coarse faces and their sub-patches.
|
||||
///
|
||||
@ -49,13 +49,13 @@ namespace Far {
|
||||
class PatchMap {
|
||||
public:
|
||||
|
||||
typedef PatchTables::PatchHandle Handle;
|
||||
typedef PatchTable::PatchHandle Handle;
|
||||
|
||||
/// \brief Constructor
|
||||
///
|
||||
/// @param patchTables A valid set of PatchTables
|
||||
/// @param patchTable A valid set of PatchTable
|
||||
///
|
||||
PatchMap( PatchTables const & patchTables );
|
||||
PatchMap( PatchTable const & patchTable );
|
||||
|
||||
/// \brief Returns a handle to the sub-patch of the face at the given (u,v).
|
||||
/// Note : the faceid corresponds to quadrangulated face indices (ie. quads
|
||||
@ -74,7 +74,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
inline void initialize( PatchTables const & patchTables );
|
||||
inline void initialize( PatchTable const & patchTable );
|
||||
|
||||
// Quadtree node with 4 children
|
||||
struct QuadNode {
|
||||
|
@ -22,7 +22,7 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../far/patchBasis.h"
|
||||
|
||||
#include <cstring>
|
||||
@ -33,15 +33,15 @@ namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
|
||||
PatchTables::PatchTables(int maxvalence) :
|
||||
PatchTable::PatchTable(int maxvalence) :
|
||||
_maxValence(maxvalence),
|
||||
_vertexStencilTables(NULL),
|
||||
_varyingStencilTables(NULL) {
|
||||
_vertexStencilTable(NULL),
|
||||
_varyingStencilTable(NULL) {
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
// XXXX manuelk we need to eliminate this constructor (C++11 smart pointers)
|
||||
PatchTables::PatchTables(PatchTables const & src) :
|
||||
PatchTable::PatchTable(PatchTable const & src) :
|
||||
_maxValence(src._maxValence),
|
||||
_numPtexFaces(src._numPtexFaces),
|
||||
_patchArrays(src._patchArrays),
|
||||
@ -49,29 +49,29 @@ PatchTables::PatchTables(PatchTables const & src) :
|
||||
_paramTable(src._paramTable),
|
||||
_quadOffsetsTable(src._quadOffsetsTable),
|
||||
_vertexValenceTable(src._vertexValenceTable),
|
||||
_vertexStencilTables(NULL),
|
||||
_varyingStencilTables(NULL),
|
||||
_vertexStencilTable(NULL),
|
||||
_varyingStencilTable(NULL),
|
||||
_fvarChannels(src._fvarChannels),
|
||||
_sharpnessIndices(src._sharpnessIndices),
|
||||
_sharpnessValues(src._sharpnessValues) {
|
||||
|
||||
if (src._vertexStencilTables) {
|
||||
_vertexStencilTables = new StencilTables(*src._vertexStencilTables);
|
||||
if (src._vertexStencilTable) {
|
||||
_vertexStencilTable = new StencilTable(*src._vertexStencilTable);
|
||||
}
|
||||
if (src._varyingStencilTables) {
|
||||
_varyingStencilTables = new StencilTables(*src._varyingStencilTables);
|
||||
if (src._varyingStencilTable) {
|
||||
_varyingStencilTable = new StencilTable(*src._varyingStencilTable);
|
||||
}
|
||||
}
|
||||
|
||||
PatchTables::~PatchTables() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
PatchTable::~PatchTable() {
|
||||
delete _vertexStencilTable;
|
||||
delete _varyingStencilTable;
|
||||
}
|
||||
|
||||
//
|
||||
// PatchArrays
|
||||
//
|
||||
struct PatchTables::PatchArray {
|
||||
struct PatchTable::PatchArray {
|
||||
|
||||
PatchArray(PatchDescriptor d, int np, Index v, Index p, Index qo) :
|
||||
desc(d), numPatches(np), vertIndex(v),
|
||||
@ -91,24 +91,24 @@ struct PatchTables::PatchArray {
|
||||
|
||||
// debug helper
|
||||
void
|
||||
PatchTables::PatchArray::print() const {
|
||||
PatchTable::PatchArray::print() const {
|
||||
desc.print();
|
||||
printf(" numPatches=%d vertIndex=%d patchIndex=%d "
|
||||
"quadOffsetIndex=%d\n", numPatches, vertIndex, patchIndex,
|
||||
quadOffsetIndex);
|
||||
}
|
||||
inline PatchTables::PatchArray &
|
||||
PatchTables::getPatchArray(Index arrayIndex) {
|
||||
inline PatchTable::PatchArray &
|
||||
PatchTable::getPatchArray(Index arrayIndex) {
|
||||
assert(arrayIndex<(Index)GetNumPatchArrays());
|
||||
return _patchArrays[arrayIndex];
|
||||
}
|
||||
inline PatchTables::PatchArray const &
|
||||
PatchTables::getPatchArray(Index arrayIndex) const {
|
||||
inline PatchTable::PatchArray const &
|
||||
PatchTable::getPatchArray(Index arrayIndex) const {
|
||||
assert(arrayIndex<(Index)GetNumPatchArrays());
|
||||
return _patchArrays[arrayIndex];
|
||||
}
|
||||
void
|
||||
PatchTables::reservePatchArrays(int numPatchArrays) {
|
||||
PatchTable::reservePatchArrays(int numPatchArrays) {
|
||||
_patchArrays.reserve(numPatchArrays);
|
||||
}
|
||||
|
||||
@ -117,16 +117,16 @@ PatchTables::reservePatchArrays(int numPatchArrays) {
|
||||
//
|
||||
// Stores a record for each patch in the primitive :
|
||||
//
|
||||
// - Each patch in the PatchTables has a corresponding patch in each
|
||||
// - Each patch in the PatchTable has a corresponding patch in each
|
||||
// face-varying patch channel. Patch vertex indices are sorted in the same
|
||||
// patch-type order as PatchTables::PTables. Face-varying data for a patch
|
||||
// patch-type order as PatchTable::PTables. Face-varying data for a patch
|
||||
// can therefore be quickly accessed by using the patch primitive ID as
|
||||
// index into patchValueOffsets to locate the face-varying control vertex
|
||||
// indices.
|
||||
//
|
||||
// - Face-varying channels can have a different interpolation modes
|
||||
//
|
||||
// - Unlike "vertex" PatchTables, there are no "transition" patterns required
|
||||
// - Unlike "vertex" PatchTable, there are no "transition" patterns required
|
||||
// for face-varying patches.
|
||||
//
|
||||
// - No transition patterns means vertex indices of face-varying patches can
|
||||
@ -139,7 +139,7 @@ PatchTables::reservePatchArrays(int numPatchArrays) {
|
||||
// similar to single-crease to resolve this condition without requiring
|
||||
// isolation if possible
|
||||
//
|
||||
struct PatchTables::FVarPatchChannel {
|
||||
struct PatchTable::FVarPatchChannel {
|
||||
|
||||
// Channel interpolation mode
|
||||
Sdc::Options::FVarLinearInterpolation interpolation;
|
||||
@ -157,22 +157,22 @@ struct PatchTables::FVarPatchChannel {
|
||||
std::vector<Index> patchValues; // point values for each patch
|
||||
};
|
||||
|
||||
inline PatchTables::FVarPatchChannel &
|
||||
PatchTables::getFVarPatchChannel(int channel) {
|
||||
inline PatchTable::FVarPatchChannel &
|
||||
PatchTable::getFVarPatchChannel(int channel) {
|
||||
assert(channel<(int)_fvarChannels.size());
|
||||
return _fvarChannels[channel];
|
||||
}
|
||||
inline PatchTables::FVarPatchChannel const &
|
||||
PatchTables::getFVarPatchChannel(int channel) const {
|
||||
inline PatchTable::FVarPatchChannel const &
|
||||
PatchTable::getFVarPatchChannel(int channel) const {
|
||||
assert(channel<(int)_fvarChannels.size());
|
||||
return _fvarChannels[channel];
|
||||
}
|
||||
void
|
||||
PatchTables::allocateFVarPatchChannels(int numChannels) {
|
||||
PatchTable::allocateFVarPatchChannels(int numChannels) {
|
||||
_fvarChannels.resize(numChannels);
|
||||
}
|
||||
void
|
||||
PatchTables::allocateChannelValues(int channel,
|
||||
PatchTable::allocateChannelValues(int channel,
|
||||
int numPatches, int numVerticesTotal) {
|
||||
|
||||
FVarPatchChannel & c = getFVarPatchChannel(channel);
|
||||
@ -192,22 +192,22 @@ PatchTables::allocateChannelValues(int channel,
|
||||
}
|
||||
}
|
||||
void
|
||||
PatchTables::setFVarPatchChannelLinearInterpolation(int channel,
|
||||
PatchTable::setFVarPatchChannelLinearInterpolation(int channel,
|
||||
Sdc::Options::FVarLinearInterpolation interpolation) {
|
||||
FVarPatchChannel & c = getFVarPatchChannel(channel);
|
||||
c.interpolation = interpolation;
|
||||
}
|
||||
void
|
||||
PatchTables::setFVarPatchChannelPatchesType(int channel, PatchDescriptor::Type type) {
|
||||
PatchTable::setFVarPatchChannelPatchesType(int channel, PatchDescriptor::Type type) {
|
||||
FVarPatchChannel & c = getFVarPatchChannel(channel);
|
||||
c.patchesType = type;
|
||||
}
|
||||
void
|
||||
PatchTables::setBicubicFVarPatchChannelValues(int channel, int patchSize,
|
||||
PatchTable::setBicubicFVarPatchChannelValues(int channel, int patchSize,
|
||||
std::vector<Index> const & values) {
|
||||
|
||||
// This method populates the sparse array of values held in the patch
|
||||
// tables from a non-sparse array of value indices generated during
|
||||
// table from a non-sparse array of value indices generated during
|
||||
// the second traversal of an adaptive TopologyRefiner.
|
||||
// It is assumed that the patch types have been stored in the channel's
|
||||
// 'patchTypes' vector during the first traversal.
|
||||
@ -245,7 +245,7 @@ PatchTables::setBicubicFVarPatchChannelValues(int channel, int patchSize,
|
||||
}
|
||||
|
||||
//
|
||||
// PatchTables
|
||||
// PatchTable
|
||||
//
|
||||
|
||||
inline int
|
||||
@ -254,7 +254,7 @@ getPatchSize(PatchDescriptor desc) {
|
||||
}
|
||||
|
||||
void
|
||||
PatchTables::pushPatchArray(PatchDescriptor desc, int npatches,
|
||||
PatchTable::pushPatchArray(PatchDescriptor desc, int npatches,
|
||||
Index * vidx, Index * pidx, Index * qoidx) {
|
||||
|
||||
if (npatches>0) {
|
||||
@ -271,52 +271,52 @@ PatchTables::pushPatchArray(PatchDescriptor desc, int npatches,
|
||||
}
|
||||
|
||||
int
|
||||
PatchTables::getPatchIndex(int arrayIndex, int patchIndex) const {
|
||||
PatchTable::getPatchIndex(int arrayIndex, int patchIndex) const {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
assert(patchIndex<pa.numPatches);
|
||||
return pa.patchIndex + patchIndex;
|
||||
}
|
||||
Index *
|
||||
PatchTables::getSharpnessIndices(int arrayIndex) {
|
||||
PatchTable::getSharpnessIndices(int arrayIndex) {
|
||||
return &_sharpnessIndices[getPatchArray(arrayIndex).patchIndex];
|
||||
}
|
||||
|
||||
float *
|
||||
PatchTables::getSharpnessValues(int arrayIndex) {
|
||||
PatchTable::getSharpnessValues(int arrayIndex) {
|
||||
return &_sharpnessValues[getPatchArray(arrayIndex).patchIndex];
|
||||
}
|
||||
|
||||
PatchDescriptor
|
||||
PatchTables::GetPatchDescriptor(PatchHandle const & handle) const {
|
||||
PatchTable::GetPatchDescriptor(PatchHandle const & handle) const {
|
||||
return getPatchArray(handle.arrayIndex).desc;
|
||||
}
|
||||
|
||||
PatchDescriptor
|
||||
PatchTables::GetPatchArrayDescriptor(int arrayIndex) const {
|
||||
PatchTable::GetPatchArrayDescriptor(int arrayIndex) const {
|
||||
return getPatchArray(arrayIndex).desc;
|
||||
}
|
||||
|
||||
int
|
||||
PatchTables::GetNumPatchArrays() const {
|
||||
PatchTable::GetNumPatchArrays() const {
|
||||
return (int)_patchArrays.size();
|
||||
}
|
||||
int
|
||||
PatchTables::GetNumPatches(int arrayIndex) const {
|
||||
PatchTable::GetNumPatches(int arrayIndex) const {
|
||||
return getPatchArray(arrayIndex).numPatches;
|
||||
}
|
||||
int
|
||||
PatchTables::GetNumPatchesTotal() const {
|
||||
PatchTable::GetNumPatchesTotal() const {
|
||||
// there is one PatchParam record for each patch in the mesh
|
||||
return (int)_paramTable.size();
|
||||
}
|
||||
int
|
||||
PatchTables::GetNumControlVertices(int arrayIndex) const {
|
||||
PatchTable::GetNumControlVertices(int arrayIndex) const {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
return pa.numPatches * getPatchSize(pa.desc);
|
||||
}
|
||||
|
||||
Index
|
||||
PatchTables::findPatchArray(PatchDescriptor desc) {
|
||||
PatchTable::findPatchArray(PatchDescriptor desc) {
|
||||
for (int i=0; i<(int)_patchArrays.size(); ++i) {
|
||||
if (_patchArrays[i].desc==desc)
|
||||
return i;
|
||||
@ -324,14 +324,14 @@ PatchTables::findPatchArray(PatchDescriptor desc) {
|
||||
return Vtr::INDEX_INVALID;
|
||||
}
|
||||
IndexArray
|
||||
PatchTables::getPatchArrayVertices(int arrayIndex) {
|
||||
PatchTable::getPatchArrayVertices(int arrayIndex) {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
int size = getPatchSize(pa.desc);
|
||||
assert(pa.vertIndex<(Index)_patchVerts.size());
|
||||
return IndexArray(&_patchVerts[pa.vertIndex], pa.numPatches * size);
|
||||
}
|
||||
ConstIndexArray
|
||||
PatchTables::GetPatchArrayVertices(int arrayIndex) const {
|
||||
PatchTable::GetPatchArrayVertices(int arrayIndex) const {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
int size = getPatchSize(pa.desc);
|
||||
assert(pa.vertIndex<(Index)_patchVerts.size());
|
||||
@ -339,13 +339,13 @@ PatchTables::GetPatchArrayVertices(int arrayIndex) const {
|
||||
}
|
||||
|
||||
ConstIndexArray
|
||||
PatchTables::GetPatchVertices(PatchHandle const & handle) const {
|
||||
PatchTable::GetPatchVertices(PatchHandle const & handle) const {
|
||||
PatchArray const & pa = getPatchArray(handle.arrayIndex);
|
||||
Index vert = pa.vertIndex + handle.vertIndex;
|
||||
return ConstIndexArray(&_patchVerts[vert], getPatchSize(pa.desc));
|
||||
}
|
||||
ConstIndexArray
|
||||
PatchTables::GetPatchVertices(int arrayIndex, int patchIndex) const {
|
||||
PatchTable::GetPatchVertices(int arrayIndex, int patchIndex) const {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
int size = getPatchSize(pa.desc);
|
||||
assert((pa.vertIndex + patchIndex*size)<(Index)_patchVerts.size());
|
||||
@ -353,29 +353,29 @@ PatchTables::GetPatchVertices(int arrayIndex, int patchIndex) const {
|
||||
}
|
||||
|
||||
PatchParam
|
||||
PatchTables::GetPatchParam(PatchHandle const & handle) const {
|
||||
PatchTable::GetPatchParam(PatchHandle const & handle) const {
|
||||
assert(handle.patchIndex < (Index)_paramTable.size());
|
||||
return _paramTable[handle.patchIndex];
|
||||
}
|
||||
PatchParam
|
||||
PatchTables::GetPatchParam(int arrayIndex, int patchIndex) const {
|
||||
PatchTable::GetPatchParam(int arrayIndex, int patchIndex) const {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
assert((pa.patchIndex + patchIndex) < (int)_paramTable.size());
|
||||
return _paramTable[pa.patchIndex + patchIndex];
|
||||
}
|
||||
PatchParamArray
|
||||
PatchTables::getPatchParams(int arrayIndex) {
|
||||
PatchTable::getPatchParams(int arrayIndex) {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
return PatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches);
|
||||
}
|
||||
ConstPatchParamArray const
|
||||
PatchTables::GetPatchParams(int arrayIndex) const {
|
||||
PatchTable::GetPatchParams(int arrayIndex) const {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
return ConstPatchParamArray(&_paramTable[pa.patchIndex], pa.numPatches);
|
||||
}
|
||||
|
||||
float
|
||||
PatchTables::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const {
|
||||
PatchTable::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) const {
|
||||
assert((handle.patchIndex) < (int)_sharpnessIndices.size());
|
||||
Index index = _sharpnessIndices[handle.patchIndex];
|
||||
if (index == Vtr::INDEX_INVALID) {
|
||||
@ -385,7 +385,7 @@ PatchTables::GetSingleCreasePatchSharpnessValue(PatchHandle const & handle) cons
|
||||
return _sharpnessValues[index];
|
||||
}
|
||||
float
|
||||
PatchTables::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex) const {
|
||||
PatchTable::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex) const {
|
||||
PatchArray const & pa = getPatchArray(arrayIndex);
|
||||
assert((pa.patchIndex + patchIndex) < (int)_sharpnessIndices.size());
|
||||
Index index = _sharpnessIndices[pa.patchIndex + patchIndex];
|
||||
@ -396,13 +396,13 @@ PatchTables::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex)
|
||||
return _sharpnessValues[index];
|
||||
}
|
||||
|
||||
PatchTables::ConstQuadOffsetsArray
|
||||
PatchTables::GetPatchQuadOffsets(PatchHandle const & handle) const {
|
||||
PatchTable::ConstQuadOffsetsArray
|
||||
PatchTable::GetPatchQuadOffsets(PatchHandle const & handle) const {
|
||||
PatchArray const & pa = getPatchArray(handle.arrayIndex);
|
||||
return Vtr::ConstArray<unsigned int>(&_quadOffsetsTable[pa.quadOffsetIndex + handle.vertIndex], 4);
|
||||
}
|
||||
bool
|
||||
PatchTables::IsFeatureAdaptive() const {
|
||||
PatchTable::IsFeatureAdaptive() const {
|
||||
|
||||
// XXX:
|
||||
// revisit this function, since we'll add uniform cubic patches later.
|
||||
@ -418,22 +418,22 @@ PatchTables::IsFeatureAdaptive() const {
|
||||
}
|
||||
|
||||
int
|
||||
PatchTables::GetNumFVarChannels() const {
|
||||
PatchTable::GetNumFVarChannels() const {
|
||||
return (int)_fvarChannels.size();
|
||||
}
|
||||
Sdc::Options::FVarLinearInterpolation
|
||||
PatchTables::GetFVarChannelLinearInterpolation(int channel) const {
|
||||
PatchTable::GetFVarChannelLinearInterpolation(int channel) const {
|
||||
FVarPatchChannel const & c = getFVarPatchChannel(channel);
|
||||
return c.interpolation;
|
||||
}
|
||||
Vtr::Array<PatchDescriptor::Type>
|
||||
PatchTables::getFVarPatchTypes(int channel) {
|
||||
PatchTable::getFVarPatchTypes(int channel) {
|
||||
FVarPatchChannel & c = getFVarPatchChannel(channel);
|
||||
return Vtr::Array<PatchDescriptor::Type>(&c.patchTypes[0],
|
||||
(int)c.patchTypes.size());
|
||||
}
|
||||
Vtr::ConstArray<PatchDescriptor::Type>
|
||||
PatchTables::GetFVarPatchTypes(int channel) const {
|
||||
PatchTable::GetFVarPatchTypes(int channel) const {
|
||||
FVarPatchChannel const & c = getFVarPatchChannel(channel);
|
||||
if (c.patchesType!=PatchDescriptor::NON_PATCH) {
|
||||
return Vtr::ConstArray<PatchDescriptor::Type>(&c.patchesType, 1);
|
||||
@ -443,17 +443,17 @@ PatchTables::GetFVarPatchTypes(int channel) const {
|
||||
}
|
||||
}
|
||||
ConstIndexArray
|
||||
PatchTables::GetFVarPatchesValues(int channel) const {
|
||||
PatchTable::GetFVarPatchesValues(int channel) const {
|
||||
FVarPatchChannel const & c = getFVarPatchChannel(channel);
|
||||
return ConstIndexArray(&c.patchValues[0], (int)c.patchValues.size());
|
||||
}
|
||||
IndexArray
|
||||
PatchTables::getFVarPatchesValues(int channel) {
|
||||
PatchTable::getFVarPatchesValues(int channel) {
|
||||
FVarPatchChannel & c = getFVarPatchChannel(channel);
|
||||
return IndexArray(&c.patchValues[0], (int)c.patchValues.size());
|
||||
}
|
||||
PatchDescriptor::Type
|
||||
PatchTables::getFVarPatchType(int channel, int patch) const {
|
||||
PatchTable::getFVarPatchType(int channel, int patch) const {
|
||||
FVarPatchChannel const & c = getFVarPatchChannel(channel);
|
||||
PatchDescriptor::Type type;
|
||||
if (c.patchesType!=PatchDescriptor::NON_PATCH) {
|
||||
@ -466,15 +466,15 @@ PatchTables::getFVarPatchType(int channel, int patch) const {
|
||||
return type;
|
||||
}
|
||||
PatchDescriptor::Type
|
||||
PatchTables::GetFVarPatchType(int channel, PatchHandle const & handle) const {
|
||||
PatchTable::GetFVarPatchType(int channel, PatchHandle const & handle) const {
|
||||
return getFVarPatchType(channel, handle.patchIndex);
|
||||
}
|
||||
PatchDescriptor::Type
|
||||
PatchTables::GetFVarPatchType(int channel, int arrayIndex, int patchIndex) const {
|
||||
PatchTable::GetFVarPatchType(int channel, int arrayIndex, int patchIndex) const {
|
||||
return getFVarPatchType(channel, getPatchIndex(arrayIndex, patchIndex));
|
||||
}
|
||||
ConstIndexArray
|
||||
PatchTables::getFVarPatchValues(int channel, int patch) const {
|
||||
PatchTable::getFVarPatchValues(int channel, int patch) const {
|
||||
|
||||
FVarPatchChannel const & c = getFVarPatchChannel(channel);
|
||||
|
||||
@ -489,17 +489,17 @@ PatchTables::getFVarPatchValues(int channel, int patch) const {
|
||||
}
|
||||
}
|
||||
ConstIndexArray
|
||||
PatchTables::GetFVarPatchValues(int channel, PatchHandle const & handle) const {
|
||||
PatchTable::GetFVarPatchValues(int channel, PatchHandle const & handle) const {
|
||||
return getFVarPatchValues(channel, handle.patchIndex);
|
||||
}
|
||||
ConstIndexArray
|
||||
PatchTables::GetFVarPatchValues(int channel, int arrayIndex, int patchIndex) const {
|
||||
PatchTable::GetFVarPatchValues(int channel, int arrayIndex, int patchIndex) const {
|
||||
return getFVarPatchValues(channel, getPatchIndex(arrayIndex, patchIndex));
|
||||
}
|
||||
|
||||
void
|
||||
PatchTables::print() const {
|
||||
printf("patchTables (0x%p)\n", this);
|
||||
PatchTable::print() const {
|
||||
printf("patchTable (0x%p)\n", this);
|
||||
printf(" numPatches = %d\n", GetNumPatchesTotal());
|
||||
for (int i=0; i<GetNumPatchArrays(); ++i) {
|
||||
printf(" patchArray %d:\n", i);
|
||||
@ -512,7 +512,7 @@ PatchTables::print() const {
|
||||
// Evaluate basis functions for position and first derivatives at (s,t):
|
||||
//
|
||||
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 {
|
||||
|
||||
PatchDescriptor::Type patchType = GetPatchArrayDescriptor(handle.arrayIndex).GetType();
|
@ -22,14 +22,14 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_FAR_PATCH_TABLES_H
|
||||
#define OPENSUBDIV3_FAR_PATCH_TABLES_H
|
||||
#ifndef OPENSUBDIV3_FAR_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_FAR_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchDescriptor.h"
|
||||
#include "../far/patchParam.h"
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
#include "../sdc/options.h"
|
||||
|
||||
@ -46,26 +46,26 @@ namespace Far {
|
||||
|
||||
/// \brief Container for arrays of parametric patches
|
||||
///
|
||||
/// PatchTables contain topology and parametric information about the patches
|
||||
/// generated by the Refinement process. Patches in the tables are sorted into
|
||||
/// PatchTable contain topology and parametric information about the patches
|
||||
/// generated by the Refinement process. Patches in the table are sorted into
|
||||
/// 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.
|
||||
///
|
||||
/// 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:
|
||||
|
||||
/// \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 {
|
||||
// XXXX manuelk members will eventually be made private
|
||||
public:
|
||||
|
||||
friend class PatchTables;
|
||||
friend class PatchTable;
|
||||
friend class PatchMap;
|
||||
|
||||
Index arrayIndex, // Array index of the patch
|
||||
@ -76,20 +76,20 @@ public:
|
||||
public:
|
||||
|
||||
/// \brief Copy constructor
|
||||
PatchTables(PatchTables const & src);
|
||||
PatchTable(PatchTable const & src);
|
||||
|
||||
/// \brief Destructor
|
||||
~PatchTables();
|
||||
~PatchTable();
|
||||
|
||||
/// \brief True if the patches are of feature adaptive types
|
||||
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 {
|
||||
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;
|
||||
|
||||
/// \brief Returns max vertex valence
|
||||
@ -172,16 +172,16 @@ public:
|
||||
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.
|
||||
StencilTables const *GetEndCapVertexStencilTables() const {
|
||||
return _vertexStencilTables;
|
||||
StencilTable const *GetEndCapVertexStencilTable() const {
|
||||
return _vertexStencilTable;
|
||||
}
|
||||
|
||||
/// \brief Returns the varying stencil tables for the endcap patches
|
||||
/// which has same ordering as the endcap vertex stencil tables.
|
||||
StencilTables const *GetEndCapVaryingStencilTables() const {
|
||||
return _varyingStencilTables;
|
||||
/// \brief Returns the varying stencil table for the endcap patches
|
||||
/// which has same ordering as the endcap vertex stencil table.
|
||||
StencilTable const *GetEndCapVaryingStencilTable() const {
|
||||
return _varyingStencilTable;
|
||||
}
|
||||
|
||||
//@}
|
||||
@ -304,10 +304,10 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
friend class PatchTablesFactory;
|
||||
friend class PatchTableFactory;
|
||||
|
||||
// Factory constructor
|
||||
PatchTables(int maxvalence);
|
||||
PatchTable(int maxvalence);
|
||||
|
||||
Index getPatchIndex(int array, int patch) const;
|
||||
|
||||
@ -386,8 +386,8 @@ private:
|
||||
//
|
||||
QuadOffsetsTable _quadOffsetsTable; // Quad offsets (for Gregory patches)
|
||||
VertexValenceTable _vertexValenceTable; // Vertex valence table (for Gregory patches)
|
||||
StencilTables const * _vertexStencilTables; // endcap basis conversion stencils
|
||||
StencilTables const * _varyingStencilTables; // endcap varying stencils (for convenience)
|
||||
StencilTable const * _vertexStencilTable; // endcap basis conversion stencils
|
||||
StencilTable const * _varyingStencilTable; // endcap varying stencils (for convenience)
|
||||
|
||||
//
|
||||
// Face-varying data
|
||||
@ -410,4 +410,4 @@ using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // 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
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
#include "../far/patchTablesFactory.h"
|
||||
#include "../far/patchTableFactory.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/ptexIndices.h"
|
||||
#include "../far/topologyRefiner.h"
|
||||
@ -91,12 +91,12 @@ typedef PatchTypes<Far::Index **> PatchFVarPointers;
|
||||
namespace Far {
|
||||
|
||||
void
|
||||
PatchTablesFactory::PatchFaceTag::clear() {
|
||||
PatchTableFactory::PatchFaceTag::clear() {
|
||||
std::memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void
|
||||
PatchTablesFactory::PatchFaceTag::assignBoundaryPropertiesFromEdgeMask(int boundaryEdgeMask) {
|
||||
PatchTableFactory::PatchFaceTag::assignBoundaryPropertiesFromEdgeMask(int boundaryEdgeMask) {
|
||||
//
|
||||
// The number of rotations to apply for boundary or corner patches varies on both
|
||||
// where the boundary/corner occurs and whether boundary or corner -- so using a
|
||||
@ -134,7 +134,7 @@ PatchTablesFactory::PatchFaceTag::assignBoundaryPropertiesFromEdgeMask(int bound
|
||||
}
|
||||
|
||||
void
|
||||
PatchTablesFactory::PatchFaceTag::assignBoundaryPropertiesFromVertexMask(int boundaryVertexMask) {
|
||||
PatchTableFactory::PatchFaceTag::assignBoundaryPropertiesFromVertexMask(int boundaryVertexMask) {
|
||||
//
|
||||
// This is strictly needed for the irregular case when a vertex is a boundary in
|
||||
// the presence of no boundary edges -- an extra-ordinary face with only one corner
|
||||
@ -179,7 +179,7 @@ offsetAndPermuteIndices(Far::Index const indices[], int count,
|
||||
// The patch vertices for boundary and corner patches
|
||||
// are assigned index values even though indices will
|
||||
// be undefined along boundary and corner edges.
|
||||
// When the resulting patch tables are going to be used
|
||||
// When the resulting patch table is going to be used
|
||||
// as indices for drawing, it is convenient for invalid
|
||||
// indices to be replaced with known good values, such
|
||||
// as the first un-permuted index, which is the index
|
||||
@ -217,7 +217,7 @@ class FVarChannelCursor {
|
||||
public:
|
||||
|
||||
FVarChannelCursor(TopologyRefiner const & refiner,
|
||||
PatchTablesFactory::Options options) {
|
||||
PatchTableFactory::Options options) {
|
||||
if (options.generateFVarTables) {
|
||||
// If client-code does not select specific channels, default to all
|
||||
// the channels in the refiner.
|
||||
@ -278,13 +278,13 @@ private:
|
||||
// Adaptive Context
|
||||
//
|
||||
// Helper class aggregating transient contextual data structures during the
|
||||
// creation of feature adaptive patch tables. The structure simplifies
|
||||
// creation of feature adaptive patch table. The structure simplifies
|
||||
// the function prototypes of high-level private methods in the factory.
|
||||
// This helps keeping the factory class stateless.
|
||||
//
|
||||
// Note : struct members are not re-entrant nor are they intended to be !
|
||||
//
|
||||
struct PatchTablesFactory::AdaptiveContext {
|
||||
struct PatchTableFactory::AdaptiveContext {
|
||||
|
||||
public:
|
||||
AdaptiveContext(TopologyRefiner const & refiner, Options options);
|
||||
@ -293,8 +293,8 @@ public:
|
||||
|
||||
Options const options;
|
||||
|
||||
// The patch tables being created
|
||||
PatchTables * tables;
|
||||
// The patch table being created
|
||||
PatchTable * table;
|
||||
|
||||
public:
|
||||
|
||||
@ -341,16 +341,16 @@ public:
|
||||
};
|
||||
|
||||
// Constructor
|
||||
PatchTablesFactory::AdaptiveContext::AdaptiveContext(
|
||||
PatchTableFactory::AdaptiveContext::AdaptiveContext(
|
||||
TopologyRefiner const & ref, Options opts) :
|
||||
refiner(ref), options(opts), tables(0),
|
||||
refiner(ref), options(opts), table(0),
|
||||
fvarChannelCursor(ref, opts) {
|
||||
|
||||
fvarPatchValues.resize(fvarChannelCursor.size());
|
||||
}
|
||||
|
||||
void
|
||||
PatchTablesFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) {
|
||||
PatchTableFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) {
|
||||
|
||||
FVarChannelCursor & fvc = fvarChannelCursor;
|
||||
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
|
||||
@ -367,31 +367,31 @@ PatchTablesFactory::AdaptiveContext::AllocateFVarPatchValues(int npatches) {
|
||||
}
|
||||
|
||||
bool
|
||||
PatchTablesFactory::AdaptiveContext::RequiresFVarPatches() const {
|
||||
PatchTableFactory::AdaptiveContext::RequiresFVarPatches() const {
|
||||
return not fvarPatchValues.empty();
|
||||
}
|
||||
|
||||
//
|
||||
// Reserves tables based on the contents of the PatchArrayVector in the PatchTables:
|
||||
// Reserves tables based on the contents of the PatchArrayVector in the PatchTable:
|
||||
//
|
||||
void
|
||||
PatchTablesFactory::allocateVertexTables(PatchTables * tables, int /* nlevels */, bool hasSharpness) {
|
||||
PatchTableFactory::allocateVertexTables(PatchTable * table, int /* nlevels */, bool hasSharpness) {
|
||||
|
||||
int ncvs = 0, npatches = 0;
|
||||
for (int i=0; i<tables->GetNumPatchArrays(); ++i) {
|
||||
npatches += tables->GetNumPatches(i);
|
||||
ncvs += tables->GetNumControlVertices(i);
|
||||
for (int i=0; i<table->GetNumPatchArrays(); ++i) {
|
||||
npatches += table->GetNumPatches(i);
|
||||
ncvs += table->GetNumControlVertices(i);
|
||||
}
|
||||
|
||||
if (ncvs==0 or npatches==0)
|
||||
return;
|
||||
|
||||
tables->_patchVerts.resize( ncvs );
|
||||
table->_patchVerts.resize( ncvs );
|
||||
|
||||
tables->_paramTable.resize( npatches );
|
||||
table->_paramTable.resize( npatches );
|
||||
|
||||
if (hasSharpness) {
|
||||
tables->_sharpnessIndices.resize( npatches, Vtr::INDEX_INVALID );
|
||||
table->_sharpnessIndices.resize( npatches, Vtr::INDEX_INVALID );
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,11 +399,11 @@ PatchTablesFactory::allocateVertexTables(PatchTables * tables, int /* nlevels */
|
||||
// Allocate face-varying tables
|
||||
//
|
||||
void
|
||||
PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner,
|
||||
Options options, int npatches, PatchTables * tables) {
|
||||
PatchTableFactory::allocateFVarChannels(TopologyRefiner const & refiner,
|
||||
Options options, int npatches, PatchTable * table) {
|
||||
|
||||
assert(options.generateFVarTables and
|
||||
refiner.GetNumFVarChannels()>0 and npatches>0 and tables);
|
||||
refiner.GetNumFVarChannels()>0 and npatches>0 and table);
|
||||
|
||||
// Create a channel cursor to iterate over client-selected channels or
|
||||
// default to the channels found in the TopologyRefiner
|
||||
@ -412,7 +412,7 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner,
|
||||
return;
|
||||
}
|
||||
|
||||
tables->allocateFVarPatchChannels(fvc.size());
|
||||
table->allocateFVarPatchChannels(fvc.size());
|
||||
|
||||
// Iterate with the cursor to initialize each channel
|
||||
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
|
||||
@ -420,7 +420,7 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner,
|
||||
Sdc::Options::FVarLinearInterpolation interpolation =
|
||||
refiner.GetFVarLinearInterpolation(*fvc);
|
||||
|
||||
tables->setFVarPatchChannelLinearInterpolation(fvc.pos(), interpolation);
|
||||
table->setFVarPatchChannelLinearInterpolation(fvc.pos(), interpolation);
|
||||
|
||||
int nverts = 0;
|
||||
if (interpolation==Sdc::Options::FVAR_LINEAR_ALL) {
|
||||
@ -428,20 +428,20 @@ PatchTablesFactory::allocateFVarChannels(TopologyRefiner const & refiner,
|
||||
PatchDescriptor::Type type = options.triangulateQuads ?
|
||||
PatchDescriptor::TRIANGLES : PatchDescriptor::QUADS;
|
||||
|
||||
tables->setFVarPatchChannelPatchesType(fvc.pos(), type);
|
||||
table->setFVarPatchChannelPatchesType(fvc.pos(), type);
|
||||
|
||||
nverts =
|
||||
npatches * PatchDescriptor::GetNumFVarControlVertices(type);
|
||||
|
||||
}
|
||||
tables->allocateChannelValues(fvc.pos(), npatches, nverts);
|
||||
table->allocateChannelValues(fvc.pos(), npatches, nverts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// gather face-varying patch points
|
||||
int
|
||||
PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
|
||||
PatchTableFactory::gatherFVarData(AdaptiveContext & context, int level,
|
||||
Index faceIndex, Index levelFaceOffset, int rotation,
|
||||
Index const * levelFVarVertOffsets, Index fofss, Index ** fptrs) {
|
||||
|
||||
@ -451,7 +451,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
|
||||
|
||||
TopologyRefiner const & refiner = context.refiner;
|
||||
|
||||
PatchTables * tables = context.tables;
|
||||
PatchTable * table = context.table;
|
||||
|
||||
assert((levelFaceOffset + faceIndex)<(int)context.patchTags.size());
|
||||
PatchFaceTag & vertexPatchTag = context.patchTags[levelFaceOffset + faceIndex];
|
||||
@ -572,7 +572,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
|
||||
}
|
||||
|
||||
Vtr::Array<PatchDescriptor::Type> patchTypes =
|
||||
tables->getFVarPatchTypes(fvc.pos());
|
||||
table->getFVarPatchTypes(fvc.pos());
|
||||
assert(not patchTypes.empty());
|
||||
patchTypes[fofss] = fvarPatchType;
|
||||
|
||||
@ -652,7 +652,7 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
|
||||
// a pointer to the next descriptor
|
||||
//
|
||||
PatchParam *
|
||||
PatchTablesFactory::computePatchParam(
|
||||
PatchTableFactory::computePatchParam(
|
||||
TopologyRefiner const & refiner, PtexIndices const &ptexIndices,
|
||||
int depth, Vtr::Index faceIndex, int boundaryMask,
|
||||
int transitionMask, PatchParam *coord) {
|
||||
@ -665,7 +665,7 @@ PatchTablesFactory::computePatchParam(
|
||||
v = 0,
|
||||
ofs = 1;
|
||||
|
||||
bool nonquad = (refiner.GetFaceVertices(depth, faceIndex).size() != 4);
|
||||
bool nonquad = (refiner.GetLevel(depth).GetFaceVertices(faceIndex).size() != 4);
|
||||
|
||||
for (int i = depth; i > 0; --i) {
|
||||
Vtr::Refinement const& refinement = refiner.getRefinement(i-1);
|
||||
@ -733,8 +733,8 @@ assignSharpnessIndex(float sharpness, std::vector<float> & sharpnessValues) {
|
||||
// cases. In the past, more additional arguments were passed to the uniform version,
|
||||
// but that may no longer be necessary (see notes in the uniform version below)...
|
||||
//
|
||||
PatchTables *
|
||||
PatchTablesFactory::Create(TopologyRefiner const & refiner, Options options) {
|
||||
PatchTable *
|
||||
PatchTableFactory::Create(TopologyRefiner const & refiner, Options options) {
|
||||
|
||||
if (refiner.IsUniform()) {
|
||||
return createUniform(refiner, options);
|
||||
@ -743,8 +743,8 @@ PatchTablesFactory::Create(TopologyRefiner const & refiner, Options options) {
|
||||
}
|
||||
}
|
||||
|
||||
PatchTables *
|
||||
PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options options) {
|
||||
PatchTable *
|
||||
PatchTableFactory::createUniform(TopologyRefiner const & refiner, Options options) {
|
||||
|
||||
assert(refiner.IsUniform());
|
||||
|
||||
@ -772,22 +772,26 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
|
||||
assert(ptype!=PatchDescriptor::NON_PATCH);
|
||||
|
||||
//
|
||||
// Create the instance of the tables and allocate and initialize its members.
|
||||
// Create the instance of the table and allocate and initialize its members.
|
||||
//
|
||||
PatchTables * tables = new PatchTables(maxvalence);
|
||||
PatchTable * table = new PatchTable(maxvalence);
|
||||
|
||||
tables->_numPtexFaces = ptexIndices.GetNumFaces();
|
||||
table->_numPtexFaces = ptexIndices.GetNumFaces();
|
||||
|
||||
tables->reservePatchArrays(nlevels);
|
||||
table->reservePatchArrays(nlevels);
|
||||
|
||||
PatchDescriptor desc(ptype);
|
||||
|
||||
// generate patch arrays
|
||||
for (int level=firstlevel, poffset=0, voffset=0; level<=maxlevel; ++level) {
|
||||
|
||||
int npatches = refiner.GetNumFaces(level);
|
||||
TopologyLevel const & refLevel = refiner.GetLevel(level);
|
||||
|
||||
int npatches = refLevel.GetNumFaces();
|
||||
if (refiner.HasHoles()) {
|
||||
npatches -= refiner.GetNumHoles(level);
|
||||
for (int i = npatches - 1; i >= 0; --i) {
|
||||
npatches -= refLevel.IsFaceHole(i);
|
||||
}
|
||||
}
|
||||
assert(npatches>=0);
|
||||
|
||||
@ -795,31 +799,31 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
|
||||
npatches *= 2;
|
||||
|
||||
if (level>=firstlevel) {
|
||||
tables->pushPatchArray(desc, npatches, &voffset, &poffset, 0);
|
||||
table->pushPatchArray(desc, npatches, &voffset, &poffset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate various tables
|
||||
allocateVertexTables( tables, 0, /*hasSharpness=*/false );
|
||||
allocateVertexTables( table, 0, /*hasSharpness=*/false );
|
||||
|
||||
bool generateFVarPatches=false;
|
||||
FVarChannelCursor fvc(refiner, options);
|
||||
if (options.generateFVarTables and fvc.size()>0) {
|
||||
int npatches = tables->GetNumPatchesTotal();
|
||||
allocateFVarChannels(refiner, options, npatches, tables);
|
||||
assert(fvc.size() == tables->GetNumFVarChannels());
|
||||
int npatches = table->GetNumPatchesTotal();
|
||||
allocateFVarChannels(refiner, options, npatches, table);
|
||||
assert(fvc.size() == table->GetNumFVarChannels());
|
||||
}
|
||||
|
||||
//
|
||||
// Now populate the patches:
|
||||
//
|
||||
|
||||
Index * iptr = &tables->_patchVerts[0];
|
||||
PatchParam * pptr = &tables->_paramTable[0];
|
||||
Index * iptr = &table->_patchVerts[0];
|
||||
PatchParam * pptr = &table->_paramTable[0];
|
||||
Index ** fptr = 0;
|
||||
|
||||
Index levelVertOffset = options.generateAllLevels ?
|
||||
0 : refiner.GetNumVertices(0);
|
||||
0 : refiner.GetLevel(0).GetNumVertices();
|
||||
|
||||
Index * levelFVarVertOffsets = 0;
|
||||
if (generateFVarPatches) {
|
||||
@ -829,21 +833,23 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
|
||||
|
||||
fptr = (Index **)alloca(fvc.size()*sizeof(Index *));
|
||||
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
|
||||
fptr[fvc.pos()] = tables->getFVarPatchesValues(fvc.pos()).begin();
|
||||
fptr[fvc.pos()] = table->getFVarPatchesValues(fvc.pos()).begin();
|
||||
}
|
||||
}
|
||||
|
||||
for (int level=1; level<=maxlevel; ++level) {
|
||||
|
||||
int nfaces = refiner.GetNumFaces(level);
|
||||
TopologyLevel const & refLevel = refiner.GetLevel(level);
|
||||
|
||||
int nfaces = refLevel.GetNumFaces();
|
||||
if (level>=firstlevel) {
|
||||
for (int face=0; face<nfaces; ++face) {
|
||||
|
||||
if (refiner.HasHoles() and refiner.IsFaceHole(level, face)) {
|
||||
if (refiner.HasHoles() and refLevel.IsFaceHole(face)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ConstIndexArray fverts = refiner.GetFaceVertices(level, face);
|
||||
ConstIndexArray fverts = refLevel.GetFaceVertices(face);
|
||||
for (int vert=0; vert<fverts.size(); ++vert) {
|
||||
*iptr++ = levelVertOffset + fverts[vert];
|
||||
}
|
||||
@ -852,9 +858,9 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
|
||||
|
||||
if (generateFVarPatches) {
|
||||
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) {
|
||||
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()]+=fvalues.size();
|
||||
@ -884,17 +890,17 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
|
||||
}
|
||||
|
||||
if (options.generateAllLevels) {
|
||||
levelVertOffset += refiner.GetNumVertices(level);
|
||||
levelVertOffset += refiner.GetLevel(level).GetNumVertices();
|
||||
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
|
||||
levelFVarVertOffsets[fvc.pos()] += refiner.GetNumFVarValues(level, fvc.pos());
|
||||
levelFVarVertOffsets[fvc.pos()] += refiner.GetLevel(level).GetNumFVarValues(fvc.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
return tables;
|
||||
return table;
|
||||
}
|
||||
|
||||
PatchTables *
|
||||
PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options options) {
|
||||
PatchTable *
|
||||
PatchTableFactory::createAdaptive(TopologyRefiner const & refiner, Options options) {
|
||||
|
||||
assert(not refiner.IsUniform());
|
||||
|
||||
@ -909,15 +915,15 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
|
||||
identifyAdaptivePatches(context);
|
||||
|
||||
//
|
||||
// Create the instance of the tables and allocate and initialize its members based on
|
||||
// Create the instance of the table and allocate and initialize its members based on
|
||||
// the inventory of patches determined above:
|
||||
//
|
||||
int maxValence = refiner.GetMaxValence();
|
||||
|
||||
context.tables = new PatchTables(maxValence);
|
||||
context.table = new PatchTable(maxValence);
|
||||
|
||||
// Populate the patch array descriptors
|
||||
context.tables->reservePatchArrays(context.patchInventory.getNumPatchArrays());
|
||||
context.table->reservePatchArrays(context.patchInventory.getNumPatchArrays());
|
||||
|
||||
// Sort through the inventory and push back non-empty patch arrays
|
||||
ConstPatchDescriptorArray const & descs =
|
||||
@ -926,21 +932,21 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
|
||||
int voffset=0, poffset=0, qoffset=0;
|
||||
for (int i=0; i<descs.size(); ++i) {
|
||||
PatchDescriptor desc = descs[i];
|
||||
context.tables->pushPatchArray(desc,
|
||||
context.table->pushPatchArray(desc,
|
||||
context.patchInventory.getValue(desc), &voffset, &poffset, &qoffset );
|
||||
}
|
||||
|
||||
context.tables->_numPtexFaces = ptexIndices.GetNumFaces();
|
||||
context.table->_numPtexFaces = ptexIndices.GetNumFaces();
|
||||
|
||||
// Allocate various tables
|
||||
bool hasSharpness = context.options.useSingleCreasePatch;
|
||||
allocateVertexTables(context.tables, 0, hasSharpness);
|
||||
allocateVertexTables(context.table, 0, hasSharpness);
|
||||
|
||||
if (context.RequiresFVarPatches()) {
|
||||
|
||||
int npatches = context.tables->GetNumPatchesTotal();
|
||||
int npatches = context.table->GetNumPatchesTotal();
|
||||
|
||||
allocateFVarChannels(refiner, options, npatches, context.tables);
|
||||
allocateFVarChannels(refiner, options, npatches, context.table);
|
||||
|
||||
// Reserve temporary non-sparse storage for non-linear fvar channels.
|
||||
// FVar Values for these channels are copied into the final
|
||||
@ -954,7 +960,7 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
|
||||
//
|
||||
populateAdaptivePatches(context, ptexIndices);
|
||||
|
||||
return context.tables;
|
||||
return context.table;
|
||||
}
|
||||
|
||||
//
|
||||
@ -963,7 +969,7 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
|
||||
// later with no additional analysis.
|
||||
//
|
||||
void
|
||||
PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) {
|
||||
PatchTableFactory::identifyAdaptivePatches(AdaptiveContext & context) {
|
||||
|
||||
TopologyRefiner const & refiner = context.refiner;
|
||||
|
||||
@ -1225,12 +1231,12 @@ PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) {
|
||||
// idenified.
|
||||
//
|
||||
void
|
||||
PatchTablesFactory::populateAdaptivePatches(
|
||||
PatchTableFactory::populateAdaptivePatches(
|
||||
AdaptiveContext & context, PtexIndices const & ptexIndices) {
|
||||
|
||||
TopologyRefiner const & refiner = context.refiner;
|
||||
|
||||
PatchTables * tables = context.tables;
|
||||
PatchTable * table = context.table;
|
||||
|
||||
//
|
||||
// Setup convenience pointers at the beginning of each patch array for each
|
||||
@ -1249,33 +1255,33 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
|
||||
PatchDescriptor desc = descs[i];
|
||||
|
||||
Index arrayIndex = tables->findPatchArray(desc);
|
||||
Index arrayIndex = table->findPatchArray(desc);
|
||||
|
||||
if (arrayIndex==Vtr::INDEX_INVALID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iptrs.getValue(desc) = tables->getPatchArrayVertices(arrayIndex).begin();
|
||||
pptrs.getValue(desc) = tables->getPatchParams(arrayIndex).begin();
|
||||
iptrs.getValue(desc) = table->getPatchArrayVertices(arrayIndex).begin();
|
||||
pptrs.getValue(desc) = table->getPatchParams(arrayIndex).begin();
|
||||
if (context.options.useSingleCreasePatch) {
|
||||
sptrs.getValue(desc) = tables->getSharpnessIndices(arrayIndex);
|
||||
sptrs.getValue(desc) = table->getSharpnessIndices(arrayIndex);
|
||||
}
|
||||
|
||||
if (context.RequiresFVarPatches()) {
|
||||
|
||||
Index & offsets = fofss.getValue(desc);
|
||||
offsets = tables->getPatchIndex(arrayIndex, 0);
|
||||
offsets = table->getPatchIndex(arrayIndex, 0);
|
||||
|
||||
// XXXX manuelk this stuff will go away as we use offsets from FVarPatchChannel
|
||||
FVarChannelCursor & fvc = context.fvarChannelCursor;
|
||||
assert(fvc.size() == tables->GetNumFVarChannels());
|
||||
assert(fvc.size() == table->GetNumFVarChannels());
|
||||
|
||||
Index ** fptr = (Index **)alloca(fvc.size()*sizeof(Index *));
|
||||
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
|
||||
|
||||
Index pidx = tables->getPatchIndex(arrayIndex, 0);
|
||||
Index pidx = table->getPatchIndex(arrayIndex, 0);
|
||||
int ofs = pidx * 4;
|
||||
fptr[fvc.pos()] = &tables->getFVarPatchesValues(fvc.pos())[ofs];
|
||||
fptr[fvc.pos()] = &table->getFVarPatchesValues(fvc.pos())[ofs];
|
||||
}
|
||||
fptrs.getValue(desc) = fptr;
|
||||
}
|
||||
@ -1371,7 +1377,7 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
iptrs.R += 16;
|
||||
pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, boundaryMask, transitionMask, pptrs.R);
|
||||
// XXX: sharpness will be integrated into patch param soon.
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues);
|
||||
|
||||
fofss.R += gatherFVarData(context,
|
||||
i, faceIndex, levelFaceOffset, /*rotation*/0, levelFVarVertOffsets, fofss.R, fptrs.R);
|
||||
@ -1389,7 +1395,7 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
|
||||
iptrs.R += 16;
|
||||
pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, /*boundary*/0, transitionMask, pptrs.R);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(sharpness, tables->_sharpnessValues);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(sharpness, table->_sharpnessValues);
|
||||
|
||||
fofss.R += gatherFVarData(context,
|
||||
i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.R, fptrs.R);
|
||||
@ -1410,7 +1416,7 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
iptrs.GP += cvs.size();
|
||||
pptrs.GP = computePatchParam(
|
||||
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.GP);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues);
|
||||
fofss.GP += gatherFVarData(context,
|
||||
i, faceIndex, levelFaceOffset,
|
||||
0, levelFVarVertOffsets, fofss.GP, fptrs.GP);
|
||||
@ -1425,7 +1431,7 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
iptrs.R += cvs.size();
|
||||
pptrs.R = computePatchParam(
|
||||
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.R);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues);
|
||||
fofss.R += gatherFVarData(context,
|
||||
i, faceIndex, levelFaceOffset,
|
||||
0, levelFVarVertOffsets, fofss.R, fptrs.R);
|
||||
@ -1441,7 +1447,7 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
iptrs.G += cvs.size();
|
||||
pptrs.G = computePatchParam(
|
||||
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.G);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues);
|
||||
fofss.G += gatherFVarData(context,
|
||||
i, faceIndex, levelFaceOffset,
|
||||
0, levelFVarVertOffsets, fofss.G, fptrs.G);
|
||||
@ -1450,7 +1456,7 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
iptrs.GB += cvs.size();
|
||||
pptrs.GB = computePatchParam(
|
||||
refiner, ptexIndices, i, faceIndex, /*boundary*/0, /*transition*/0, pptrs.GB);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, tables->_sharpnessValues);
|
||||
if (sptrs.R) *sptrs.R++ = assignSharpnessIndex(0, table->_sharpnessValues);
|
||||
fofss.GB += gatherFVarData(context,
|
||||
i, faceIndex, levelFaceOffset,
|
||||
0, levelFVarVertOffsets, fofss.GB, fptrs.GB);
|
||||
@ -1480,24 +1486,24 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
// finalize end patches
|
||||
switch(context.options.GetEndCapType()) {
|
||||
case Options::ENDCAP_GREGORY_BASIS:
|
||||
tables->_vertexStencilTables =
|
||||
endCapGregoryBasis->CreateVertexStencilTables();
|
||||
tables->_varyingStencilTables =
|
||||
endCapGregoryBasis->CreateVaryingStencilTables();
|
||||
table->_vertexStencilTable =
|
||||
endCapGregoryBasis->CreateVertexStencilTable();
|
||||
table->_varyingStencilTable =
|
||||
endCapGregoryBasis->CreateVaryingStencilTable();
|
||||
delete endCapGregoryBasis;
|
||||
break;
|
||||
case Options::ENDCAP_BSPLINE_BASIS:
|
||||
tables->_vertexStencilTables =
|
||||
endCapBSpline->CreateVertexStencilTables();
|
||||
tables->_varyingStencilTables =
|
||||
endCapBSpline->CreateVaryingStencilTables();
|
||||
table->_vertexStencilTable =
|
||||
endCapBSpline->CreateVertexStencilTable();
|
||||
table->_varyingStencilTable =
|
||||
endCapBSpline->CreateVaryingStencilTable();
|
||||
delete endCapBSpline;
|
||||
break;
|
||||
case Options::ENDCAP_LEGACY_GREGORY:
|
||||
endCapLegacyGregory->Finalize(
|
||||
tables->GetMaxValence(),
|
||||
&tables->_quadOffsetsTable,
|
||||
&tables->_vertexValenceTable);
|
||||
table->GetMaxValence(),
|
||||
&table->_quadOffsetsTable,
|
||||
&table->_vertexValenceTable);
|
||||
delete endCapLegacyGregory;
|
||||
break;
|
||||
default:
|
||||
@ -1511,8 +1517,8 @@ PatchTablesFactory::populateAdaptivePatches(
|
||||
FVarChannelCursor & fvc = context.fvarChannelCursor;
|
||||
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
|
||||
|
||||
if (tables->GetFVarChannelLinearInterpolation(fvc.pos())!=Sdc::Options::FVAR_LINEAR_ALL) {
|
||||
tables->setBicubicFVarPatchChannelValues(fvc.pos(),
|
||||
if (table->GetFVarChannelLinearInterpolation(fvc.pos())!=Sdc::Options::FVAR_LINEAR_ALL) {
|
||||
table->setBicubicFVarPatchChannelValues(fvc.pos(),
|
||||
context.fvarPatchSize, context.fvarPatchValues[fvc.pos()]);
|
||||
}
|
||||
}
|
@ -22,12 +22,12 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H
|
||||
#define OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H
|
||||
#ifndef OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H
|
||||
#define OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -40,12 +40,12 @@ namespace Far {
|
||||
class PtexIndices;
|
||||
class TopologyRefiner;
|
||||
|
||||
class PatchTablesFactory {
|
||||
class PatchTableFactory {
|
||||
public:
|
||||
// PatchFaceTag
|
||||
// A simple struct containing all information gathered about a face that is relevant
|
||||
// to constructing a patch for it (some of these enums should probably be defined more
|
||||
// as part of PatchTables)
|
||||
// as part of PatchTable)
|
||||
//
|
||||
// Like the HbrFace<T>::AdaptiveFlags, this struct aggregates all of the face tags
|
||||
// supporting feature adaptive refinement. For now it is not used elsewhere and can
|
||||
@ -125,16 +125,16 @@ public:
|
||||
int const * fvarChannelIndices; ///< List containing the indices of the channels selected for the factory
|
||||
};
|
||||
|
||||
/// \brief Factory constructor for PatchTables
|
||||
/// \brief Factory constructor for PatchTable
|
||||
///
|
||||
/// @param refiner TopologyRefiner from which to generate patches
|
||||
///
|
||||
/// @param options Options controlling the creation of the tables
|
||||
/// @param options Options controlling the creation of the table
|
||||
///
|
||||
/// @return A new instance of PatchTables
|
||||
/// @return A new instance of PatchTable
|
||||
///
|
||||
static PatchTables * Create(TopologyRefiner const & refiner,
|
||||
Options options=Options());
|
||||
static PatchTable * Create(TopologyRefiner const & refiner,
|
||||
Options options=Options());
|
||||
|
||||
private:
|
||||
//
|
||||
@ -145,11 +145,11 @@ private:
|
||||
//
|
||||
// Methods for allocating and managing the patch table data arrays:
|
||||
//
|
||||
static PatchTables * createUniform(TopologyRefiner const & refiner,
|
||||
Options options);
|
||||
static PatchTable * createUniform(TopologyRefiner const & refiner,
|
||||
Options options);
|
||||
|
||||
static PatchTables * createAdaptive(TopologyRefiner const & refiner,
|
||||
Options options);
|
||||
static PatchTable * createAdaptive(TopologyRefiner const & refiner,
|
||||
Options options);
|
||||
|
||||
//
|
||||
// High-level methods for identifying and populating patches associated with faces:
|
||||
@ -160,10 +160,10 @@ private:
|
||||
static void populateAdaptivePatches(AdaptiveContext & state,
|
||||
PtexIndices const &ptexIndices);
|
||||
|
||||
static void allocateVertexTables(PatchTables * tables, int nlevels, bool hasSharpness);
|
||||
static void allocateVertexTables(PatchTable * table, int nlevels, bool hasSharpness);
|
||||
|
||||
static void allocateFVarChannels(TopologyRefiner const & refiner,
|
||||
Options options, int npatches, PatchTables * tables);
|
||||
Options options, int npatches, PatchTable * table);
|
||||
|
||||
static PatchParam * computePatchParam(TopologyRefiner const & refiner,
|
||||
PtexIndices const & ptexIndices,
|
||||
@ -184,4 +184,4 @@ using namespace OPENSUBDIV_VERSION;
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif /* OPENSUBDIV3_FAR_PATCH_TABLES_FACTORY_H */
|
||||
#endif /* OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H */
|
@ -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.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_FAR_STENCILTABLES_H
|
||||
#define OPENSUBDIV3_FAR_STENCILTABLES_H
|
||||
#ifndef OPENSUBDIV3_FAR_STENCILTABLE_H
|
||||
#define OPENSUBDIV3_FAR_STENCILTABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/types.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
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
|
||||
///
|
||||
/// Allows access and manipulation of a single stencil in a StencilTables.
|
||||
/// Allows access and manipulation of a single stencil in a StencilTable.
|
||||
///
|
||||
class Stencil {
|
||||
|
||||
@ -100,8 +178,8 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class StencilTablesFactory;
|
||||
friend class LimitStencilTablesFactory;
|
||||
friend class StencilTableFactory;
|
||||
friend class LimitStencilTableFactory;
|
||||
|
||||
int * _size;
|
||||
Index * _indices;
|
||||
@ -120,7 +198,24 @@ protected:
|
||||
/// recomputed simply by applying the blending weights to the series of coarse
|
||||
/// control vertices.
|
||||
///
|
||||
class StencilTables {
|
||||
class StencilTable {
|
||||
StencilTable(int numControlVerts,
|
||||
std::vector<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:
|
||||
|
||||
@ -134,7 +229,7 @@ public:
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// \brief Returns a Stencil at index i in the tables
|
||||
/// \brief Returns a Stencil at index i in the table
|
||||
Stencil GetStencil(Index i) const;
|
||||
|
||||
/// \brief Returns the number of control vertices of each stencil in the table
|
||||
@ -157,7 +252,7 @@ public:
|
||||
return _weights;
|
||||
}
|
||||
|
||||
/// \brief Returns the stencil at index i in the tables
|
||||
/// \brief Returns the stencil at index i in the table
|
||||
Stencil operator[] (Index index) const;
|
||||
|
||||
/// \brief Updates point values based on the control values
|
||||
@ -202,9 +297,12 @@ protected:
|
||||
void resize(int nstencils, int nelems);
|
||||
|
||||
protected:
|
||||
StencilTables() : _numControlVertices(0) {}
|
||||
StencilTable() : _numControlVertices(0) {}
|
||||
StencilTable(int numControlVerts)
|
||||
: _numControlVertices(numControlVerts)
|
||||
{ }
|
||||
|
||||
friend class StencilTablesFactory;
|
||||
friend class StencilTableFactory;
|
||||
// XXX: temporarily, GregoryBasis class will go away.
|
||||
friend class GregoryBasis;
|
||||
|
||||
@ -267,8 +365,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
friend class StencilTablesFactory;
|
||||
friend class LimitStencilTablesFactory;
|
||||
friend class StencilTableFactory;
|
||||
friend class LimitStencilTableFactory;
|
||||
|
||||
float * _duWeights, // pointer to stencil u derivative limit weights
|
||||
* _dvWeights; // pointer to stencil v derivative limit weights
|
||||
@ -277,10 +375,33 @@ private:
|
||||
/// \brief Table of limit subdivision stencils.
|
||||
///
|
||||
///
|
||||
class LimitStencilTables : public StencilTables {
|
||||
class LimitStencilTable : public StencilTable {
|
||||
|
||||
public:
|
||||
|
||||
// TODO: share construction logic
|
||||
LimitStencilTable(int numControlVerts,
|
||||
std::vector<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
|
||||
std::vector<float> const & GetDuWeights() const {
|
||||
return _duWeights;
|
||||
@ -318,13 +439,13 @@ public:
|
||||
|
||||
/// \brief Clears the stencils from the table
|
||||
void Clear() {
|
||||
StencilTables::Clear();
|
||||
StencilTable::Clear();
|
||||
_duWeights.clear();
|
||||
_dvWeights.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LimitStencilTablesFactory;
|
||||
friend class LimitStencilTableFactory;
|
||||
|
||||
// Resize the table arrays (factory helper)
|
||||
void resize(int nstencils, int nelems);
|
||||
@ -337,7 +458,7 @@ private:
|
||||
|
||||
// Update values by appling cached stencil weights to new control values
|
||||
template <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 {
|
||||
|
||||
int const * sizes = &_sizes.at(0);
|
||||
@ -370,7 +491,7 @@ StencilTables::update(T const *controlValues, T *values,
|
||||
}
|
||||
|
||||
inline void
|
||||
StencilTables::generateOffsets() {
|
||||
StencilTable::generateOffsets() {
|
||||
Index offset=0;
|
||||
int noffsets = (int)_sizes.size();
|
||||
_offsets.resize(noffsets);
|
||||
@ -381,7 +502,7 @@ StencilTables::generateOffsets() {
|
||||
}
|
||||
|
||||
inline void
|
||||
StencilTables::resize(int nstencils, int nelems) {
|
||||
StencilTable::resize(int nstencils, int nelems) {
|
||||
|
||||
_sizes.resize(nstencils);
|
||||
_indices.resize(nelems);
|
||||
@ -390,7 +511,7 @@ StencilTables::resize(int nstencils, int nelems) {
|
||||
|
||||
// Returns a Stencil at index i in the table
|
||||
inline Stencil
|
||||
StencilTables::GetStencil(Index i) const {
|
||||
StencilTable::GetStencil(Index i) const {
|
||||
|
||||
assert((not _offsets.empty()) and i<(int)_offsets.size());
|
||||
|
||||
@ -402,14 +523,14 @@ StencilTables::GetStencil(Index i) const {
|
||||
}
|
||||
|
||||
inline Stencil
|
||||
StencilTables::operator[] (Index index) const {
|
||||
StencilTable::operator[] (Index index) const {
|
||||
return GetStencil(index);
|
||||
}
|
||||
|
||||
inline void
|
||||
LimitStencilTables::resize(int nstencils, int nelems) {
|
||||
LimitStencilTable::resize(int nstencils, int nelems) {
|
||||
|
||||
StencilTables::resize(nstencils, nelems);
|
||||
StencilTable::resize(nstencils, nelems);
|
||||
_duWeights.resize(nelems);
|
||||
_dvWeights.resize(nelems);
|
||||
}
|
||||
@ -422,4 +543,4 @@ using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_FAR_STENCILTABLES_H
|
||||
#endif // OPENSUBDIV3_FAR_STENCILTABLE_H
|
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 "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -39,13 +39,13 @@ namespace Far {
|
||||
class TopologyRefiner;
|
||||
|
||||
class Stencil;
|
||||
class StencilTables;
|
||||
class StencilTable;
|
||||
class LimitStencil;
|
||||
class LimitStencilTables;
|
||||
class LimitStencilTable;
|
||||
|
||||
/// \brief A specialized factory for StencilTables
|
||||
/// \brief A specialized factory for StencilTable
|
||||
///
|
||||
class StencilTablesFactory {
|
||||
class StencilTableFactory {
|
||||
|
||||
public:
|
||||
|
||||
@ -73,7 +73,7 @@ public:
|
||||
maxLevel : 4; ///< generate stencils up to 'maxLevel'
|
||||
};
|
||||
|
||||
/// \brief Instantiates StencilTables from TopologyRefiner that have been
|
||||
/// \brief Instantiates StencilTable from TopologyRefiner that have been
|
||||
/// refined uniformly or adaptively.
|
||||
///
|
||||
/// \note The factory only creates stencils for vertices that have already
|
||||
@ -82,45 +82,45 @@ public:
|
||||
///
|
||||
/// @param refiner The TopologyRefiner containing the topology
|
||||
///
|
||||
/// @param options Options controlling the creation of the tables
|
||||
/// @param options Options controlling the creation of the table
|
||||
///
|
||||
static StencilTables const * Create(TopologyRefiner const & refiner,
|
||||
static StencilTable const * Create(TopologyRefiner const & refiner,
|
||||
Options options = Options());
|
||||
|
||||
|
||||
/// \brief Instantiates StencilTables by concatenating an array of existing
|
||||
/// stencil tables.
|
||||
/// \brief Instantiates StencilTable by concatenating an array of existing
|
||||
/// stencil table.
|
||||
///
|
||||
/// \note This factory checks that the stencil tables point to the same set
|
||||
/// \note This factory checks that the stencil table point to the same set
|
||||
/// of supporting control vertices - no re-indexing is done.
|
||||
/// GetNumControlVertices() *must* return the same value for all input
|
||||
/// tables.
|
||||
///
|
||||
/// @param numTables Number of input StencilTables
|
||||
///
|
||||
/// @param tables Array of input StencilTables
|
||||
/// @param table Array of input StencilTables
|
||||
///
|
||||
static StencilTables const * Create(int numTables, StencilTables const ** tables);
|
||||
static StencilTable const * Create(int numTables, StencilTable const ** tables);
|
||||
|
||||
|
||||
/// \brief Utility function for stencil splicing for endcap stencils.
|
||||
///
|
||||
/// @param refiner The TopologyRefiner containing the topology
|
||||
///
|
||||
/// @param baseStencilTables Input StencilTables for refined vertices
|
||||
/// @param baseStencilTable Input StencilTable for refined vertices
|
||||
///
|
||||
/// @param endCapStencilTables EndCap basis conversion stencils. This stenciltable
|
||||
/// @param endCapStencilTable EndCap basis conversion stencils. This stenciltable
|
||||
/// has to be relative to the max level of subdivision.
|
||||
///
|
||||
/// @param factorize If factorize sets to true, endcap stencils will be
|
||||
/// factorized with supporting vertices from baseStencil
|
||||
/// tables so that the endcap points can be computed
|
||||
/// table so that the endcap points can be computed
|
||||
/// directly from control vertices.
|
||||
///
|
||||
static StencilTables const * AppendEndCapStencilTables(
|
||||
static StencilTable const * AppendEndCapStencilTable(
|
||||
TopologyRefiner const &refiner,
|
||||
StencilTables const *baseStencilTables,
|
||||
StencilTables const *endCapStencilTables,
|
||||
StencilTable const *baseStencilTable,
|
||||
StencilTable const *endCapStencilTable,
|
||||
bool factorize = true);
|
||||
|
||||
private:
|
||||
@ -129,9 +129,9 @@ private:
|
||||
static void generateControlVertStencils(int numControlVerts, Stencil & dst);
|
||||
};
|
||||
|
||||
/// \brief A specialized factory for LimitStencilTables
|
||||
/// \brief A specialized factory for LimitStencilTable
|
||||
///
|
||||
/// The LimitStencilTablesFactory creates tables of limit stencils. Limit
|
||||
/// The LimitStencilTableFactory creates a table of limit stencils. Limit
|
||||
/// stencils can interpolate any arbitrary location on the limit surface.
|
||||
/// The stencils will be bilinear if the surface is refined uniformly, and
|
||||
/// bicubic if feature adaptive isolation is used instead.
|
||||
@ -140,7 +140,7 @@ private:
|
||||
/// normalized (s,t) patch coordinates. The factory exposes the LocationArray
|
||||
/// struct as a container for these location descriptors.
|
||||
///
|
||||
class LimitStencilTablesFactory {
|
||||
class LimitStencilTableFactory {
|
||||
|
||||
public:
|
||||
|
||||
@ -158,7 +158,7 @@ public:
|
||||
|
||||
typedef std::vector<LocationArray> LocationArrayVec;
|
||||
|
||||
/// \brief Instantiates LimitStencilTables from a TopologyRefiner that has
|
||||
/// \brief Instantiates LimitStencilTable from a TopologyRefiner that has
|
||||
/// been refined either uniformly or adaptively.
|
||||
///
|
||||
/// @param refiner The TopologyRefiner containing the topology
|
||||
@ -166,18 +166,18 @@ public:
|
||||
/// @param locationArrays An array of surface location descriptors
|
||||
/// (see LocationArray)
|
||||
///
|
||||
/// @param cvStencils A set of StencilTables generated from the
|
||||
/// @param cvStencils A set of StencilTable generated from the
|
||||
/// TopologyRefiner (optional: prevents redundant
|
||||
/// instanciation of the tables if available)
|
||||
/// instanciation of the table if available)
|
||||
///
|
||||
/// @param patchTables A set of PatchTables generated from the
|
||||
/// @param patchTable A set of PatchTable generated from the
|
||||
/// TopologyRefiner (optional: prevents redundant
|
||||
/// instanciation of the tables if available)
|
||||
/// instanciation of the table if available)
|
||||
///
|
||||
static LimitStencilTables const * Create(TopologyRefiner const & refiner,
|
||||
static LimitStencilTable const * Create(TopologyRefiner const & refiner,
|
||||
LocationArrayVec const & locationArrays,
|
||||
StencilTables const * cvStencils=0,
|
||||
PatchTables const * patchTables=0);
|
||||
StencilTable const * cvStencils=0,
|
||||
PatchTable const * patchTable=0);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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:
|
||||
|
@ -217,8 +217,8 @@ public:
|
||||
/// \brief Apply vertex and varying interpolation weights to a primvar
|
||||
/// buffer
|
||||
///
|
||||
/// The destination buffer must allocate an array of data for all the
|
||||
/// refined vertices (at least GetNumVerticesTotal()-GetNumVertices(0))
|
||||
/// The destination buffer must allocate an array of data for all the refined
|
||||
/// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices())
|
||||
///
|
||||
/// @param src Source primvar buffer (\ref templating control vertex data)
|
||||
///
|
||||
@ -231,7 +231,7 @@ public:
|
||||
/// level of refinement.
|
||||
///
|
||||
/// The destination buffer must allocate an array of data for all the
|
||||
/// refined vertices (at least GetNumVertices(level))
|
||||
/// refined vertices (at least GetLevel(level).GetNumVertices())
|
||||
///
|
||||
/// @param level The refinement level
|
||||
///
|
||||
@ -247,8 +247,8 @@ public:
|
||||
/// This method can be a useful alternative if the varying primvar data
|
||||
/// does not need to be re-computed over time.
|
||||
///
|
||||
/// The destination buffer must allocate an array of data for all the
|
||||
/// refined vertices (at least GetNumVerticesTotal()-GetNumVertices(0))
|
||||
/// The destination buffer must allocate an array of data for all the refined
|
||||
/// vertices (at least GetNumVerticesTotal()-GetLevel(0).GetNumVertices())
|
||||
///
|
||||
/// @param src Source primvar buffer (\ref templating control vertex data)
|
||||
///
|
||||
@ -263,7 +263,7 @@ public:
|
||||
/// does not need to be re-computed over time.
|
||||
///
|
||||
/// The destination buffer must allocate an array of data for all the
|
||||
/// refined vertices (at least GetNumVertices(level))
|
||||
/// refined vertices (at least GetLevel(level).GetNumVertices())
|
||||
///
|
||||
/// @param level The refinement level
|
||||
///
|
||||
@ -288,7 +288,7 @@ public:
|
||||
/// The source buffer must refer to an array of previously interpolated
|
||||
/// vertex data for the last refinement level. The destination buffer
|
||||
/// must allocate an array for all vertices at the last refinement level
|
||||
/// (at least GetNumVertices(GetMaxLevel()))
|
||||
/// (at least GetLevel(GetMaxLevel()).GetNumVertices())
|
||||
///
|
||||
/// @param src Source primvar buffer (refined vertex data) for last level
|
||||
///
|
||||
@ -317,73 +317,6 @@ public:
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
//
|
||||
// Access to data per-level -- being made obsolete via this->GetLevel(level).Method():
|
||||
//
|
||||
// Component inventory:
|
||||
int GetNumVertices(int level) const { return GetLevel(level).GetNumVertices(); }
|
||||
int GetNumEdges(int level) const { return GetLevel(level).GetNumEdges(); }
|
||||
int GetNumFaces(int level) const { return GetLevel(level).GetNumFaces(); }
|
||||
int GetNumFaceVertices(int level) const { return GetLevel(level).GetNumFaceVertices(); }
|
||||
|
||||
// Component tags:
|
||||
float GetEdgeSharpness(int level, Index e) const { return GetLevel(level).GetEdgeSharpness(e); }
|
||||
float GetVertexSharpness(int level, Index v) const { return GetLevel(level).GetVertexSharpness(v); }
|
||||
bool IsFaceHole(int level, Index f) const { return GetLevel(level).IsFaceHole(f); }
|
||||
|
||||
Sdc::Crease::Rule GetVertexRule(int level, Index v) const { return GetLevel(level).GetVertexRule(v); }
|
||||
|
||||
// Face-varying values:
|
||||
int GetNumFVarValues(int level, int channel = 0) const { return GetLevel(level).GetNumFVarValues(channel); }
|
||||
ConstIndexArray GetFVarFaceValues(int level, Index f, int channel = 0) const { return GetLevel(level).GetFVarFaceValues(f, channel); }
|
||||
|
||||
// Component neighbors:
|
||||
ConstIndexArray GetFaceVertices(int level, Index f) const { return GetLevel(level).GetFaceVertices(f); }
|
||||
ConstIndexArray GetFaceEdges(int level, Index f) const { return GetLevel(level).GetFaceEdges(f); }
|
||||
ConstIndexArray GetEdgeVertices(int level, Index e) const { return GetLevel(level).GetEdgeVertices(e); }
|
||||
ConstIndexArray GetEdgeFaces(int level, Index e) const { return GetLevel(level).GetEdgeFaces(e); }
|
||||
ConstIndexArray GetVertexFaces(int level, Index v) const { return GetLevel(level).GetVertexFaces(v); }
|
||||
ConstIndexArray GetVertexEdges(int level, Index v) const { return GetLevel(level).GetVertexEdges(v); }
|
||||
|
||||
ConstLocalIndexArray GetEdgeFaceLocalIndices(int level, Index e) const { return GetLevel(level).GetEdgeFaceLocalIndices(e); }
|
||||
ConstLocalIndexArray GetVertexFaceLocalIndices(int level, Index v) const { return GetLevel(level).GetVertexFaceLocalIndices(v); }
|
||||
ConstLocalIndexArray GetVertexEdgeLocalIndices(int level, Index v) const { return GetLevel(level).GetVertexEdgeLocalIndices(v); }
|
||||
|
||||
Index FindEdge(int level, Index v0, Index v1) const { return GetLevel(level).FindEdge(v0, v1); }
|
||||
|
||||
// Child components:
|
||||
ConstIndexArray GetFaceChildFaces(int level, Index f) const { return GetLevel(level).GetFaceChildFaces(f); }
|
||||
ConstIndexArray GetFaceChildEdges(int level, Index f) const { return GetLevel(level).GetFaceChildEdges(f); }
|
||||
ConstIndexArray GetEdgeChildEdges(int level, Index e) const { return GetLevel(level).GetEdgeChildEdges(e); }
|
||||
|
||||
Index GetFaceChildVertex( int level, Index f) const { return GetLevel(level).GetFaceChildVertex(f); }
|
||||
Index GetEdgeChildVertex( int level, Index e) const { return GetLevel(level).GetEdgeChildVertex(e); }
|
||||
Index GetVertexChildVertex(int level, Index v) const { return GetLevel(level).GetVertexChildVertex(v); }
|
||||
|
||||
// Parent components:
|
||||
Index GetFaceParentFace(int level, Index f) const { return GetLevel(level).GetFaceParentFace(f); }
|
||||
Index GetFaceBaseFace(int level, Index f) const { return GetLevel(level).GetFaceBaseFace(f); }
|
||||
|
||||
// Debugging aides:
|
||||
bool ValidateTopology(int level) const { return GetLevel(level).ValidateTopology(); }
|
||||
void PrintTopology(int level, bool children = true) const { GetLevel(level).PrintTopology(children); }
|
||||
|
||||
|
||||
// UNDER RE-CONSIDERATION...
|
||||
//
|
||||
// Potentially too special-purpose to warrant public method (needs to iterate through all faces):
|
||||
int GetNumHoles(int level) const;
|
||||
|
||||
// Appears to be completely unused:
|
||||
bool FaceIsRegular(int level, Index face) const {
|
||||
ConstIndexArray fVerts = _levels[level]->getFaceVertices(face);
|
||||
Vtr::Level::VTag compFaceVertTag =
|
||||
_levels[level]->getFaceCompositeVTag(fVerts);
|
||||
return not compFaceVertTag._xordinary;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
@ -440,7 +373,7 @@ protected:
|
||||
// Lower level protected methods intended strictly for internal use:
|
||||
//
|
||||
friend class TopologyRefinerFactoryBase;
|
||||
friend class PatchTablesFactory;
|
||||
friend class PatchTableFactory;
|
||||
friend class EndCapGregoryBasisPatchFactory;
|
||||
friend class EndCapLegacyGregoryPatchFactory;
|
||||
friend class PtexIndices;
|
||||
@ -549,7 +482,7 @@ TopologyRefiner::Interpolate(T const * src, U * dst) const {
|
||||
Interpolate(level, src, dst);
|
||||
|
||||
src = dst;
|
||||
dst += GetNumVertices(level);
|
||||
dst += GetLevel(level).GetNumVertices();
|
||||
}
|
||||
}
|
||||
|
||||
@ -777,7 +710,7 @@ TopologyRefiner::InterpolateVarying(T const * src, U * dst) const {
|
||||
InterpolateVarying(level, src, dst);
|
||||
|
||||
src = dst;
|
||||
dst += GetNumVertices(level);
|
||||
dst += GetLevel(level).GetNumVertices();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,13 +317,14 @@ bool
|
||||
TopologyRefinerFactory<TopologyRefinerFactoryBase::TopologyDescriptor>::assignComponentTags(
|
||||
TopologyRefiner & refiner, TopologyDescriptor const & desc) {
|
||||
|
||||
TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
|
||||
|
||||
if ((desc.numCreases>0) and desc.creaseVertexIndexPairs and desc.creaseWeights) {
|
||||
|
||||
int const * vertIndexPairs = desc.creaseVertexIndexPairs;
|
||||
for (int edge=0; edge<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) {
|
||||
refiner.setBaseEdgeSharpness(idx, desc.creaseWeights[edge]);
|
||||
@ -342,7 +343,7 @@ TopologyRefinerFactory<TopologyRefinerFactoryBase::TopologyDescriptor>::assignCo
|
||||
|
||||
int idx = desc.cornerVertexIndices[vert];
|
||||
|
||||
if (idx >= 0 and idx < refiner.GetNumVertices(0)) {
|
||||
if (idx >= 0 and idx < refBaseLevel.GetNumVertices()) {
|
||||
refiner.setBaseVertexSharpness(idx, desc.cornerWeights[vert]);
|
||||
} else {
|
||||
char msg[1024];
|
||||
|
@ -343,7 +343,7 @@ TopologyRefinerFactory<MESH>::assignComponentTopology(TopologyRefiner& /* refine
|
||||
//
|
||||
// void TopologyRefiner::setBaseVertexNonManifold(Index vertex, bool b);
|
||||
//
|
||||
// Also consider using TopologyRefiner::ValidateTopology() when debugging to ensure
|
||||
// Also consider using TopologyLevel::ValidateTopology() when debugging to ensure
|
||||
// that topolology has been completely and correctly specified.
|
||||
//
|
||||
return false;
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -61,22 +61,22 @@ createCLBuffer(std::vector<T> const & src, cl_context clContext) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CLStencilTables::CLStencilTables(Far::StencilTables const *stencilTables,
|
||||
cl_context clContext) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
CLStencilTable::CLStencilTable(Far::StencilTable const *stencilTable,
|
||||
cl_context clContext) {
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCLBuffer(stencilTables->GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(stencilTables->GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(stencilTables->GetControlIndices(),
|
||||
_sizes = createCLBuffer(stencilTable->GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(stencilTable->GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(stencilTable->GetControlIndices(),
|
||||
clContext);
|
||||
_weights = createCLBuffer(stencilTables->GetWeights(), clContext);
|
||||
_weights = createCLBuffer(stencilTable->GetWeights(), clContext);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CLStencilTables::~CLStencilTables() {
|
||||
CLStencilTable::~CLStencilTable() {
|
||||
if (_sizes) clReleaseMemObject(_sizes);
|
||||
if (_offsets) clReleaseMemObject(_offsets);
|
||||
if (_indices) clReleaseMemObject(_indices);
|
||||
|
@ -34,29 +34,29 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
class StencilTable;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief OpenCL stencil tables
|
||||
/// \brief OpenCL stencil table
|
||||
///
|
||||
/// This class is an OpenCL buffer representation of Far::StencilTables.
|
||||
/// This class is an OpenCL buffer representation of Far::StencilTable.
|
||||
///
|
||||
/// CLCompute consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class CLStencilTables {
|
||||
class CLStencilTable {
|
||||
public:
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLStencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new CLStencilTables(stencilTables, context->GetContext());
|
||||
static CLStencilTable *Create(Far::StencilTable const *stencilTable,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new CLStencilTable(stencilTable, context->GetContext());
|
||||
}
|
||||
|
||||
CLStencilTables(Far::StencilTables const *stencilTables,
|
||||
cl_context clContext);
|
||||
~CLStencilTables();
|
||||
CLStencilTable(Far::StencilTable const *stencilTable,
|
||||
cl_context clContext);
|
||||
~CLStencilTable();
|
||||
|
||||
// interfaces needed for CLComputeKernel
|
||||
cl_mem GetSizesBuffer() const { return _sizes; }
|
||||
@ -123,7 +123,7 @@ public:
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// @param stencilTable stencil table to be applied. The table must have
|
||||
/// OpenCL memory interfaces.
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
|
@ -59,10 +59,10 @@ CpuEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float *dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float *dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
float *dstDs,
|
||||
VertexBufferDescriptor const &dstDsDesc,
|
||||
float *dstDt,
|
||||
VertexBufferDescriptor const &dstDtDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
@ -72,13 +72,13 @@ CpuEvaluator::EvalStencils(const float *src,
|
||||
int start, int end) {
|
||||
if (end <= start) return true;
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
if (srcDesc.length != dstDuDesc.length) return false;
|
||||
if (srcDesc.length != dstDvDesc.length) return false;
|
||||
if (srcDesc.length != dstDsDesc.length) return false;
|
||||
if (srcDesc.length != dstDtDesc.length) return false;
|
||||
|
||||
CpuEvalStencils(src, srcDesc,
|
||||
dst, dstDesc,
|
||||
dstDu, dstDuDesc,
|
||||
dstDv, dstDvDesc,
|
||||
dstDs, dstDsDesc,
|
||||
dstDt, dstDtDesc,
|
||||
sizes, offsets, indices,
|
||||
weights, duWeights, dvWeights,
|
||||
start, end);
|
||||
@ -93,19 +93,21 @@ struct BufferAdapter {
|
||||
void Clear() {
|
||||
for (int i = 0; i < _length; ++i) _p[i] = 0;
|
||||
}
|
||||
void AddWithWeight(T const *src, float w, float wu, float wv) {
|
||||
(void)wu;
|
||||
(void)wv;
|
||||
// TODO: derivatives.
|
||||
for (int i = 0; i < _length; ++i) {
|
||||
_p[i] += src[i] * w;
|
||||
void AddWithWeight(T const *src, float w) {
|
||||
if (_p) {
|
||||
// TODO: derivatives.
|
||||
for (int i = 0; i < _length; ++i) {
|
||||
_p[i] += src[i] * w;
|
||||
}
|
||||
}
|
||||
}
|
||||
const T *operator[] (int index) const {
|
||||
return _p + _stride * index;
|
||||
}
|
||||
BufferAdapter<T> & operator ++() {
|
||||
_p += _stride;
|
||||
if (_p) {
|
||||
_p += _stride;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -115,24 +117,23 @@ struct BufferAdapter {
|
||||
};
|
||||
|
||||
/* static */
|
||||
int
|
||||
bool
|
||||
CpuEvaluator::EvalPatches(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable) {
|
||||
int numPatchCoords,
|
||||
PatchCoord const *patchCoords,
|
||||
Far::PatchTable const *patchTable) {
|
||||
src += srcDesc.offset;
|
||||
dst += dstDesc.offset;
|
||||
int count = 0;
|
||||
if (dst) dst += dstDesc.offset;
|
||||
|
||||
// XXX: this implementaion is temporary.
|
||||
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
|
||||
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
|
||||
|
||||
float wP[20], wDs[20], wDt[20];
|
||||
|
||||
for (size_t i = 0; i < patchCoords.size(); ++i) {
|
||||
for (int i = 0; i < numPatchCoords; ++i) {
|
||||
PatchCoord const &coords = patchCoords[i];
|
||||
|
||||
patchTable->EvaluateBasis(coords.handle, coords.s, coords.t, wP, wDs, wDt);
|
||||
@ -141,13 +142,58 @@ CpuEvaluator::EvalPatches(const float *src,
|
||||
|
||||
dstT.Clear();
|
||||
for (int j = 0; j < cvs.size(); ++j) {
|
||||
dstT.AddWithWeight(srcT[cvs[j]], wP[j], wDs[j], wDt[j]);
|
||||
dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
|
||||
}
|
||||
|
||||
++count;
|
||||
++dstT;
|
||||
}
|
||||
return count;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalPatches(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float *dstDs,
|
||||
VertexBufferDescriptor const &dstDsDesc,
|
||||
float *dstDt,
|
||||
VertexBufferDescriptor const &dstDtDesc,
|
||||
int numPatchCoords,
|
||||
PatchCoord const *patchCoords,
|
||||
Far::PatchTable const *patchTable) {
|
||||
src += srcDesc.offset;
|
||||
if (dst) dst += dstDesc.offset;
|
||||
if (dstDs) dstDs += dstDsDesc.offset;
|
||||
if (dstDt) dstDt += dstDtDesc.offset;
|
||||
|
||||
BufferAdapter<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 <vector>
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -49,21 +49,24 @@ struct PatchCoord {
|
||||
///
|
||||
/// @param t parametric location on the patch
|
||||
///
|
||||
PatchCoord(Far::PatchTables::PatchHandle handle, float s, float t) :
|
||||
PatchCoord(Far::PatchTable::PatchHandle handle, float s, float t) :
|
||||
handle(handle), s(s), t(t) { }
|
||||
|
||||
Far::PatchTables::PatchHandle handle; ///< patch handle
|
||||
Far::PatchTable::PatchHandle handle; ///< patch handle
|
||||
float s, t; ///< parametric location on patch
|
||||
};
|
||||
|
||||
typedef std::vector<PatchCoord> PatchCoordArray;
|
||||
|
||||
|
||||
class CpuEvaluator {
|
||||
public:
|
||||
/// ----------------------------------------------------------------------
|
||||
///
|
||||
/// Stencil evaluations with StencilTable
|
||||
///
|
||||
/// ----------------------------------------------------------------------
|
||||
|
||||
/// \brief Generic static eval stencils function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
/// in the same way from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
@ -108,7 +111,28 @@ public:
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// stencil evaluate function.
|
||||
/// \brief Static eval stencils function which takes raw CPU pointers for
|
||||
/// input and output.
|
||||
///
|
||||
/// @param src Input primvar pointer. An offset of srcDesc
|
||||
/// will be applied internally (i.e. the pointer
|
||||
/// should not include the offset)
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dst Output primvar pointer. An offset of dstDesc
|
||||
/// will be applied internally.
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied.
|
||||
///
|
||||
/// @param instance not used in the cpu kernel
|
||||
/// (declared as a typed pointer to prevent
|
||||
/// undesirable template resolution)
|
||||
///
|
||||
/// @param deviceContext not used in the cpu kernel
|
||||
///
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
@ -120,15 +144,52 @@ public:
|
||||
int start,
|
||||
int end);
|
||||
|
||||
/// \brief Generic static eval stencils function with derivatives.
|
||||
/// This function has a same signature as other device kernels
|
||||
/// have so that it can be called in the same way from OsdMesh
|
||||
/// template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param dstDsBuffer Output s-derivative buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDsDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param dstDtBuffer Output t-derivative buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDtDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied.
|
||||
///
|
||||
/// @param instance not used in the cpu kernel
|
||||
/// (declared as a typed pointer to prevent
|
||||
/// undesirable template resolution)
|
||||
///
|
||||
/// @param deviceContext not used in the cpu kernel
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
DST_BUFFER *dstDuBuffer,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
DST_BUFFER *dstDvBuffer,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
DST_BUFFER *dstDsBuffer,
|
||||
VertexBufferDescriptor const &dstDsDesc,
|
||||
DST_BUFFER *dstDtBuffer,
|
||||
VertexBufferDescriptor const &dstDtDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
const CpuEvaluator *evaluator = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
@ -139,10 +200,10 @@ public:
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
dstDuBuffer->BindCpuBuffer(),
|
||||
dstDuDesc,
|
||||
dstDvBuffer->BindCpuBuffer(),
|
||||
dstDvDesc,
|
||||
dstDsBuffer->BindCpuBuffer(),
|
||||
dstDsDesc,
|
||||
dstDtBuffer->BindCpuBuffer(),
|
||||
dstDtDesc,
|
||||
&stencilTable->GetSizes()[0],
|
||||
&stencilTable->GetOffsets()[0],
|
||||
&stencilTable->GetControlIndices()[0],
|
||||
@ -153,14 +214,46 @@ public:
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// \brief Static eval stencils function with derivatives, which takes
|
||||
/// raw CPU pointers for input and output.
|
||||
///
|
||||
/// @param src Input primvar pointer. An offset of srcDesc
|
||||
/// will be applied internally (i.e. the pointer
|
||||
/// should not include the offset)
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dst Output primvar pointer. An offset of dstDesc
|
||||
/// will be applied internally.
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param dstDs Output s-derivatives pointer. An offset of
|
||||
/// dstDsDesc will be applied internally.
|
||||
///
|
||||
/// @param dstDsDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param dstDt Output t-derivatives pointer. An offset of
|
||||
/// dstDtDesc will be applied internally.
|
||||
///
|
||||
/// @param dstDtDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied.
|
||||
///
|
||||
/// @param instance not used in the cpu kernel
|
||||
/// (declared as a typed pointer to prevent
|
||||
/// undesirable template resolution)
|
||||
///
|
||||
/// @param deviceContext not used in the cpu kernel
|
||||
///
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float *dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float *dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
float *dstDs,
|
||||
VertexBufferDescriptor const &dstDsDesc,
|
||||
float *dstDt,
|
||||
VertexBufferDescriptor const &dstDtDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
@ -170,11 +263,15 @@ public:
|
||||
int start,
|
||||
int end);
|
||||
|
||||
/// ----------------------------------------------------------------------
|
||||
///
|
||||
/// Limit evaluations with PatchTable
|
||||
///
|
||||
/// ----------------------------------------------------------------------
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently.
|
||||
///
|
||||
/// XXX: This interface is still work in progress. XXX
|
||||
/// in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
@ -188,23 +285,26 @@ public:
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param patchCoord array of locations to be evaluated.
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
///
|
||||
/// @param patchTable Far::PatchTable
|
||||
///
|
||||
/// @param instanced not used in the cpu evaluator
|
||||
/// @param instance not used in the cpu evaluator
|
||||
///
|
||||
/// @param deviceContext not used in the cpu evaluator
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER>
|
||||
static int EvalPatches(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable,
|
||||
CpuEvaluator const *instance,
|
||||
void * deviceContext = NULL) {
|
||||
static bool EvalPatches(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
PatchCoord const *patchCoords,
|
||||
Far::PatchTable const *patchTable,
|
||||
CpuEvaluator const *instance,
|
||||
void * deviceContext = NULL) {
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
@ -212,17 +312,158 @@ public:
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
numPatchCoords,
|
||||
patchCoords,
|
||||
patchTable);
|
||||
}
|
||||
|
||||
/// \brief limit eval function.
|
||||
static int EvalPatches(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable);
|
||||
/// \brief Generic limit eval function with derivatives. This function has
|
||||
/// a same signature as other device kernels have so that it can be
|
||||
/// called in the same way.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param dstDsBuffer Output s-derivatives buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDsDesc vertex buffer descriptor for the dstDsBuffer
|
||||
///
|
||||
/// @param dstDtBuffer Output t-derivatives buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDtDesc vertex buffer descriptor for the dstDtBuffer
|
||||
///
|
||||
/// @param numPatchCoords number of patchCoords.
|
||||
///
|
||||
/// @param patchCoords array of locations to be evaluated.
|
||||
///
|
||||
/// @param patchTable Far::PatchTable
|
||||
///
|
||||
/// @param instance not used in the cpu evaluator
|
||||
///
|
||||
/// @param deviceContext not used in the cpu evaluator
|
||||
///
|
||||
template <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.
|
||||
static void Synchronize(void * /*deviceContext = NULL*/) {
|
||||
|
@ -36,14 +36,14 @@ CpuSmoothNormalContext::CpuSmoothNormalContext(
|
||||
Far::TopologyRefiner const & refiner, int level, bool resetMemory) :
|
||||
_numVertices(0), _resetMemory(resetMemory) {
|
||||
|
||||
int nfaces = refiner.GetNumFaces(level),
|
||||
int nfaces = refiner.GetLevel(level).GetNumFaces(),
|
||||
nverts = nfaces * 4;
|
||||
|
||||
_faceVerts.resize(nverts);
|
||||
Far::Index * dest = &_faceVerts[0];
|
||||
|
||||
for (int face=0; face<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));
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <cuda_runtime.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
extern "C" {
|
||||
void CudaEvalStencils(const float *src,
|
||||
@ -69,19 +69,19 @@ createCudaBuffer(std::vector<T> const & src) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaStencilTables::CudaStencilTables(Far::StencilTables const *stencilTables) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
CudaStencilTable::CudaStencilTable(Far::StencilTable const *stencilTable) {
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCudaBuffer(stencilTables->GetSizes());
|
||||
_offsets = createCudaBuffer(stencilTables->GetOffsets());
|
||||
_indices = createCudaBuffer(stencilTables->GetControlIndices());
|
||||
_weights = createCudaBuffer(stencilTables->GetWeights());
|
||||
_sizes = createCudaBuffer(stencilTable->GetSizes());
|
||||
_offsets = createCudaBuffer(stencilTable->GetOffsets());
|
||||
_indices = createCudaBuffer(stencilTable->GetControlIndices());
|
||||
_weights = createCudaBuffer(stencilTable->GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CudaStencilTables::~CudaStencilTables() {
|
||||
CudaStencilTable::~CudaStencilTable() {
|
||||
if (_sizes) cudaFree(_sizes);
|
||||
if (_offsets) cudaFree(_offsets);
|
||||
if (_indices) cudaFree(_indices);
|
||||
|
@ -34,28 +34,28 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
class StencilTable;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief CUDA stencil tables
|
||||
/// \brief CUDA stencil table
|
||||
///
|
||||
/// This class is a cuda buffer representation of Far::StencilTables.
|
||||
/// This class is a cuda buffer representation of Far::StencilTable.
|
||||
///
|
||||
/// CudaComputeKernel consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class CudaStencilTables {
|
||||
class CudaStencilTable {
|
||||
public:
|
||||
static CudaStencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
void *deviceContext = NULL) {
|
||||
static CudaStencilTable *Create(Far::StencilTable const *stencilTable,
|
||||
void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new CudaStencilTables(stencilTables);
|
||||
return new CudaStencilTable(stencilTable);
|
||||
}
|
||||
|
||||
explicit CudaStencilTables(Far::StencilTables const *stencilTables);
|
||||
~CudaStencilTables();
|
||||
explicit CudaStencilTable(Far::StencilTable const *stencilTable);
|
||||
~CudaStencilTable();
|
||||
|
||||
// interfaces needed for CudaCompute
|
||||
void *GetSizesBuffer() const { return _sizes; }
|
||||
@ -92,7 +92,7 @@ public:
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// @param stencilTable stencil table to be applied. The table must have
|
||||
/// Cuda memory interfaces.
|
||||
///
|
||||
/// @param instance not used in the CudaEvaluator
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -112,37 +112,37 @@ static ID3D11ShaderResourceView *createSRV(ID3D11Buffer *buffer,
|
||||
return srv;
|
||||
}
|
||||
|
||||
D3D11StencilTables::D3D11StencilTables(Far::StencilTables const *stencilTables,
|
||||
ID3D11DeviceContext *deviceContext)
|
||||
D3D11StencilTable::D3D11StencilTable(Far::StencilTable const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext)
|
||||
{
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
std::vector<int> const &sizes = stencilTables->GetSizes();
|
||||
std::vector<int> const &sizes = stencilTable->GetSizes();
|
||||
|
||||
_sizesBuffer = createBuffer(sizes, device);
|
||||
_offsetsBuffer = createBuffer(stencilTables->GetOffsets(), device);
|
||||
_indicesBuffer = createBuffer(stencilTables->GetControlIndices(), device);
|
||||
_weightsBuffer = createBuffer(stencilTables->GetWeights(), device);
|
||||
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), device);
|
||||
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), device);
|
||||
_weightsBuffer = createBuffer(stencilTable->GetWeights(), device);
|
||||
|
||||
_sizes = createSRV(_sizesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetSizes().size());
|
||||
stencilTable->GetSizes().size());
|
||||
_offsets = createSRV(_offsetsBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetOffsets().size());
|
||||
stencilTable->GetOffsets().size());
|
||||
_indices = createSRV(_indicesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetControlIndices().size());
|
||||
stencilTable->GetControlIndices().size());
|
||||
_weights= createSRV(_weightsBuffer, DXGI_FORMAT_R32_FLOAT, device,
|
||||
stencilTables->GetWeights().size());
|
||||
stencilTable->GetWeights().size());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11StencilTables::~D3D11StencilTables() {
|
||||
D3D11StencilTable::~D3D11StencilTable() {
|
||||
SAFE_RELEASE(_sizes);
|
||||
SAFE_RELEASE(_sizesBuffer);
|
||||
SAFE_RELEASE(_offsets);
|
||||
@ -341,7 +341,7 @@ D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV,
|
||||
ID3D11ShaderResourceView *SRViews[] = {
|
||||
sizesSRV, offsetsSRV, indicesSRV, weightsSRV };
|
||||
|
||||
// bind source vertex and stencil tables
|
||||
// bind source vertex and stencil table
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4
|
||||
|
||||
if (srcUAV == dstUAV) {
|
||||
@ -356,7 +356,7 @@ D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV,
|
||||
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
}
|
||||
|
||||
// unbind stencil tables and vertexbuffers
|
||||
// unbind stencil table and vertexbuffers
|
||||
SRViews[0] = SRViews[1] = SRViews[2] = SRViews[3] = NULL;
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews);
|
||||
|
||||
|
@ -41,35 +41,35 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
class StencilTable;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief D3D11 stencil tables
|
||||
/// \brief D3D11 stencil table
|
||||
///
|
||||
/// This class is a D3D11 Shader Resource View representation of
|
||||
/// Far::StencilTables.
|
||||
/// Far::StencilTable.
|
||||
///
|
||||
/// D3D11ComputeEvaluator consumes this table to apply stencils
|
||||
///
|
||||
class D3D11StencilTables {
|
||||
class D3D11StencilTable {
|
||||
public:
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static D3D11StencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
static D3D11StencilTable *Create(Far::StencilTable const *stencilTable,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new D3D11StencilTables(stencilTables, context->GetDeviceContext());
|
||||
return new D3D11StencilTable(stencilTable, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11StencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
static D3D11StencilTable *Create(Far::StencilTable const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
return new D3D11StencilTables(stencilTables, deviceContext);
|
||||
return new D3D11StencilTable(stencilTable, deviceContext);
|
||||
}
|
||||
|
||||
D3D11StencilTables(Far::StencilTables const *stencilTables,
|
||||
D3D11StencilTable(Far::StencilTable const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
~D3D11StencilTables();
|
||||
~D3D11StencilTable();
|
||||
|
||||
// interfaces needed for D3D11ComputeEvaluator
|
||||
ID3D11ShaderResourceView *GetSizesSRV() const { return _sizes; }
|
||||
@ -122,7 +122,7 @@ public:
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// @param stencilTable stencil table to be applied. The table must have
|
||||
/// SSBO interfaces.
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
|
@ -46,7 +46,7 @@ D3D11LegacyGregoryPatchTable::~D3D11LegacyGregoryPatchTable() {
|
||||
}
|
||||
|
||||
D3D11LegacyGregoryPatchTable *
|
||||
D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables,
|
||||
D3D11LegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext) {
|
||||
ID3D11Device *pd3d11Device = NULL;
|
||||
pd3d11DeviceContext->GetDevice(&pd3d11Device);
|
||||
@ -54,10 +54,10 @@ D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables,
|
||||
|
||||
D3D11LegacyGregoryPatchTable *result = new D3D11LegacyGregoryPatchTable();
|
||||
|
||||
Far::PatchTables::VertexValenceTable const &
|
||||
valenceTable = farPatchTables->GetVertexValenceTable();
|
||||
Far::PatchTables::QuadOffsetsTable const &
|
||||
quadOffsetsTable = farPatchTables->GetQuadOffsetsTable();
|
||||
Far::PatchTable::VertexValenceTable const &
|
||||
valenceTable = farPatchTable->GetVertexValenceTable();
|
||||
Far::PatchTable::QuadOffsetsTable const &
|
||||
quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
|
||||
|
||||
if (not valenceTable.empty()) {
|
||||
D3D11_BUFFER_DESC bd;
|
||||
@ -126,11 +126,11 @@ D3D11LegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables,
|
||||
result->_quadOffsetsBase[1] = 0;
|
||||
|
||||
// scan patchtable to find quadOffsetsBase.
|
||||
for (int i = 0; i < farPatchTables->GetNumPatchArrays(); ++i) {
|
||||
for (int i = 0; i < farPatchTable->GetNumPatchArrays(); ++i) {
|
||||
// GREGORY_BOUNDARY's quadoffsets come after GREGORY's.
|
||||
if (farPatchTables->GetPatchArrayDescriptor(i) ==
|
||||
if (farPatchTable->GetPatchArrayDescriptor(i) ==
|
||||
Far::PatchDescriptor::GREGORY) {
|
||||
result->_quadOffsetsBase[1] = farPatchTables->GetNumPatches(i) * 4;
|
||||
result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
struct ID3D11Buffer;
|
||||
@ -47,12 +47,12 @@ public:
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static D3D11LegacyGregoryPatchTable *Create(
|
||||
Far::PatchTables const *farPatchTables, DEVICE_CONTEXT context) {
|
||||
return Create(farPatchTables, context->GetDeviceContext());
|
||||
Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context) {
|
||||
return Create(farPatchTable, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11LegacyGregoryPatchTable *Create(
|
||||
Far::PatchTables const *farPatchTables,
|
||||
Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
void UpdateVertexBuffer(ID3D11Buffer *vbo,
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "../osd/d3d11PatchTable.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -43,17 +43,17 @@ D3D11PatchTable::~D3D11PatchTable() {
|
||||
}
|
||||
|
||||
D3D11PatchTable *
|
||||
D3D11PatchTable::Create(Far::PatchTables const *farPatchTables,
|
||||
D3D11PatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext) {
|
||||
D3D11PatchTable *instance = new D3D11PatchTable();
|
||||
if (instance->allocate(farPatchTables, pd3d11DeviceContext))
|
||||
if (instance->allocate(farPatchTable, pd3d11DeviceContext))
|
||||
return instance;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables,
|
||||
D3D11PatchTable::allocate(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext) {
|
||||
ID3D11Device *pd3d11Device = NULL;
|
||||
pd3d11DeviceContext->GetDevice(&pd3d11Device);
|
||||
@ -63,18 +63,18 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables,
|
||||
std::vector<unsigned int> ppBuffer;
|
||||
|
||||
// needs reserve?
|
||||
int nPatchArrays = farPatchTables->GetNumPatchArrays();
|
||||
int nPatchArrays = farPatchTable->GetNumPatchArrays();
|
||||
|
||||
// for each patchArray
|
||||
for (int j = 0; j < nPatchArrays; ++j) {
|
||||
PatchArray patchArray(farPatchTables->GetPatchArrayDescriptor(j),
|
||||
farPatchTables->GetNumPatches(j),
|
||||
PatchArray patchArray(farPatchTable->GetPatchArrayDescriptor(j),
|
||||
farPatchTable->GetNumPatches(j),
|
||||
(int)buffer.size(),
|
||||
(int)ppBuffer.size()/3);
|
||||
_patchArrays.push_back(patchArray);
|
||||
|
||||
// indices
|
||||
Far::ConstIndexArray indices = farPatchTables->GetPatchArrayVertices(j);
|
||||
Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j);
|
||||
for (int k = 0; k < indices.size(); ++k) {
|
||||
buffer.push_back(indices[k]);
|
||||
}
|
||||
@ -84,7 +84,7 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables,
|
||||
// XXX: we need sharpness interface for patcharray or put sharpness
|
||||
// into patchParam.
|
||||
Far::ConstPatchParamArray patchParams =
|
||||
farPatchTables->GetPatchParams(j);
|
||||
farPatchTable->GetPatchParams(j);
|
||||
for (int k = 0; k < patchParams.size(); ++k) {
|
||||
float sharpness = 0.0;
|
||||
ppBuffer.push_back(patchParams[k].faceIndex);
|
||||
@ -93,21 +93,21 @@ D3D11PatchTable::allocate(Far::PatchTables const *farPatchTables,
|
||||
}
|
||||
#else
|
||||
// XXX: workaround. GetPatchParamTable() will be deprecated though.
|
||||
Far::PatchParamTable const & patchParamTables =
|
||||
farPatchTables->GetPatchParamTable();
|
||||
Far::PatchParamTable const & patchParamTable =
|
||||
farPatchTable->GetPatchParamTable();
|
||||
std::vector<Far::Index> const &sharpnessIndexTable =
|
||||
farPatchTables->GetSharpnessIndexTable();
|
||||
int numPatches = farPatchTables->GetNumPatches(j);
|
||||
farPatchTable->GetSharpnessIndexTable();
|
||||
int numPatches = farPatchTable->GetNumPatches(j);
|
||||
for (int k = 0; k < numPatches; ++k) {
|
||||
float sharpness = 0.0;
|
||||
int patchIndex = (int)ppBuffer.size()/3;
|
||||
if (patchIndex < (int)sharpnessIndexTable.size()) {
|
||||
int sharpnessIndex = sharpnessIndexTable[patchIndex];
|
||||
if (sharpnessIndex >= 0)
|
||||
sharpness = farPatchTables->GetSharpnessValues()[sharpnessIndex];
|
||||
sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex];
|
||||
}
|
||||
ppBuffer.push_back(patchParamTables[patchIndex].faceIndex);
|
||||
ppBuffer.push_back(patchParamTables[patchIndex].bitField.field);
|
||||
ppBuffer.push_back(patchParamTable[patchIndex].faceIndex);
|
||||
ppBuffer.push_back(patchParamTable[patchIndex].bitField.field);
|
||||
ppBuffer.push_back(*((unsigned int *)&sharpness));
|
||||
}
|
||||
#endif
|
||||
|
@ -40,7 +40,7 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{
|
||||
class PatchTables;
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
@ -80,12 +80,12 @@ public:
|
||||
~D3D11PatchTable();
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static D3D11PatchTable *Create(Far::PatchTables const *farPatchTables,
|
||||
static D3D11PatchTable *Create(Far::PatchTable const *farPatchTable,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(farPatchTables, context->GetDeviceContext());
|
||||
return Create(farPatchTable, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11PatchTable *Create(Far::PatchTables const *farPatchTables,
|
||||
static D3D11PatchTable *Create(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
PatchArrayVector const &GetPatchArrays() const {
|
||||
@ -103,8 +103,8 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
// allocate buffers from patchTables
|
||||
bool allocate(Far::PatchTables const *farPatchTables,
|
||||
// allocate buffers from patchTable
|
||||
bool allocate(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
PatchArrayVector _patchArrays;
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
@ -65,20 +65,20 @@ createSSBO(std::vector<T> const & src) {
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
GLStencilTablesSSBO::GLStencilTablesSSBO(
|
||||
Far::StencilTables const *stencilTables) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
GLStencilTableSSBO::GLStencilTableSSBO(
|
||||
Far::StencilTable const *stencilTable) {
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createSSBO(stencilTables->GetSizes());
|
||||
_offsets = createSSBO(stencilTables->GetOffsets());
|
||||
_indices = createSSBO(stencilTables->GetControlIndices());
|
||||
_weights = createSSBO(stencilTables->GetWeights());
|
||||
_sizes = createSSBO(stencilTable->GetSizes());
|
||||
_offsets = createSSBO(stencilTable->GetOffsets());
|
||||
_indices = createSSBO(stencilTable->GetControlIndices());
|
||||
_weights = createSSBO(stencilTable->GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTablesSSBO::~GLStencilTablesSSBO() {
|
||||
GLStencilTableSSBO::~GLStencilTableSSBO() {
|
||||
if (_sizes) glDeleteBuffers(1, &_sizes);
|
||||
if (_offsets) glDeleteBuffers(1, &_offsets);
|
||||
if (_weights) glDeleteBuffers(1, &_weights);
|
||||
|
@ -34,27 +34,27 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
class StencilTable;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief GL stencil tables (Shader Storage buffer)
|
||||
/// \brief GL stencil table (Shader Storage buffer)
|
||||
///
|
||||
/// This class is a GLSL SSBO representation of Far::StencilTables.
|
||||
/// This class is a GLSL SSBO representation of Far::StencilTable.
|
||||
///
|
||||
/// GLSLComputeKernel consumes this table to apply stencils
|
||||
///
|
||||
class GLStencilTablesSSBO {
|
||||
class GLStencilTableSSBO {
|
||||
public:
|
||||
static GLStencilTablesSSBO *Create(Far::StencilTables const *stencilTables,
|
||||
static GLStencilTableSSBO *Create(Far::StencilTable const *stencilTable,
|
||||
void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new GLStencilTablesSSBO(stencilTables);
|
||||
return new GLStencilTableSSBO(stencilTable);
|
||||
}
|
||||
|
||||
explicit GLStencilTablesSSBO(Far::StencilTables const *stencilTables);
|
||||
~GLStencilTablesSSBO();
|
||||
explicit GLStencilTableSSBO(Far::StencilTable const *stencilTable);
|
||||
~GLStencilTableSSBO();
|
||||
|
||||
// interfaces needed for GLSLComputeKernel
|
||||
GLuint GetSizesBuffer() const { return _sizes; }
|
||||
@ -190,7 +190,7 @@ public:
|
||||
private:
|
||||
GLuint _program;
|
||||
|
||||
GLuint _uniformSizes, // stencil tables
|
||||
GLuint _uniformSizes, // stencil table
|
||||
_uniformOffsets,
|
||||
_uniformIndices,
|
||||
_uniformWeights,
|
||||
|
@ -45,17 +45,17 @@ GLLegacyGregoryPatchTable::~GLLegacyGregoryPatchTable() {
|
||||
}
|
||||
|
||||
GLLegacyGregoryPatchTable *
|
||||
GLLegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables) {
|
||||
GLLegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable) {
|
||||
|
||||
GLLegacyGregoryPatchTable *result = new GLLegacyGregoryPatchTable();
|
||||
glGenTextures(1, &result->_vertexTextureBuffer);
|
||||
glGenTextures(1, &result->_vertexValenceTextureBuffer);
|
||||
glGenTextures(1, &result->_quadOffsetsTextureBuffer);
|
||||
|
||||
Far::PatchTables::VertexValenceTable const &
|
||||
valenceTable = farPatchTables->GetVertexValenceTable();
|
||||
Far::PatchTables::QuadOffsetsTable const &
|
||||
quadOffsetsTable = farPatchTables->GetQuadOffsetsTable();
|
||||
Far::PatchTable::VertexValenceTable const &
|
||||
valenceTable = farPatchTable->GetVertexValenceTable();
|
||||
Far::PatchTable::QuadOffsetsTable const &
|
||||
quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
|
||||
|
||||
GLuint buffers[2];
|
||||
glGenBuffers(2, buffers);
|
||||
@ -82,11 +82,11 @@ GLLegacyGregoryPatchTable::Create(Far::PatchTables const *farPatchTables) {
|
||||
result->_quadOffsetsBase[0] = 0;
|
||||
result->_quadOffsetsBase[1] = 0;
|
||||
// scan patchtable to find quadOffsetsBase.
|
||||
for (int i = 0; i < farPatchTables->GetNumPatchArrays(); ++i) {
|
||||
for (int i = 0; i < farPatchTable->GetNumPatchArrays(); ++i) {
|
||||
// GREGORY_BOUNDARY's quadoffsets come after GREGORY's.
|
||||
if (farPatchTables->GetPatchArrayDescriptor(i) ==
|
||||
if (farPatchTable->GetPatchArrayDescriptor(i) ==
|
||||
Far::PatchDescriptor::GREGORY) {
|
||||
result->_quadOffsetsBase[1] = farPatchTables->GetNumPatches(i) * 4;
|
||||
result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/opengl.h"
|
||||
|
||||
@ -41,7 +41,7 @@ class GLLegacyGregoryPatchTable
|
||||
public:
|
||||
~GLLegacyGregoryPatchTable();
|
||||
|
||||
static GLLegacyGregoryPatchTable *Create(Far::PatchTables const *patchTable);
|
||||
static GLLegacyGregoryPatchTable *Create(Far::PatchTable const *patchTable);
|
||||
|
||||
void UpdateVertexBuffer(GLuint vbo);
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "../osd/glPatchTable.h"
|
||||
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/opengl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
@ -42,16 +42,16 @@ GLPatchTable::~GLPatchTable() {
|
||||
}
|
||||
|
||||
GLPatchTable *
|
||||
GLPatchTable::Create(Far::PatchTables const *farPatchTables,
|
||||
GLPatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
void * /*deviceContext*/) {
|
||||
GLPatchTable *instance = new GLPatchTable();
|
||||
if (instance->allocate(farPatchTables)) return instance;
|
||||
if (instance->allocate(farPatchTable)) return instance;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
GLPatchTable::allocate(Far::PatchTables const *farPatchTables) {
|
||||
GLPatchTable::allocate(Far::PatchTable const *farPatchTable) {
|
||||
glGenBuffers(1, &_indexBuffer);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
|
||||
@ -60,18 +60,18 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) {
|
||||
|
||||
// needs reserve?
|
||||
|
||||
int nPatchArrays = farPatchTables->GetNumPatchArrays();
|
||||
int nPatchArrays = farPatchTable->GetNumPatchArrays();
|
||||
|
||||
// for each patchArray
|
||||
for (int j = 0; j < nPatchArrays; ++j) {
|
||||
PatchArray patchArray(farPatchTables->GetPatchArrayDescriptor(j),
|
||||
farPatchTables->GetNumPatches(j),
|
||||
PatchArray patchArray(farPatchTable->GetPatchArrayDescriptor(j),
|
||||
farPatchTable->GetNumPatches(j),
|
||||
(int)buffer.size(),
|
||||
(int)ppBuffer.size()/3);
|
||||
_patchArrays.push_back(patchArray);
|
||||
|
||||
// indices
|
||||
Far::ConstIndexArray indices = farPatchTables->GetPatchArrayVertices(j);
|
||||
Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j);
|
||||
for (int k = 0; k < indices.size(); ++k) {
|
||||
buffer.push_back(indices[k]);
|
||||
}
|
||||
@ -81,7 +81,7 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) {
|
||||
// XXX: we need sharpness interface for patcharray or put sharpness
|
||||
// into patchParam.
|
||||
Far::ConstPatchParamArray patchParams =
|
||||
farPatchTables->GetPatchParams(j);
|
||||
farPatchTable->GetPatchParams(j);
|
||||
for (int k = 0; k < patchParams.size(); ++k) {
|
||||
float sharpness = 0.0;
|
||||
ppBuffer.push_back(patchParams[k].faceIndex);
|
||||
@ -90,21 +90,21 @@ GLPatchTable::allocate(Far::PatchTables const *farPatchTables) {
|
||||
}
|
||||
#else
|
||||
// XXX: workaround. GetPatchParamTable() will be deprecated though.
|
||||
Far::PatchParamTable const & patchParamTables =
|
||||
farPatchTables->GetPatchParamTable();
|
||||
Far::PatchParamTable const & patchParamTable =
|
||||
farPatchTable->GetPatchParamTable();
|
||||
std::vector<Far::Index> const &sharpnessIndexTable =
|
||||
farPatchTables->GetSharpnessIndexTable();
|
||||
int numPatches = farPatchTables->GetNumPatches(j);
|
||||
farPatchTable->GetSharpnessIndexTable();
|
||||
int numPatches = farPatchTable->GetNumPatches(j);
|
||||
for (int k = 0; k < numPatches; ++k) {
|
||||
float sharpness = 0.0;
|
||||
int patchIndex = (int)ppBuffer.size()/3;
|
||||
if (patchIndex < (int)sharpnessIndexTable.size()) {
|
||||
int sharpnessIndex = sharpnessIndexTable[patchIndex];
|
||||
if (sharpnessIndex >= 0)
|
||||
sharpness = farPatchTables->GetSharpnessValues()[sharpnessIndex];
|
||||
sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex];
|
||||
}
|
||||
ppBuffer.push_back(patchParamTables[patchIndex].faceIndex);
|
||||
ppBuffer.push_back(patchParamTables[patchIndex].bitField.field);
|
||||
ppBuffer.push_back(patchParamTable[patchIndex].faceIndex);
|
||||
ppBuffer.push_back(patchParamTable[patchIndex].bitField.field);
|
||||
ppBuffer.push_back(*((unsigned int *)&sharpness));
|
||||
}
|
||||
#endif
|
||||
|
@ -36,7 +36,7 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{
|
||||
class PatchTables;
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
@ -75,7 +75,7 @@ public:
|
||||
GLPatchTable();
|
||||
~GLPatchTable();
|
||||
|
||||
static GLPatchTable *Create(Far::PatchTables const *farPatchTables,
|
||||
static GLPatchTable *Create(Far::PatchTable const *farPatchTable,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
PatchArrayVector const &GetPatchArrays() const {
|
||||
@ -93,8 +93,8 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
// allocate buffers from patchTables
|
||||
bool allocate(Far::PatchTables const *farPatchTables);
|
||||
// allocate buffers from patchTable
|
||||
bool allocate(Far::PatchTable const *farPatchTable);
|
||||
|
||||
PatchArrayVector _patchArrays;
|
||||
GLuint _indexBuffer;
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
@ -82,23 +82,23 @@ createGLTextureBuffer(std::vector<T> const & src, GLenum type) {
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
GLStencilTablesTBO::GLStencilTablesTBO(
|
||||
Far::StencilTables const *stencilTables) {
|
||||
GLStencilTableTBO::GLStencilTableTBO(
|
||||
Far::StencilTable const *stencilTable) {
|
||||
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createGLTextureBuffer(stencilTables->GetSizes(), GL_R32UI);
|
||||
_sizes = createGLTextureBuffer(stencilTable->GetSizes(), GL_R32UI);
|
||||
_offsets = createGLTextureBuffer(
|
||||
stencilTables->GetOffsets(), GL_R32I);
|
||||
stencilTable->GetOffsets(), GL_R32I);
|
||||
_indices = createGLTextureBuffer(
|
||||
stencilTables->GetControlIndices(), GL_R32I);
|
||||
_weights = createGLTextureBuffer(stencilTables->GetWeights(), GL_R32F);
|
||||
stencilTable->GetControlIndices(), GL_R32I);
|
||||
_weights = createGLTextureBuffer(stencilTable->GetWeights(), GL_R32F);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTablesTBO::~GLStencilTablesTBO() {
|
||||
GLStencilTableTBO::~GLStencilTableTBO() {
|
||||
if (_sizes) glDeleteTextures(1, &_sizes);
|
||||
if (_offsets) glDeleteTextures(1, &_offsets);
|
||||
if (_weights) glDeleteTextures(1, &_weights);
|
||||
@ -277,7 +277,7 @@ GLXFBEvaluator::EvalStencils(GLuint srcBuffer,
|
||||
|
||||
bindTexture(_uniformSrcBufferTexture, _srcBufferTexture, 0);
|
||||
|
||||
// bind stencil tables textures.
|
||||
// bind stencil table textures.
|
||||
bindTexture(_uniformSizesTexture, sizesTexture, 1);
|
||||
bindTexture(_uniformOffsetsTexture, offsetsTexture, 2);
|
||||
bindTexture(_uniformIndicesTexture, indicesTexture, 3);
|
||||
|
@ -34,28 +34,28 @@ namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
class StencilTable;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief GL TextureBuffer stencil tables
|
||||
/// \brief GL TextureBuffer stencil table
|
||||
///
|
||||
/// This class is a GL Texture Buffer representation of Far::StencilTables.
|
||||
/// This class is a GL Texture Buffer representation of Far::StencilTable.
|
||||
///
|
||||
/// GLSLTransformFeedback consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class GLStencilTablesTBO {
|
||||
class GLStencilTableTBO {
|
||||
public:
|
||||
static GLStencilTablesTBO *Create(
|
||||
Far::StencilTables const *stencilTables, void *deviceContext = NULL) {
|
||||
static GLStencilTableTBO *Create(
|
||||
Far::StencilTable const *stencilTable, void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new GLStencilTablesTBO(stencilTables);
|
||||
return new GLStencilTableTBO(stencilTable);
|
||||
}
|
||||
|
||||
explicit GLStencilTablesTBO(Far::StencilTables const *stencilTables);
|
||||
~GLStencilTablesTBO();
|
||||
explicit GLStencilTableTBO(Far::StencilTable const *stencilTable);
|
||||
~GLStencilTableTBO();
|
||||
|
||||
// interfaces needed for GLSLTransformFeedbackKernel
|
||||
GLuint GetSizesTexture() const { return _sizes; }
|
||||
|
@ -33,9 +33,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "../far/topologyRefiner.h"
|
||||
#include "../far/patchTablesFactory.h"
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/stencilTablesFactory.h"
|
||||
#include "../far/patchTableFactory.h"
|
||||
#include "../far/stencilTable.h"
|
||||
#include "../far/stencilTableFactory.h"
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
@ -87,7 +87,7 @@ public:
|
||||
|
||||
virtual PatchTable * GetPatchTable() const = 0;
|
||||
|
||||
virtual Far::PatchTables const *GetFarPatchTables() const = 0;
|
||||
virtual Far::PatchTable const *GetFarPatchTable() const = 0;
|
||||
|
||||
virtual VertexBufferBinding BindVertexBuffer() = 0;
|
||||
|
||||
@ -114,32 +114,32 @@ protected:
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename STENCIL_TABLES, typename DEVICE_CONTEXT>
|
||||
STENCIL_TABLES const *
|
||||
convertToCompatibleStencilTables(
|
||||
Far::StencilTables const *table, DEVICE_CONTEXT *context) {
|
||||
template <typename STENCIL_TABLE, typename DEVICE_CONTEXT>
|
||||
STENCIL_TABLE const *
|
||||
convertToCompatibleStencilTable(
|
||||
Far::StencilTable const *table, DEVICE_CONTEXT *context) {
|
||||
if (not table) return NULL;
|
||||
return STENCIL_TABLES::Create(table, context);
|
||||
return STENCIL_TABLE::Create(table, context);
|
||||
}
|
||||
|
||||
template <>
|
||||
Far::StencilTables const *
|
||||
convertToCompatibleStencilTables<Far::StencilTables, void>(
|
||||
Far::StencilTables const *table, void * /*context*/) {
|
||||
Far::StencilTable const *
|
||||
convertToCompatibleStencilTable<Far::StencilTable, void>(
|
||||
Far::StencilTable const *table, void * /*context*/) {
|
||||
// no need for conversion
|
||||
// XXX: We don't want to even copy.
|
||||
if (not table) return NULL;
|
||||
return new Far::StencilTables(*table);
|
||||
return new Far::StencilTable(*table);
|
||||
}
|
||||
|
||||
template <>
|
||||
Far::StencilTables const *
|
||||
convertToCompatibleStencilTables<Far::StencilTables, ID3D11DeviceContext>(
|
||||
Far::StencilTables const *table, ID3D11DeviceContext * /*context*/) {
|
||||
Far::StencilTable const *
|
||||
convertToCompatibleStencilTable<Far::StencilTable, ID3D11DeviceContext>(
|
||||
Far::StencilTable const *table, ID3D11DeviceContext * /*context*/) {
|
||||
// no need for conversion
|
||||
// XXX: We don't want to even copy.
|
||||
if (not table) return NULL;
|
||||
return new Far::StencilTables(*table);
|
||||
return new Far::StencilTable(*table);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -231,7 +231,7 @@ static EVALUATOR *GetEvaluator(
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename VERTEX_BUFFER,
|
||||
typename STENCIL_TABLES,
|
||||
typename STENCIL_TABLE,
|
||||
typename EVALUATOR,
|
||||
typename PATCH_TABLE,
|
||||
typename DEVICE_CONTEXT = void>
|
||||
@ -239,7 +239,7 @@ class Mesh : public MeshInterface<PATCH_TABLE> {
|
||||
public:
|
||||
typedef VERTEX_BUFFER VertexBuffer;
|
||||
typedef EVALUATOR Evaluator;
|
||||
typedef STENCIL_TABLES StencilTables;
|
||||
typedef STENCIL_TABLE StencilTable;
|
||||
typedef PATCH_TABLE PatchTable;
|
||||
typedef DEVICE_CONTEXT DeviceContext;
|
||||
typedef EvaluatorCacheT<Evaluator> EvaluatorCache;
|
||||
@ -254,13 +254,13 @@ public:
|
||||
DeviceContext * deviceContext = NULL) :
|
||||
|
||||
_refiner(refiner),
|
||||
_farPatchTables(NULL),
|
||||
_farPatchTable(NULL),
|
||||
_numVertices(0),
|
||||
_maxValence(0),
|
||||
_vertexBuffer(NULL),
|
||||
_varyingBuffer(NULL),
|
||||
_vertexStencilTables(NULL),
|
||||
_varyingStencilTables(NULL),
|
||||
_vertexStencilTable(NULL),
|
||||
_varyingStencilTable(NULL),
|
||||
_evaluatorCache(evaluatorCache),
|
||||
_patchTable(NULL),
|
||||
_deviceContext(deviceContext) {
|
||||
@ -302,11 +302,11 @@ public:
|
||||
|
||||
virtual ~Mesh() {
|
||||
delete _refiner;
|
||||
delete _farPatchTables;
|
||||
delete _farPatchTable;
|
||||
delete _vertexBuffer;
|
||||
delete _varyingBuffer;
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
delete _vertexStencilTable;
|
||||
delete _varyingStencilTable;
|
||||
delete _patchTable;
|
||||
// deviceContext and evaluatorCache are not owned by this class.
|
||||
}
|
||||
@ -325,7 +325,7 @@ public:
|
||||
|
||||
virtual void Refine() {
|
||||
|
||||
int numControlVertices = _refiner->GetNumVertices(0);
|
||||
int numControlVertices = _refiner->GetLevel(0).GetNumVertices();
|
||||
|
||||
VertexBufferDescriptor srcDesc = _vertexDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
@ -339,7 +339,7 @@ public:
|
||||
|
||||
Evaluator::EvalStencils(_vertexBuffer, srcDesc,
|
||||
_vertexBuffer, dstDesc,
|
||||
_vertexStencilTables,
|
||||
_vertexStencilTable,
|
||||
instance, _deviceContext);
|
||||
|
||||
if (_varyingDesc.length > 0) {
|
||||
@ -354,13 +354,13 @@ public:
|
||||
// non-interleaved
|
||||
Evaluator::EvalStencils(_varyingBuffer, srcDesc,
|
||||
_varyingBuffer, dstDesc,
|
||||
_varyingStencilTables,
|
||||
_varyingStencilTable,
|
||||
instance, _deviceContext);
|
||||
} else {
|
||||
// interleaved
|
||||
Evaluator::EvalStencils(_vertexBuffer, srcDesc,
|
||||
_vertexBuffer, dstDesc,
|
||||
_varyingStencilTables,
|
||||
_varyingStencilTable,
|
||||
instance, _deviceContext);
|
||||
}
|
||||
}
|
||||
@ -374,8 +374,8 @@ public:
|
||||
return _patchTable;
|
||||
}
|
||||
|
||||
virtual Far::PatchTables const *GetFarPatchTables() const {
|
||||
return _farPatchTables;
|
||||
virtual Far::PatchTable const *GetFarPatchTable() const {
|
||||
return _farPatchTable;
|
||||
}
|
||||
|
||||
virtual int GetNumVertices() const { return _numVertices; }
|
||||
@ -408,85 +408,85 @@ private:
|
||||
int level, MeshBitset bits) {
|
||||
assert(_refiner);
|
||||
|
||||
Far::StencilTablesFactory::Options options;
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateOffsets = true;
|
||||
options.generateIntermediateLevels =
|
||||
_refiner->IsUniform() ? false : true;
|
||||
|
||||
Far::StencilTables const * vertexStencils = NULL;
|
||||
Far::StencilTables const * varyingStencils = NULL;
|
||||
Far::StencilTable const * vertexStencils = NULL;
|
||||
Far::StencilTable const * varyingStencils = NULL;
|
||||
|
||||
if (numVertexElements>0) {
|
||||
|
||||
vertexStencils = Far::StencilTablesFactory::Create(*_refiner,
|
||||
options);
|
||||
vertexStencils = Far::StencilTableFactory::Create(*_refiner,
|
||||
options);
|
||||
}
|
||||
|
||||
if (numVaryingElements>0) {
|
||||
|
||||
options.interpolationMode =
|
||||
Far::StencilTablesFactory::INTERPOLATE_VARYING;
|
||||
Far::StencilTableFactory::INTERPOLATE_VARYING;
|
||||
|
||||
varyingStencils = Far::StencilTablesFactory::Create(*_refiner,
|
||||
options);
|
||||
varyingStencils = Far::StencilTableFactory::Create(*_refiner,
|
||||
options);
|
||||
}
|
||||
|
||||
Far::PatchTablesFactory::Options poptions(level);
|
||||
Far::PatchTableFactory::Options poptions(level);
|
||||
poptions.generateFVarTables = bits.test(MeshFVarData);
|
||||
poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
|
||||
|
||||
if (bits.test(MeshEndCapBSplineBasis)) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTablesFactory::Options::ENDCAP_BSPLINE_BASIS);
|
||||
Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
|
||||
} else if (bits.test(MeshEndCapGregoryBasis)) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
// points on gregory basis endcap boundary can be shared among
|
||||
// adjacent patches to save some stencils.
|
||||
poptions.shareEndCapPatchPoints = true;
|
||||
} else if (bits.test(MeshEndCapLegacyGregory)) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTablesFactory::Options::ENDCAP_LEGACY_GREGORY);
|
||||
Far::PatchTableFactory::Options::ENDCAP_LEGACY_GREGORY);
|
||||
}
|
||||
|
||||
_farPatchTables = Far::PatchTablesFactory::Create(*_refiner, poptions);
|
||||
_farPatchTable = Far::PatchTableFactory::Create(*_refiner, poptions);
|
||||
|
||||
// if there's endcap stencils, merge it into regular stencils.
|
||||
if (_farPatchTables->GetEndCapVertexStencilTables()) {
|
||||
if (_farPatchTable->GetEndCapVertexStencilTable()) {
|
||||
// append stencils
|
||||
if (Far::StencilTables const *vertexStencilsWithEndCap =
|
||||
Far::StencilTablesFactory::AppendEndCapStencilTables(
|
||||
if (Far::StencilTable const *vertexStencilsWithEndCap =
|
||||
Far::StencilTableFactory::AppendEndCapStencilTable(
|
||||
*_refiner,
|
||||
vertexStencils,
|
||||
_farPatchTables->GetEndCapVertexStencilTables())) {
|
||||
_farPatchTable->GetEndCapVertexStencilTable())) {
|
||||
delete vertexStencils;
|
||||
vertexStencils = vertexStencilsWithEndCap;
|
||||
}
|
||||
if (varyingStencils) {
|
||||
if (Far::StencilTables const *varyingStencilsWithEndCap =
|
||||
Far::StencilTablesFactory::AppendEndCapStencilTables(
|
||||
if (Far::StencilTable const *varyingStencilsWithEndCap =
|
||||
Far::StencilTableFactory::AppendEndCapStencilTable(
|
||||
*_refiner,
|
||||
varyingStencils,
|
||||
_farPatchTables->GetEndCapVaryingStencilTables())) {
|
||||
_farPatchTable->GetEndCapVaryingStencilTable())) {
|
||||
delete varyingStencils;
|
||||
varyingStencils = varyingStencilsWithEndCap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_maxValence = _farPatchTables->GetMaxValence();
|
||||
_patchTable = PatchTable::Create(_farPatchTables, _deviceContext);
|
||||
_maxValence = _farPatchTable->GetMaxValence();
|
||||
_patchTable = PatchTable::Create(_farPatchTable, _deviceContext);
|
||||
|
||||
// numvertices = coarse verts + refined verts + gregory basis verts
|
||||
_numVertices = vertexStencils->GetNumControlVertices()
|
||||
+ vertexStencils->GetNumStencils();
|
||||
|
||||
// convert to device stenciltables if necessary.
|
||||
_vertexStencilTables =
|
||||
convertToCompatibleStencilTables<StencilTables>(
|
||||
// convert to device stenciltable if necessary.
|
||||
_vertexStencilTable =
|
||||
convertToCompatibleStencilTable<StencilTable>(
|
||||
vertexStencils, _deviceContext);
|
||||
_varyingStencilTables =
|
||||
convertToCompatibleStencilTables<StencilTables>(
|
||||
_varyingStencilTable =
|
||||
convertToCompatibleStencilTable<StencilTable>(
|
||||
varyingStencils, _deviceContext);
|
||||
|
||||
// FIXME: we do extra copyings for Far::Stencils.
|
||||
@ -510,7 +510,7 @@ private:
|
||||
}
|
||||
|
||||
Far::TopologyRefiner * _refiner;
|
||||
Far::PatchTables * _farPatchTables;
|
||||
Far::PatchTable * _farPatchTable;
|
||||
|
||||
int _numVertices;
|
||||
int _maxValence;
|
||||
@ -521,8 +521,8 @@ private:
|
||||
VertexBufferDescriptor _vertexDesc;
|
||||
VertexBufferDescriptor _varyingDesc;
|
||||
|
||||
StencilTables const * _vertexStencilTables;
|
||||
StencilTables const * _varyingStencilTables;
|
||||
StencilTable const * _vertexStencilTable;
|
||||
StencilTable const * _varyingStencilTable;
|
||||
EvaluatorCache * _evaluatorCache;
|
||||
|
||||
PatchTable *_patchTable;
|
||||
|
@ -40,15 +40,7 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Forward declaration of friend classes:
|
||||
namespace Far {
|
||||
class TopologyRefiner;
|
||||
class PatchTablesFactory;
|
||||
}
|
||||
namespace Vtr {
|
||||
class Refinement;
|
||||
class FVarRefinement;
|
||||
}
|
||||
|
||||
//
|
||||
// FVarLevel:
|
||||
@ -82,17 +74,8 @@ namespace Vtr {
|
||||
// Everything is being declared public for now to facilitate access until its
|
||||
// clearer how this functionality will be provided.
|
||||
//
|
||||
namespace Vtr {
|
||||
|
||||
class FVarLevel {
|
||||
protected:
|
||||
friend class Level;
|
||||
friend class Refinement;
|
||||
friend class FVarRefinement;
|
||||
friend class Far::TopologyRefiner;
|
||||
friend class Far::PatchTablesFactory;
|
||||
|
||||
protected:
|
||||
public:
|
||||
//
|
||||
// Component tags -- trying to minimize the types needed here:
|
||||
//
|
||||
@ -171,7 +154,7 @@ protected:
|
||||
typedef ConstLocalIndexArray ConstSiblingArray;
|
||||
typedef LocalIndexArray SiblingArray;
|
||||
|
||||
protected:
|
||||
public:
|
||||
FVarLevel(Level const& level);
|
||||
~FVarLevel();
|
||||
|
||||
@ -250,7 +233,8 @@ protected:
|
||||
void print() const;
|
||||
void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector<Sibling>& fvSiblings) const;
|
||||
|
||||
protected:
|
||||
// Members temporarily public pending re-assessment of friends:
|
||||
public:
|
||||
Level const & _level;
|
||||
|
||||
// Linear interpolation options vary between channels:
|
||||
|
@ -40,12 +40,7 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
//
|
||||
// Forward declaration of friend classes:
|
||||
//
|
||||
namespace Far {
|
||||
class TopologyRefiner;
|
||||
}
|
||||
namespace Vtr {
|
||||
|
||||
//
|
||||
// FVarRefinement:
|
||||
@ -60,14 +55,8 @@ namespace Far {
|
||||
// the refinement between Levels serves most purposes and all that is required
|
||||
// in addition is a mapping from values in the child FVarLevel to the parent.
|
||||
//
|
||||
namespace Vtr {
|
||||
|
||||
class FVarRefinement {
|
||||
protected:
|
||||
friend class Refinement;
|
||||
friend class Far::TopologyRefiner;
|
||||
|
||||
protected:
|
||||
public:
|
||||
FVarRefinement(Refinement const& refinement, FVarLevel& parent, FVarLevel& child);
|
||||
~FVarRefinement();
|
||||
|
||||
@ -96,7 +85,8 @@ protected:
|
||||
void propagateValueCreases();
|
||||
void reclassifySemisharpValues();
|
||||
|
||||
protected:
|
||||
// Members temporarily public pending re-assessment of friends:
|
||||
public:
|
||||
//
|
||||
// Identify the Refinement, its Levels and assigned FVarLevels for more
|
||||
// immediate access -- child FVarLevel is non-const as it is to be assigned:
|
||||
|
@ -40,20 +40,9 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
// Forward declarations for friends:
|
||||
namespace Far {
|
||||
template <class MESH> class TopologyRefinerFactory;
|
||||
class TopologyRefinerFactoryBase;
|
||||
class TopologyRefiner;
|
||||
class PatchTablesFactory;
|
||||
}
|
||||
|
||||
namespace Vtr {
|
||||
|
||||
class Refinement;
|
||||
class QuadRefinement;
|
||||
class TriRefinement;
|
||||
class FVarRefinement;
|
||||
class FVarLevel;
|
||||
|
||||
//
|
||||
@ -63,13 +52,12 @@ class FVarLevel;
|
||||
// level can be used as the base level of another subdivision hierarchy and can
|
||||
// be considered a complete mesh independent of its ancestors. It currently
|
||||
// does contain a "depth" member -- as some inferences can then be made about
|
||||
// the topology (i.e. all quads or all tris if not level 0) but that is still
|
||||
// under consideration (e.g. a "regular" flag would serve the same purpose, and
|
||||
// level 0 may even be regular).
|
||||
// the topology (i.e. all quads or all tris if not level 0).
|
||||
//
|
||||
// This class is intended for private use within the library. So really its
|
||||
// interface should be fully protected and only those library classes that need
|
||||
// it will be declared as friends, e.g. Refinement.
|
||||
// This class is intended for private use within the library. There are still
|
||||
// opportunities to specialize levels -- e.g. those supporing N-sided faces vs
|
||||
// those are are purely quads or tris -- so we prefer to insulate it from public
|
||||
// access.
|
||||
//
|
||||
// The represenation of topology here is to store six topological relationships
|
||||
// in tables of integers. Each is stored in its own array(s) so the result is
|
||||
@ -87,38 +75,6 @@ class FVarLevel;
|
||||
// the Far layer essentially store 5 of these 6 in a permuted form -- we add
|
||||
// the face-edges here to simplify refinement.
|
||||
//
|
||||
// Notes/limitations/stuff to do -- much of this code still reflects the early days
|
||||
// when it was being prototyped and so it does not conform to OSD standards in many
|
||||
// ways:
|
||||
// - superficial stylistic issues:
|
||||
// . replacing "m" prefix with "_" on member variables
|
||||
// - done
|
||||
// . replace "access" and "modify" prefixes on Array methods with "get"
|
||||
// - done
|
||||
// - replace use of "...Count" with "GetNum..."
|
||||
// - use of Vertex vs Vert in non-local (or any?) methods
|
||||
// - review public/protected/friend accessibility
|
||||
//
|
||||
// Most are more relevant to the refinement, which used to be part of this class:
|
||||
// - short cuts that need revisiting:
|
||||
// - support for face-vert counts > 4
|
||||
// - support for edge-face counts > 2
|
||||
// - some neighborhood searches avoidable with more "local indexing"
|
||||
// - identify (informally) where scheme-specific code will be needed, so far:
|
||||
// - topological splitting and associated marking
|
||||
// - really the only variable here is whether to generate tris or
|
||||
// quads from non-quads
|
||||
// - interpolation
|
||||
// - potentially not part of the pre-processing required for FarMesh
|
||||
// and where it appears *not* to be needed:
|
||||
// - subdivision of sharpness values
|
||||
// - classification of vertex type/mask
|
||||
// - apply classification of vertices (computing Rules or masks)
|
||||
// - apply to base/course level on conversion
|
||||
// - apply to child level after subdivision of sharpness
|
||||
// - keep in mind desired similarity with FarMesh tables for ease of transfer
|
||||
// (contradicts previous point to some degree)
|
||||
//
|
||||
|
||||
class Level {
|
||||
|
||||
@ -262,7 +218,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
// Debugging aides -- unclear what will persist...
|
||||
// Debugging aides:
|
||||
enum TopologyError {
|
||||
TOPOLOGY_MISSING_EDGE_FACES=0,
|
||||
TOPOLOGY_MISSING_EDGE_VERTS,
|
||||
@ -295,8 +251,7 @@ public:
|
||||
void print(const Refinement* parentRefinement = 0) const;
|
||||
|
||||
public:
|
||||
// High-level topology queries -- these are likely to be moved elsewhere, but here
|
||||
// is the best place for them for now...
|
||||
// High-level topology queries -- these may be moved elsewhere:
|
||||
|
||||
bool isSingleCreasePatch(Index face, float* sharpnessOut=NULL, int* rotationOut=NULL) const;
|
||||
|
||||
@ -325,19 +280,7 @@ public:
|
||||
int gatherTriRegularCornerVertexPatchPoints( Index fIndex, Index patchVerts[], int cornerVertInFace) const;
|
||||
int gatherTriRegularCornerEdgePatchPoints( Index fIndex, Index patchVerts[], int cornerEdgeInFace) const;
|
||||
|
||||
protected:
|
||||
|
||||
friend class Refinement;
|
||||
friend class QuadRefinement;
|
||||
friend class TriRefinement;
|
||||
friend class FVarRefinement;
|
||||
friend class FVarLevel;
|
||||
|
||||
template <class MESH> friend class Far::TopologyRefinerFactory;
|
||||
friend class Far::TopologyRefinerFactoryBase;
|
||||
friend class Far::TopologyRefiner;
|
||||
friend class Far::PatchTablesFactory;
|
||||
|
||||
public:
|
||||
// Sizing methods used to construct a level to populate:
|
||||
void resizeFaces( int numFaces);
|
||||
void resizeFaceVertices(int numFaceVertsTotal);
|
||||
@ -418,13 +361,14 @@ protected:
|
||||
void resizeVertexEdges(Index vertIndex, int count);
|
||||
void trimVertexEdges( Index vertIndex, int count);
|
||||
|
||||
protected:
|
||||
public:
|
||||
//
|
||||
// Plans where to have a few specific friend classes properly construct the topology,
|
||||
// e.g. the Refinement class. There is now clearly a need to have some class
|
||||
// construct full topology given only a simple face-vertex list. That can be done
|
||||
// externally (either a Factory outside Vtr or another Vtr construction helper), but
|
||||
// until we decide where, the required implementation is defined here.
|
||||
// Initial plans were to have a few specific classes properly construct the
|
||||
// topology from scratch, e.g. the Refinement class and a Factory class for
|
||||
// the base level, by populating all topological relations. The need to have
|
||||
// a class construct full topology given only a simple face-vertex list, made
|
||||
// it necessary to write code to define and orient all relations -- and most
|
||||
// of that seemed best placed here.
|
||||
//
|
||||
bool completeTopologyFromFaceVertices();
|
||||
Index findEdge(Index v0, Index v1, ConstIndexArray v0Edges) const;
|
||||
@ -437,7 +381,8 @@ protected:
|
||||
|
||||
IndexArray shareFaceVertCountsAndOffsets() const;
|
||||
|
||||
protected:
|
||||
// Members temporarily public pending re-assessment of friends:
|
||||
public:
|
||||
//
|
||||
// A Level is independent of subdivision scheme or options. While it may have been
|
||||
// affected by them in its construction, they are not associated with it -- a Level
|
||||
|
@ -39,14 +39,8 @@
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class TopologyRefiner;
|
||||
class PatchTablesFactory;
|
||||
}
|
||||
|
||||
namespace Vtr {
|
||||
|
||||
class SparseSelector;
|
||||
class FVarRefinement;
|
||||
|
||||
//
|
||||
@ -60,7 +54,7 @@ class FVarRefinement;
|
||||
// of topological splits that the supported subdivisions schemes collectively require, i.e. those
|
||||
// list in Sdc::SplitType. Note the virtual requirements expected of the subclasses in the list
|
||||
// of protected methods -- they differ mainly in the topology that is created in the child Level
|
||||
// and not the propagation of tags through refinement, subdivision of sharpness values of the
|
||||
// and not the propagation of tags through refinement, subdivision of sharpness values or the
|
||||
// treatment of face-varying data. The primary subclasses are QuadRefinement and TriRefinement.
|
||||
//
|
||||
// At a high level, all that is necessary in terms of interface is to construct, initialize
|
||||
@ -156,22 +150,15 @@ public:
|
||||
Index getChildFaceBaseFace(Index f) const { return _childFaceBaseFaceIndex[f]; }
|
||||
|
||||
//
|
||||
// Non-public methods:
|
||||
// Modifiers intended for internal/protected use:
|
||||
//
|
||||
protected:
|
||||
|
||||
friend class FVarRefinement;
|
||||
friend class SparseSelector;
|
||||
|
||||
friend class Far::TopologyRefiner;
|
||||
friend class Far::PatchTablesFactory;
|
||||
|
||||
public:
|
||||
|
||||
IndexArray getFaceChildFaces(Index parentFace);
|
||||
IndexArray getFaceChildEdges(Index parentFace);
|
||||
IndexArray getEdgeChildEdges(Index parentEdge);
|
||||
|
||||
protected:
|
||||
public:
|
||||
//
|
||||
// Tags have now been added per-component in Level, but there is additional need to tag
|
||||
// components within Refinement -- we can't tag the parent level components for any
|
||||
@ -204,10 +191,8 @@ protected:
|
||||
unsigned char _indexInParent : 2; // index of child wrt parent: 0-3, or iterative if N > 4
|
||||
};
|
||||
|
||||
//
|
||||
// Remaining methods should remain protected -- for use by subclasses...
|
||||
//
|
||||
protected:
|
||||
// Remaining methods should really be protected -- for use by subclasses...
|
||||
public:
|
||||
//
|
||||
// Methods involved in constructing the parent-to-child mapping -- when the
|
||||
// refinement is sparse, additional methods are needed to identify the selection:
|
||||
@ -309,12 +294,12 @@ protected:
|
||||
//
|
||||
void subdivideFVarChannels();
|
||||
|
||||
protected:
|
||||
// Members temporarily public pending re-assessment of friends:
|
||||
public:
|
||||
//
|
||||
// Data members -- the logical grouping of some of these (and methods that make use
|
||||
// of them) may lead to grouping them into a few utility classes or structs...
|
||||
//
|
||||
friend class Level; // Access for some debugging information
|
||||
|
||||
// Defined on construction:
|
||||
Level const * _parent;
|
||||
|
@ -70,10 +70,11 @@ GetReorderedHbrVertexData(
|
||||
{ // Populate base level
|
||||
// note : topological ordering is identical between Hbr and Vtr
|
||||
// for the base level
|
||||
OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0);
|
||||
|
||||
int nfaces = refiner.GetNumFaces(0),
|
||||
nedges = refiner.GetNumEdges(0),
|
||||
nverts = refiner.GetNumVertices(0);
|
||||
int nfaces = refBaseLevel.GetNumFaces(),
|
||||
nedges = refBaseLevel.GetNumEdges(),
|
||||
nverts = refBaseLevel.GetNumVertices();
|
||||
|
||||
maps[0].faces.resize(nfaces, 0);
|
||||
maps[0].edges.resize(nedges, 0);
|
||||
@ -85,7 +86,7 @@ GetReorderedHbrVertexData(
|
||||
|
||||
for (int edge = 0; edge <nedges; ++edge) {
|
||||
|
||||
ConstIndexArray vtrVerts = refiner.GetEdgeVertices(0, edge);
|
||||
ConstIndexArray vtrVerts = refBaseLevel.GetEdgeVertices(edge);
|
||||
|
||||
Hvertex const * v0 = hmesh.GetVertex(vtrVerts[0]),
|
||||
* v1 = hmesh.GetVertex(vtrVerts[1]);
|
||||
@ -110,16 +111,19 @@ GetReorderedHbrVertexData(
|
||||
LevelMap & previous = maps[level-1],
|
||||
& current = maps[level];
|
||||
|
||||
current.faces.resize(refiner.GetNumFaces(level), 0);
|
||||
current.edges.resize(refiner.GetNumEdges(level), 0);
|
||||
current.verts.resize(refiner.GetNumVertices(level), 0);
|
||||
OpenSubdiv::Far::TopologyLevel const & refLevel = refiner.GetLevel(level);
|
||||
OpenSubdiv::Far::TopologyLevel const & refPrevLevel = refiner.GetLevel(level-1);
|
||||
|
||||
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
|
||||
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) {
|
||||
current.faces[childFaces[i]] = f->GetChild(i);
|
||||
}
|
||||
@ -127,33 +131,33 @@ GetReorderedHbrVertexData(
|
||||
// populate child face-verts -- when present (none for Loop subdivision)
|
||||
if (!schemeIsLoop) {
|
||||
Hvertex * v = f->Subdivide();
|
||||
Index childVert = refiner.GetFaceChildVertex(level-1, face);
|
||||
Index childVert = refPrevLevel.GetFaceChildVertex(face);
|
||||
assert(v->GetParentFace());
|
||||
current.verts[childVert] = v;
|
||||
}
|
||||
}
|
||||
|
||||
for (int edge=0; edge < refiner.GetNumEdges(level-1); ++edge) {
|
||||
for (int edge=0; edge < refPrevLevel.GetNumEdges(); ++edge) {
|
||||
// populate child edge-verts
|
||||
Index childVert = refiner.GetEdgeChildVertex(level-1,edge);
|
||||
Index childVert = refPrevLevel.GetEdgeChildVertex(edge);
|
||||
Hhalfedge * e = previous.edges[edge];
|
||||
Hvertex * v = e->Subdivide();
|
||||
assert(v->GetParentEdge());
|
||||
current.verts[childVert] = v;
|
||||
}
|
||||
|
||||
for (int vert = 0; vert < refiner.GetNumVertices(level-1); ++vert) {
|
||||
for (int vert = 0; vert < refPrevLevel.GetNumVertices(); ++vert) {
|
||||
// populate child vert-verts
|
||||
Index childVert = refiner.GetVertexChildVertex(level-1, vert);
|
||||
Index childVert = refPrevLevel.GetVertexChildVertex(vert);
|
||||
Hvertex * v = previous.verts[vert]->Subdivide();
|
||||
current.verts[childVert] = v;
|
||||
assert(v->GetParentVertex());
|
||||
}
|
||||
|
||||
// populate child edges
|
||||
for (int edge=0; edge < refiner.GetNumEdges(level); ++edge) {
|
||||
for (int edge=0; edge < refLevel.GetNumEdges(); ++edge) {
|
||||
|
||||
ConstIndexArray vtrVerts = refiner.GetEdgeVertices(level, edge);
|
||||
ConstIndexArray vtrVerts = refLevel.GetEdgeVertices(edge);
|
||||
|
||||
Hvertex const * v0 = current.verts[vtrVerts[0]],
|
||||
* v1 = current.verts[vtrVerts[1]];
|
||||
@ -166,7 +170,7 @@ GetReorderedHbrVertexData(
|
||||
assert(e);
|
||||
current.edges[edge] = e;
|
||||
}
|
||||
ecount += refiner.GetNumEdges(level-1);
|
||||
ecount += refPrevLevel.GetNumEdges();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner,
|
||||
fvarWidth = 2;
|
||||
|
||||
int numValuesTotal = refiner.GetNumFVarValuesTotal(channel),
|
||||
numValues0 = refiner.GetNumFVarValues(0, channel);
|
||||
numValues0 = refiner.GetLevel(0).GetNumFVarValues(channel);
|
||||
|
||||
if (shape.uvs.empty() or numValuesTotal<=0) {
|
||||
return;
|
||||
@ -57,7 +57,7 @@ InterpolateFVarData(OpenSubdiv::Far::TopologyRefiner & refiner,
|
||||
std::vector<FVarVertex> buffer(numValuesTotal);
|
||||
|
||||
int maxlevel = refiner.GetMaxLevel(),
|
||||
numValuesM = refiner.GetNumFVarValues(maxlevel, channel);
|
||||
numValuesM = refiner.GetLevel(maxlevel).GetNumFVarValues(channel);
|
||||
|
||||
memcpy(&buffer[0], &shape.uvs[0], shape.uvs.size()*sizeof(float));
|
||||
|
||||
|
@ -155,14 +155,14 @@ InterpolateVtrVertexData(const char *shapeStr, Scheme scheme, int maxlevel,
|
||||
|
||||
// populate coarse mesh positions
|
||||
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],
|
||||
shape->verts[i*3+1],
|
||||
shape->verts[i*3+2]);
|
||||
}
|
||||
|
||||
T * verts = &data[0];
|
||||
refiner->Interpolate(verts, verts+refiner->GetNumVertices(0));
|
||||
refiner->Interpolate(verts, verts+refiner->GetLevel(0).GetNumVertices());
|
||||
|
||||
delete shape;
|
||||
return refiner;
|
||||
@ -204,7 +204,7 @@ TopologyRefinerFactory<Shape>::assignComponentTopology(
|
||||
Far::TopologyRefiner & refiner, Shape const & shape) {
|
||||
|
||||
{ // Face relations:
|
||||
int nfaces = refiner.GetNumFaces(0);
|
||||
int nfaces = refiner.GetLevel(0).GetNumFaces();
|
||||
|
||||
for (int i=0, ofs=0; i < nfaces; ++i) {
|
||||
|
||||
@ -235,7 +235,7 @@ TopologyRefinerFactory<Shape>::assignFaceVaryingTopology(
|
||||
// UV layyout (we only parse 1 channel)
|
||||
if (not shape.faceuvs.empty()) {
|
||||
|
||||
int nfaces = refiner.GetNumFaces(0),
|
||||
int nfaces = refiner.GetLevel(0).GetNumFaces(),
|
||||
channel = refiner.createBaseFVarChannel( (int)shape.uvs.size()/2 );
|
||||
|
||||
for (int i=0, ofs=0; i < nfaces; ++i) {
|
||||
@ -273,7 +273,7 @@ TopologyRefinerFactory<Shape>::assignComponentTags(
|
||||
|
||||
for (int j=0; j<(int)t->intargs.size()-1; j += 2) {
|
||||
|
||||
OpenSubdiv::Vtr::Index edge = refiner.FindEdge(/*level*/0, t->intargs[j], t->intargs[j+1]);
|
||||
OpenSubdiv::Vtr::Index edge = refiner.GetLevel(0).FindEdge(t->intargs[j], t->intargs[j+1]);
|
||||
if (edge==OpenSubdiv::Vtr::INDEX_INVALID) {
|
||||
printf("cannot find edge for crease tag (%d,%d)\n", t->intargs[j], t->intargs[j+1] );
|
||||
return false;
|
||||
@ -287,7 +287,7 @@ TopologyRefinerFactory<Shape>::assignComponentTags(
|
||||
|
||||
for (int j=0; j<(int)t->intargs.size(); ++j) {
|
||||
int vertex = t->intargs[j];
|
||||
if (vertex<0 or vertex>=refiner.GetNumVertices(/*level*/0)) {
|
||||
if (vertex<0 or vertex>=refiner.GetLevel(0).GetNumVertices()) {
|
||||
printf("cannot find vertex for corner tag (%d)\n", vertex );
|
||||
return false;
|
||||
} else {
|
||||
|
@ -52,7 +52,7 @@ GLFWwindow* g_window=0;
|
||||
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
|
||||
#include <far/stencilTablesFactory.h>
|
||||
#include <far/stencilTableFactory.h>
|
||||
|
||||
#include "../../regression/common/cmp_utils.h"
|
||||
#include "../../regression/common/hbr_utils.h"
|
||||
@ -246,19 +246,19 @@ checkVertexBuffer(
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void
|
||||
buildStencilTables(
|
||||
buildStencilTable(
|
||||
const FarTopologyRefiner &refiner,
|
||||
Far::StencilTables const **vertexStencils,
|
||||
Far::StencilTables const **varyingStencils)
|
||||
Far::StencilTable const **vertexStencils,
|
||||
Far::StencilTable const **varyingStencils)
|
||||
{
|
||||
Far::StencilTablesFactory::Options soptions;
|
||||
Far::StencilTableFactory::Options soptions;
|
||||
soptions.generateOffsets = true;
|
||||
soptions.generateIntermediateLevels = true;
|
||||
|
||||
*vertexStencils = Far::StencilTablesFactory::Create(refiner, soptions);
|
||||
*vertexStencils = Far::StencilTableFactory::Create(refiner, soptions);
|
||||
|
||||
soptions.interpolationMode = Far::StencilTablesFactory::INTERPOLATE_VARYING;
|
||||
*varyingStencils = Far::StencilTablesFactory::Create(refiner, soptions);
|
||||
soptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_VARYING;
|
||||
*varyingStencils = Far::StencilTableFactory::Create(refiner, soptions);
|
||||
}
|
||||
|
||||
|
||||
@ -269,9 +269,9 @@ checkMeshCPU( FarTopologyRefiner *refiner,
|
||||
const std::vector<xyzVV>& coarseverts,
|
||||
xyzmesh * refmesh) {
|
||||
|
||||
Far::StencilTables const *vertexStencils;
|
||||
Far::StencilTables const *varyingStencils;
|
||||
buildStencilTables(*refiner, &vertexStencils, &varyingStencils);
|
||||
Far::StencilTable const *vertexStencils;
|
||||
Far::StencilTable const *varyingStencils;
|
||||
buildStencilTable(*refiner, &vertexStencils, &varyingStencils);
|
||||
|
||||
assert(coarseverts.size() == (size_t)refiner->GetNumVerticesTotal());
|
||||
|
||||
@ -284,7 +284,7 @@ checkMeshCPU( FarTopologyRefiner *refiner,
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(0, 3, 3),
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3),
|
||||
Osd::VertexBufferDescriptor(refiner->GetLevel(0).GetNumVertices()*3, 3, 3),
|
||||
vertexStencils);
|
||||
|
||||
int result = checkVertexBuffer(*refiner, refmesh, vb->BindCpuBuffer(),
|
||||
@ -303,9 +303,9 @@ checkMeshCPUGL(FarTopologyRefiner *refiner,
|
||||
const std::vector<xyzVV>& coarseverts,
|
||||
xyzmesh * refmesh) {
|
||||
|
||||
Far::StencilTables const *vertexStencils;
|
||||
Far::StencilTables const *varyingStencils;
|
||||
buildStencilTables(*refiner, &vertexStencils, &varyingStencils);
|
||||
Far::StencilTable const *vertexStencils;
|
||||
Far::StencilTable const *varyingStencils;
|
||||
buildStencilTable(*refiner, &vertexStencils, &varyingStencils);
|
||||
|
||||
Osd::CpuGLVertexBuffer *vb = Osd::CpuGLVertexBuffer::Create(3,
|
||||
refiner->GetNumVerticesTotal());
|
||||
@ -316,7 +316,7 @@ checkMeshCPUGL(FarTopologyRefiner *refiner,
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(0, 3, 3),
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3),
|
||||
Osd::VertexBufferDescriptor(refiner->GetLevel(0).GetNumVertices()*3, 3, 3),
|
||||
vertexStencils);
|
||||
|
||||
int result = checkVertexBuffer(*refiner, refmesh,
|
||||
|
@ -149,23 +149,25 @@ int main(int, char **) {
|
||||
|
||||
{ // Output OBJ of the highest level refined -----------
|
||||
|
||||
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
|
||||
|
||||
// Print vertex positions
|
||||
for (int level=0, firstVert=0; level<=maxlevel; ++level) {
|
||||
|
||||
if (level==maxlevel) {
|
||||
for (int vert=0; vert<refiner->GetNumVertices(maxlevel); ++vert) {
|
||||
for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
|
||||
float const * pos = verts[firstVert+vert].GetPosition();
|
||||
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
|
||||
}
|
||||
} else {
|
||||
firstVert += refiner->GetNumVertices(level);
|
||||
firstVert += refiner->GetLevel(level).GetNumVertices();
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
assert(fverts.size()==4);
|
||||
|
@ -454,23 +454,25 @@ int main(int, char **) {
|
||||
|
||||
{ // Output OBJ of the highest level refined -----------
|
||||
|
||||
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
|
||||
|
||||
// Print vertex positions
|
||||
for (int level=0, firstVert=0; level<=maxlevel; ++level) {
|
||||
|
||||
if (level==maxlevel) {
|
||||
for (int vert=0; vert<refiner->GetNumVertices(maxlevel); ++vert) {
|
||||
for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
|
||||
float const * pos = verts[firstVert+vert].GetPosition();
|
||||
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
|
||||
}
|
||||
} else {
|
||||
firstVert += refiner->GetNumVertices(level);
|
||||
firstVert += refiner->GetLevel(level).GetNumVertices();
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
assert(fverts.size()==4);
|
||||
|
@ -339,7 +339,7 @@ FarTopologyRefinerFactory<OsdHbrConverter>::assignComponentTopology(
|
||||
OsdHbrConverter::EdgeMap & edges = const_cast<OsdHbrConverter &>(conv).GetEdges();
|
||||
|
||||
{ // Face relations:
|
||||
int nfaces = refiner.GetNumFaces(/*level*/0);
|
||||
int nfaces = refiner.GetLevel(0).GetNumFaces();
|
||||
for (int i=0; i < nfaces; ++i) {
|
||||
|
||||
IndexArray dstFaceVerts = refiner.setBaseFaceVertices(i);
|
||||
@ -377,7 +377,7 @@ FarTopologyRefinerFactory<OsdHbrConverter>::assignComponentTopology(
|
||||
}
|
||||
|
||||
{ // 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);
|
||||
|
||||
@ -451,7 +451,7 @@ FarTopologyRefinerFactory<OsdHbrConverter>::assignComponentTags(
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
|
@ -166,11 +166,11 @@ int main(int, char **) {
|
||||
// particles at the location of the refined vertices (don't forget to
|
||||
// turn shading on in the viewport to see the colors)
|
||||
|
||||
int nverts = refiner->GetNumVertices(maxlevel);
|
||||
int nverts = refiner->GetLevel(maxlevel).GetNumVertices();
|
||||
|
||||
// Position the 'verts' pointer to the first vertex of our 'maxlevel' level
|
||||
for (int level=0; level<maxlevel; ++level) {
|
||||
verts += refiner->GetNumVertices(level);
|
||||
verts += refiner->GetLevel(level).GetNumVertices();
|
||||
}
|
||||
|
||||
// Output particle positions
|
||||
|
@ -214,7 +214,7 @@ int main(int, char **) {
|
||||
|
||||
// Allocate & interpolate the 'face-varying' primvar data
|
||||
int channel = 0,
|
||||
nCoarseFVVerts = refiner->GetNumFVarValues(0, channel);
|
||||
nCoarseFVVerts = refiner->GetLevel(0).GetNumFVarValues(channel);
|
||||
|
||||
std::vector<FVarVertex> fvBuffer(refiner->GetNumFVarValuesTotal(channel));
|
||||
FVarVertex * fvVerts = &fvBuffer[0];
|
||||
@ -229,16 +229,18 @@ int main(int, char **) {
|
||||
|
||||
{ // Output OBJ of the highest level refined -----------
|
||||
|
||||
Far::TopologyLevel const & refLastLevel = refiner->GetLevel(maxlevel);
|
||||
|
||||
// Print vertex positions
|
||||
for (int level=0, firstVert=0; level<=maxlevel; ++level) {
|
||||
|
||||
if (level==maxlevel) {
|
||||
for (int vert=0; vert<refiner->GetNumVertices(level); ++vert) {
|
||||
for (int vert=0; vert<refLastLevel.GetNumVertices(); ++vert) {
|
||||
float const * pos = verts[firstVert+vert].GetPosition();
|
||||
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
|
||||
}
|
||||
} 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) {
|
||||
|
||||
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];
|
||||
printf("vt %f %f\n", uv.u, uv.v);
|
||||
}
|
||||
} else {
|
||||
firstVert += refiner->GetNumFVarValues(level, channel);
|
||||
firstVert += refiner->GetLevel(level).GetNumFVarValues(channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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),
|
||||
fvverts = refiner->GetFVarFaceValues(maxlevel, face, channel);
|
||||
Far::ConstIndexArray fverts = refLastLevel.GetFaceVertices(face),
|
||||
fvverts = refLastLevel.GetFVarFaceValues(face, channel);
|
||||
|
||||
// all refined Catmark faces should be quads
|
||||
assert(fverts.size()==4 and fvverts.size()==4);
|
||||
|
@ -26,13 +26,13 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Tutorial description:
|
||||
//
|
||||
// This tutorial shows how to create and manipulate FarStencilTables. We use the
|
||||
// This tutorial shows how to create and manipulate FarStencilTable. We use the
|
||||
// factorized stencils to interpolate vertex primvar data buffers.
|
||||
//
|
||||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
#include <opensubdiv/far/stencilTables.h>
|
||||
#include <opensubdiv/far/stencilTablesFactory.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/far/stencilTableFactory.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@ -118,17 +118,17 @@ int main(int, char **) {
|
||||
refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel));
|
||||
|
||||
|
||||
// Use the FarStencilTables factory to create discrete stencil tables
|
||||
// Use the FarStencilTable factory to create discrete stencil table
|
||||
// note: we only want stencils for the highest refinement level.
|
||||
Far::StencilTablesFactory::Options options;
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateIntermediateLevels=false;
|
||||
options.generateOffsets=true;
|
||||
|
||||
Far::StencilTables const * stencilTables =
|
||||
Far::StencilTablesFactory::Create(*refiner, options);
|
||||
Far::StencilTable const * stencilTable =
|
||||
Far::StencilTableFactory::Create(*refiner, options);
|
||||
|
||||
// Allocate vertex primvar buffer (1 stencil for each vertex)
|
||||
int nstencils = stencilTables->GetNumStencils();
|
||||
int nstencils = stencilTable->GetNumStencils();
|
||||
std::vector<Vertex> vertexBuffer(nstencils);
|
||||
|
||||
|
||||
@ -141,7 +141,7 @@ int main(int, char **) {
|
||||
|
||||
// Apply stencils on the control vertex data to update the primvar data
|
||||
// of the refined vertices.
|
||||
stencilTables->UpdateValues(controlValues, &vertexBuffer[0]);
|
||||
stencilTable->UpdateValues(controlValues, &vertexBuffer[0]);
|
||||
}
|
||||
|
||||
{ // Visualization with Maya : print a MEL script that generates particles
|
||||
@ -156,7 +156,7 @@ int main(int, char **) {
|
||||
}
|
||||
|
||||
delete refiner;
|
||||
delete stencilTables;
|
||||
delete stencilTable;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -27,13 +27,13 @@
|
||||
// Tutorial description:
|
||||
//
|
||||
// This tutorial shows how to create and manipulate both 'vertex' and 'varying'
|
||||
// Far::StencilTables to interpolate 2 primvar data buffers: vertex positions and
|
||||
// Far::StencilTable to interpolate 2 primvar data buffers: vertex positions and
|
||||
// vertex colors.
|
||||
//
|
||||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
#include <opensubdiv/far/stencilTables.h>
|
||||
#include <opensubdiv/far/stencilTablesFactory.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/far/stencilTableFactory.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@ -121,10 +121,10 @@ int main(int, char **) {
|
||||
int maxlevel = 4;
|
||||
refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel));
|
||||
|
||||
int nverts = refiner->GetNumVertices(maxlevel);
|
||||
int nverts = refiner->GetLevel(maxlevel).GetNumVertices();
|
||||
|
||||
// Use the Far::StencilTables factory to create discrete stencil tables
|
||||
Far::StencilTablesFactory::Options options;
|
||||
// Use the Far::StencilTable factory to create discrete stencil table
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateIntermediateLevels=false; // only the highest refinement level.
|
||||
options.generateOffsets=true;
|
||||
|
||||
@ -133,10 +133,10 @@ int main(int, char **) {
|
||||
//
|
||||
|
||||
// Create stencils table for 'vertex' interpolation
|
||||
options.interpolationMode=Far::StencilTablesFactory::INTERPOLATE_VERTEX;
|
||||
options.interpolationMode=Far::StencilTableFactory::INTERPOLATE_VERTEX;
|
||||
|
||||
Far::StencilTables const * vertexStencils =
|
||||
Far::StencilTablesFactory::Create(*refiner, options);
|
||||
Far::StencilTable const * vertexStencils =
|
||||
Far::StencilTableFactory::Create(*refiner, options);
|
||||
assert(nverts==vertexStencils->GetNumStencils());
|
||||
|
||||
// Allocate vertex primvar buffer (1 stencil for each vertex)
|
||||
@ -150,10 +150,10 @@ int main(int, char **) {
|
||||
//
|
||||
|
||||
// Create stencils table for 'varying' interpolation
|
||||
options.interpolationMode=Far::StencilTablesFactory::INTERPOLATE_VARYING;
|
||||
options.interpolationMode=Far::StencilTableFactory::INTERPOLATE_VARYING;
|
||||
|
||||
Far::StencilTables const * varyingStencils =
|
||||
Far::StencilTablesFactory::Create(*refiner, options);
|
||||
Far::StencilTable const * varyingStencils =
|
||||
Far::StencilTableFactory::Create(*refiner, options);
|
||||
assert(nverts==varyingStencils->GetNumStencils());
|
||||
|
||||
// Allocate varying primvar buffer (1 stencil for each vertex)
|
||||
|
@ -41,7 +41,7 @@
|
||||
//
|
||||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
#include <opensubdiv/far/patchTablesFactory.h>
|
||||
#include <opensubdiv/far/patchTableFactory.h>
|
||||
#include <opensubdiv/far/endCapGregoryBasisPatchFactory.h>
|
||||
#include <opensubdiv/far/patchMap.h>
|
||||
#include <opensubdiv/far/ptexIndices.h>
|
||||
@ -155,14 +155,14 @@ int main(int, char **) {
|
||||
refiner->Interpolate(&verts[0], &verts[g_nverts]);
|
||||
|
||||
|
||||
// Generate a set of Far::PatchTables that we will use to evaluate the
|
||||
// Generate a set of Far::PatchTable that we will use to evaluate the
|
||||
// surface limit
|
||||
Far::EndCapGregoryBasisPatchFactory endcapFactory(*refiner);
|
||||
Far::PatchTables const * patchTables =
|
||||
Far::PatchTablesFactory::Create(*refiner, Far::PatchTablesFactory::Options());
|
||||
Far::PatchTable const * patchTable =
|
||||
Far::PatchTableFactory::Create(*refiner, Far::PatchTableFactory::Options());
|
||||
|
||||
// Create a Far::PatchMap to help locating patches in the table
|
||||
Far::PatchMap patchmap(*patchTables);
|
||||
Far::PatchMap patchmap(*patchTable);
|
||||
|
||||
// Create a Far::PtexIndices to help find indices of ptex faces.
|
||||
Far::PtexIndices ptexIndices(*refiner);
|
||||
@ -185,14 +185,14 @@ int main(int, char **) {
|
||||
t = (float)rand()/(float)RAND_MAX;
|
||||
|
||||
// Locate the patch corresponding to the face ptex idx and (s,t)
|
||||
Far::PatchTables::PatchHandle const * handle =
|
||||
Far::PatchTable::PatchHandle const * handle =
|
||||
patchmap.FindPatch(face, s, t);
|
||||
assert(handle);
|
||||
|
||||
// Evaluate the patch weights, identify the CVs and compute the limit frame:
|
||||
patchTables->EvaluateBasis(*handle, s, t, pWeights, dsWeights, dtWeights);
|
||||
patchTable->EvaluateBasis(*handle, s, t, pWeights, dsWeights, dtWeights);
|
||||
|
||||
Far::ConstIndexArray cvs = patchTables->GetPatchVertices(*handle);
|
||||
Far::ConstIndexArray cvs = patchTable->GetPatchVertices(*handle);
|
||||
|
||||
LimitFrame & dst = samples[count];
|
||||
dst.Clear();
|
||||
|
@ -26,12 +26,12 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Tutorial description:
|
||||
//
|
||||
// This tutorial shows how to create and manipulate tables of cascading stencils.
|
||||
// This tutorial shows how to create and manipulate table of cascading stencils.
|
||||
//
|
||||
// We initalize a Far::TopologyRefiner initalized with a cube and apply uniform
|
||||
// refinement. We then use a Far::StencilTablesFactory to generate stencil
|
||||
// tables. We set the factory Options to not factorize intermediate levels,
|
||||
// thus giving tables of "cascading" stencils.
|
||||
// refinement. We then use a Far::StencilTableFactory to generate a stencil
|
||||
// table. We set the factory Options to not factorize intermediate levels,
|
||||
// thus giving a table of "cascading" stencils.
|
||||
//
|
||||
// We then apply the stencils to the vertex position primvar data, and insert
|
||||
// a hierarchical edit at level 1. This edit is smoothed by the application
|
||||
@ -42,8 +42,8 @@
|
||||
//
|
||||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
#include <opensubdiv/far/stencilTables.h>
|
||||
#include <opensubdiv/far/stencilTablesFactory.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/far/stencilTableFactory.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@ -131,17 +131,17 @@ int main(int, char **) {
|
||||
int maxlevel = 4;
|
||||
refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel));
|
||||
|
||||
// Use the FarStencilTables factory to create cascading stencil tables
|
||||
// Use the FarStencilTable factory to create cascading stencil table
|
||||
// note: we want stencils for the each refinement level
|
||||
// "cascade" mode is achieved by setting "factorizeIntermediateLevels"
|
||||
// to false
|
||||
Far::StencilTablesFactory::Options options;
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateIntermediateLevels=true;
|
||||
options.factorizeIntermediateLevels=false;
|
||||
options.generateOffsets=true;
|
||||
|
||||
Far::StencilTables const * stencilTables =
|
||||
Far::StencilTablesFactory::Create(*refiner, options);
|
||||
Far::StencilTable const * stencilTable =
|
||||
Far::StencilTableFactory::Create(*refiner, options);
|
||||
|
||||
std::vector<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
|
||||
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);
|
||||
if (level>0) {
|
||||
@ -160,7 +160,7 @@ int main(int, char **) {
|
||||
start = end;
|
||||
end += nverts;
|
||||
|
||||
stencilTables->UpdateValues(srcVerts, destVerts, start, end);
|
||||
stencilTable->UpdateValues(srcVerts, destVerts, start, end);
|
||||
|
||||
// apply 2 hierarchical edits on level 1 vertices
|
||||
if (level==1) {
|
||||
@ -180,9 +180,11 @@ int main(int, char **) {
|
||||
// Print vertex positions
|
||||
for (int level=1, firstvert=0; level<=maxlevel; ++level) {
|
||||
|
||||
Far::TopologyLevel const & refLevel = refiner->GetLevel(level);
|
||||
|
||||
printf("g level_%d\n", level);
|
||||
|
||||
int nverts = refiner->GetNumVertices(level);
|
||||
int nverts = refLevel.GetNumVertices();
|
||||
for (int vert=0; vert<nverts; ++vert) {
|
||||
float const * pos = verts[vert].GetPosition();
|
||||
printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
|
||||
@ -190,9 +192,9 @@ int main(int, char **) {
|
||||
verts += nverts;
|
||||
|
||||
// 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
|
||||
assert(fverts.size()==4);
|
||||
@ -208,7 +210,7 @@ int main(int, char **) {
|
||||
}
|
||||
|
||||
delete refiner;
|
||||
delete stencilTables;
|
||||
delete stencilTable;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -31,7 +31,7 @@
|
||||
//
|
||||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
#include <opensubdiv/far/stencilTablesFactory.h>
|
||||
#include <opensubdiv/far/stencilTableFactory.h>
|
||||
#include <opensubdiv/osd/cpuEvaluator.h>
|
||||
#include <opensubdiv/osd/cpuVertexBuffer.h>
|
||||
|
||||
@ -75,22 +75,22 @@ int main(int, char **) {
|
||||
//
|
||||
// Setup phase
|
||||
//
|
||||
Far::StencilTables const * stencilTables = NULL;
|
||||
Far::StencilTable const * stencilTable = NULL;
|
||||
{ // Setup Context
|
||||
Far::TopologyRefiner const * refiner = createTopologyRefiner(maxlevel);
|
||||
|
||||
// Setup a factory to create FarStencilTables (for more details see
|
||||
// Setup a factory to create FarStencilTable (for more details see
|
||||
// Far tutorials)
|
||||
Far::StencilTablesFactory::Options options;
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateOffsets=true;
|
||||
options.generateIntermediateLevels=false;
|
||||
|
||||
stencilTables = Far::StencilTablesFactory::Create(*refiner, options);
|
||||
stencilTable = Far::StencilTableFactory::Create(*refiner, options);
|
||||
|
||||
nCoarseVerts = refiner->GetNumVertices(0);
|
||||
nRefinedVerts = stencilTables->GetNumStencils();
|
||||
nCoarseVerts = refiner->GetLevel(0).GetNumVertices();
|
||||
nRefinedVerts = stencilTable->GetNumStencils();
|
||||
|
||||
// We are done with Far: cleanup tables
|
||||
// We are done with Far: cleanup table
|
||||
delete refiner;
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ int main(int, char **) {
|
||||
// Launch the computation
|
||||
Osd::CpuEvaluator::EvalStencils(vbuffer, srcDesc,
|
||||
vbuffer, dstDesc,
|
||||
stencilTables);
|
||||
stencilTable);
|
||||
}
|
||||
|
||||
{ // Visualization with Maya : print a MEL script that generates particles
|
||||
@ -128,7 +128,7 @@ int main(int, char **) {
|
||||
printf("-c 1;\n");
|
||||
}
|
||||
|
||||
delete stencilTables;
|
||||
delete stencilTable;
|
||||
delete vbuffer;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user