Merge branch 'dev' into 358

This commit is contained in:
Ignacio Lillo 2015-05-23 00:30:03 -03:00
commit 79eb6d5aeb
92 changed files with 2877 additions and 2565 deletions

View File

@ -45,11 +45,11 @@ First, *Far* provides the tools to refine subdivision topology
either uniform or sparse, where extraordinary features are automatically
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.

View File

@ -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>

View File

@ -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.
----

View File

@ -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**

View File

@ -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);

View File

@ -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>(

View File

@ -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;

View File

@ -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;
}
//------------------------------------------------------------------------------

View File

@ -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];

View File

@ -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();

View File

@ -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_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"
" 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) {

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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
}

View File

@ -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;
};

View File

@ -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 =

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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 ) );
}
//------------------------------------------------------------------------------

View File

@ -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();
}

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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:

View File

@ -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);

View File

@ -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:

View File

@ -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
@ -117,7 +117,7 @@ EndCapLegacyGregoryPatchFactory::Finalize(
quadOffsetsTable->resize(numTotalGregoryPatches*4);
if (numTotalGregoryPatches > 0) {
PatchTables::QuadOffsetsTable::value_type *p =
PatchTable::QuadOffsetsTable::value_type *p =
&((*quadOffsetsTable)[0]);
for (size_t i = 0; i < numGregoryPatches; ++i) {
getQuadOffsets(level, _gregoryFaceIndices[i], p);
@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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;
};

View File

@ -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;

View File

@ -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 {

View File

@ -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();

View File

@ -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 */

View File

@ -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()]);
}
}

View File

@ -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,15 +125,15 @@ 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,
static PatchTable * Create(TopologyRefiner const & refiner,
Options options=Options());
private:
@ -145,10 +145,10 @@ private:
//
// Methods for allocating and managing the patch table data arrays:
//
static PatchTables * createUniform(TopologyRefiner const & refiner,
static PatchTable * createUniform(TopologyRefiner const & refiner,
Options options);
static PatchTables * createAdaptive(TopologyRefiner const & refiner,
static PatchTable * createAdaptive(TopologyRefiner const & refiner,
Options options);
//
@ -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 */

View File

@ -1,504 +0,0 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_FAR_PROTOSTENCIL_H
#define OPENSUBDIV3_FAR_PROTOSTENCIL_H
#include "../far/stencilTables.h"
#include <cstring>
#include <map>
#include <vector>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
//
// Proto-stencil Pool Allocator classes
//
// Strategy: allocate up-front a data pool for supporting PROTOSTENCILS of a size
// (maxsize) slightly above average. For the (rare) BIG_PROTOSTENCILS that
// require more support vertices, switch to (slow) heap allocation.
//
template <typename PROTOSTENCIL, class BIG_PROTOSTENCIL>
class Allocator {
public:
// Constructor
Allocator(int maxSize, bool interpolateVarying=false) :
_maxsize(maxSize), _interpolateVarying(interpolateVarying) { }
~Allocator() {
clearBigStencils();
}
// Returns the number of stencils in the allocator
int GetNumStencils() const {
return (int)_sizes.size();
}
// Returns the total number of control vertices used by the all the stencils
int GetNumVerticesTotal() const {
int nverts=0;
for (int i=0; i<GetNumStencils(); ++i) {
nverts += _sizes[i];
}
return nverts;
}
// Returns true if the pool allocator executes AddVaryingWithWeight
// factorization
bool GetInterpolateVarying() const {
return _interpolateVarying;
}
// Allocates storage for 'size' stencils with a fixed '_maxsize' supporting
// basis of control-vertices
void Resize(int numStencils) {
clearBigStencils();
int nelems = numStencils * _maxsize;
_sizes.clear();
_sizes.resize(numStencils);
_indices.resize(nelems);
_weights.resize(nelems);
}
// Adds the contribution of a supporting vertex that was not yet
// in the stencil
void PushBackVertex(Index protoStencil, Index vert, float weight) {
assert(weight!=0.0f);
int & size = _sizes[protoStencil];
Index idx = protoStencil*_maxsize;
if (size < (_maxsize-1)) {
idx += size;
_indices[idx] = vert;
_weights[idx] = weight;
} else {
BIG_PROTOSTENCIL * dst = 0;
if (size==(_maxsize-1)) {
dst = new BIG_PROTOSTENCIL(size, &_indices[idx], &_weights[idx]);
assert(_bigStencils.find(protoStencil)==_bigStencils.end());
_bigStencils[protoStencil] = dst;
} else {
assert(_bigStencils.find(protoStencil)!=_bigStencils.end());
dst = _bigStencils[protoStencil];
}
dst->_indices.push_back(vert);
dst->_weights.push_back(weight);
}
++size;
}
// Returns the local index in 'stencil' of a given vertex index, or
// INDEX_INVALID if the stencil does not contain this vertex
int FindVertex(Index protoStencil, Index vert) {
int size = _sizes[protoStencil];
Index const * indices = GetIndices(protoStencil);
for (int i=0; i<size; ++i) {
if (indices[i]==vert) {
return i;
}
}
return Vtr::INDEX_INVALID;
}
// Returns true of the stencil does not fit in the pool allocator and
// has been moved to the 'big' (slow) allocation pool
bool IsBigStencil(Index protoStencil) const {
assert(protoStencil<(int)_sizes.size());
return _sizes[protoStencil]>=_maxsize;
}
// Returns the size of a given proto-stencil
int GetSize(Index protoStencil) const {
assert(protoStencil<(int)_sizes.size());
return _sizes[protoStencil];
}
// Resolve memory pool and return a pointer to the indices of a given
// proto-stencil
Index * GetIndices(Index protoStencil) {
if (not IsBigStencil(protoStencil)) {
return &_indices[protoStencil*_maxsize];
} else {
assert(_bigStencils.find(protoStencil)!=_bigStencils.end());
return &_bigStencils[protoStencil]->_indices[0];
}
}
// Resolve memory pool and return a pointer to the weights of a given
// proto-stencil
float * GetWeights(Index protoStencil) {
if (not IsBigStencil(protoStencil)) {
return &_weights[protoStencil*_maxsize];
} else {
assert(_bigStencils.find(protoStencil)!=_bigStencils.end());
return &_bigStencils[protoStencil]->_weights[0];
}
}
// Returns the proto-stencil at a given index
PROTOSTENCIL operator[] (Index protoStencil) {
// If the allocator is empty, AddWithWeight() expects a coarse control
// vertex instead of a stencil and we only need to pass the index
return PROTOSTENCIL(protoStencil, this->GetNumStencils()>0 ? this : 0);
}
// Returns the proto-stencil at a given index
PROTOSTENCIL operator[] (Index protoStencil) const {
// If the allocator is empty, AddWithWeight() expects a coarse control
// vertex instead of a stencil and we only need to pass the index
return PROTOSTENCIL(protoStencil, this->GetNumStencils()>0 ?
const_cast<Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL> *>(this) : 0);
}
// Copy the proto-stencil out of the pool
int CopyStencil(Index protoStencil,
Index * indices, float * weights) {
int size = GetSize(protoStencil);
memcpy(indices, this->GetIndices(protoStencil), size*sizeof(Index));
memcpy(weights, this->GetWeights(protoStencil), size*sizeof(float));
return size;
}
protected:
// delete 'slow' memory pool
void clearBigStencils() {
typename BigStencilMap::iterator it;
for (it=_bigStencils.begin(); it!=_bigStencils.end(); ++it) {
delete it->second;
}
_bigStencils.clear();
}
protected:
int _maxsize; // max size of stencil that fits in the 'fast' pool
bool _interpolateVarying; // true for varying interpolation
std::vector<int> _sizes; // 'fast' memory pool
std::vector<int> _indices;
std::vector<float> _weights;
typedef std::map<int, BIG_PROTOSTENCIL *> BigStencilMap;
BigStencilMap _bigStencils; // 'slow' memory pool
};
//
// Specialization of the Allocator for stencils with tangents that require
// additional derivative weights.
//
template <typename PROTOSTENCIL, class BIG_PROTOSTENCIL>
class LimitAllocator : public Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL> {
public:
// Constructor
LimitAllocator(int maxSize) :
Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL>(maxSize) { }
void Resize(int size) {
Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL>::Resize(size);
int nelems = (int)this->_weights.size();
_tan1Weights.resize(nelems);
_tan2Weights.resize(nelems);
}
void PushBackVertex(Index protoStencil,
Index vert, float weight, float tan1Weight, float tan2Weight) {
assert(weight!=0.0f or tan1Weight!=0.0f or tan2Weight!=0.0f);
int & size = this->_sizes[protoStencil];
Index idx = protoStencil*this->_maxsize;
if (size < (this->_maxsize-1)) {
idx += size;
this->_indices[idx] = vert;
this->_weights[idx] = weight;
this->_tan1Weights[idx] = tan1Weight;
this->_tan2Weights[idx] = tan2Weight;
} else {
BIG_PROTOSTENCIL * dst = 0;
if (size==(this->_maxsize-1)) {
dst = new BIG_PROTOSTENCIL(size,
&this->_indices[idx], &this->_weights[idx],
&this->_tan1Weights[idx], &this->_tan2Weights[idx]);
assert(this->_bigStencils.find(protoStencil)==this->_bigStencils.end());
this->_bigStencils[protoStencil] = dst;
} else {
assert(this->_bigStencils.find(protoStencil)!=this->_bigStencils.end());
dst = this->_bigStencils[protoStencil];
}
dst->_indices.push_back(vert);
dst->_weights.push_back(weight);
dst->_tan1Weights.push_back(tan1Weight);
dst->_tan2Weights.push_back(tan2Weight);
}
++size;
}
float * GetTan1Weights(Index protoStencil) {
if (not this->IsBigStencil(protoStencil)) {
return &_tan1Weights[protoStencil*this->_maxsize];
} else {
assert(this->_bigStencils.find(protoStencil)!=this->_bigStencils.end());
return &this->_bigStencils[protoStencil]->_tan1Weights[0];
}
}
float * GetTan2Weights(Index protoStencil) {
if (not this->IsBigStencil(protoStencil)) {
return &_tan2Weights[protoStencil*this->_maxsize];
} else {
assert(this->_bigStencils.find(protoStencil)!=this->_bigStencils.end());
return &this->_bigStencils[protoStencil]->_tan2Weights[0];
}
}
PROTOSTENCIL operator[] (Index protoStencil) {
assert(this->GetNumStencils()>0);
return PROTOSTENCIL(protoStencil, this);
}
void ClearStencil(Index protoStencil) {
Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL>::ClearStencil(protoStencil);
memset(GetTan1Weights(protoStencil), 0, this->_sizes[protoStencil]*sizeof(float));
memset(GetTan2Weights(protoStencil), 0, this->_sizes[protoStencil]*sizeof(float));
}
int CopyLimitStencil(Index protoStencil,
Index * indices, float * weights, float * tan1Weights, float * tan2Weights) {
int size = Allocator<PROTOSTENCIL, BIG_PROTOSTENCIL>::CopyStencil(
protoStencil, indices, weights);
memcpy(tan1Weights, this->GetTan1Weights(protoStencil), size*sizeof(Index));
memcpy(tan2Weights, this->GetTan2Weights(protoStencil), size*sizeof(float));
return size;
}
private:
std::vector<float> _tan1Weights,
_tan2Weights;
};
//
// 'Big' Proto stencil classes
//
// When proto-stencils exceed _maxsize, fall back to dynamically allocated
// "BigStencils" (with 'Limit' specialization to handle tangents)
//
struct BigStencil {
BigStencil(int size, Index const * indices,
float const * weights) {
_indices.reserve(size+5); _indices.resize(size);
memcpy(&_indices.at(0), indices, size*sizeof(int));
_weights.reserve(size+5); _weights.resize(size);
memcpy(&_weights.at(0), weights, size*sizeof(float));
}
std::vector<Index> _indices;
std::vector<float> _weights;
};
struct BigLimitStencil : public BigStencil {
BigLimitStencil(int size, Index const * indices, float const * weights,
float const * tan1Weights, float const * tan2Weights) :
BigStencil(size, indices, weights) {
_tan1Weights.reserve(size+5); _tan1Weights.resize(size);
memcpy(&_tan1Weights.at(0), tan1Weights, size*sizeof(float));
_tan2Weights.reserve(size+5); _tan2Weights.resize(size);
memcpy(&_tan2Weights.at(0), tan2Weights, size*sizeof(float));
}
std::vector<float> _tan1Weights,
_tan2Weights;
};
//
// ProtoStencils
//
// Proto-stencils are used to interpolate stencils from supporting vertices.
// These stencils are backed by a pool allocator to allow for fast push-back
// of contributing control-vertices weights & indices as they are discovered.
//
class ProtoStencil {
public:
ProtoStencil(Index id, Allocator<ProtoStencil, BigStencil> * alloc) :
_id(id), _alloc(alloc) { }
void Clear() {
// Clear() can only ever be called on an empty stencil: nothing to do
assert(_alloc->GetSize(_id)==0);
}
// Factorize from a proto-stencil allocator
void AddWithWeight(ProtoStencil const & src, float weight) {
if(weight==0.0f) {
return;
}
if (src._alloc) {
// Stencil contribution
int srcSize = src._alloc->GetSize(src._id);
Index const * srcIndices = src._alloc->GetIndices(src._id);
float const * srcWeights = src._alloc->GetWeights(src._id);
addWithWeight(weight, srcSize, srcIndices, srcWeights);
} else {
// Coarse vertex contribution
Index n = _alloc->FindVertex(_id, src._id);
if (Vtr::IndexIsValid(n)) {
_alloc->GetWeights(_id)[n] += weight;
assert(_alloc->GetWeights(_id)[n]>0.0f);
} else {
_alloc->PushBackVertex(_id, src._id, weight);
}
}
}
// Factorize from a finished stencil table
void AddWithWeight(StencilTables const & table, Index idx, float weight) {
assert(idx<table.GetNumStencils());
if(weight==0.0f) {
return;
}
int srcSize = table.GetSizes()[idx];
Index offset = table.GetOffsets()[idx];
Index const * srcIndices = &table.GetControlIndices()[offset];
float const * srcWeights = &table.GetWeights()[offset];
addWithWeight(weight, srcSize, srcIndices, srcWeights);
}
void AddVaryingWithWeight(ProtoStencil const & src, float weight) {
if (_alloc->GetInterpolateVarying()) {
AddWithWeight(src, weight);
}
}
protected:
void addWithWeight(float weight, int srcSize,
Index const * srcIndices, float const * srcWeights) {
for (int i=0; i<srcSize; ++i) {
assert(srcWeights[i]!=0.0f);
float w = weight * srcWeights[i];
if (w==0.0f) {
continue;
}
Index vertIndex = srcIndices[i],
n = _alloc->FindVertex(_id, vertIndex);
if (Vtr::IndexIsValid(n)) {
_alloc->GetWeights(_id)[n] += w;
assert(_alloc->GetWeights(_id)[n]!=0.0f);
} else {
_alloc->PushBackVertex(_id, vertIndex, w);
}
}
}
Index _id;
Allocator<ProtoStencil, BigStencil> * _alloc;
};
typedef Allocator<ProtoStencil, BigStencil> StencilAllocator;
//
// ProtoLimitStencil
//
class ProtoLimitStencil {
public:
ProtoLimitStencil(Index id,
LimitAllocator<ProtoLimitStencil, BigLimitStencil> * alloc) :
_id(id), _alloc(alloc) { }
void Clear() {
// Clear() can only ever be called on an empty stencil: nothing to do
assert(_alloc->GetSize(_id)==0);
}
void AddWithWeight(Stencil const & src,
float weight, float tan1Weight, float tan2Weight) {
if(weight==0.0f and tan1Weight==0.0f and tan2Weight==0.0f) {
return;
}
int srcSize = *src.GetSizePtr();
Index const * srcIndices = src.GetVertexIndices();
float const * srcWeights = src.GetWeights();
for (int i=0; i<srcSize; ++i) {
float w = srcWeights[i];
if (w==0.0f) {
continue;
}
Index vertIndex = srcIndices[i],
n = _alloc->FindVertex(_id, vertIndex);
if (Vtr::IndexIsValid(n)) {
_alloc->GetWeights(_id)[n] += weight*w;
_alloc->GetTan1Weights(_id)[n] += tan1Weight*w;
_alloc->GetTan2Weights(_id)[n] += tan2Weight*w;
} else {
_alloc->PushBackVertex(_id, vertIndex,
weight*w, tan1Weight*w, tan2Weight*w);
}
}
}
private:
Index _id;
LimitAllocator<ProtoLimitStencil, BigLimitStencil> * _alloc;
};
typedef LimitAllocator<ProtoLimitStencil, BigLimitStencil> LimitStencilAllocator;
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv
#endif // OPENSUBDIV3_FAR_PROTOSTENCIL_H

View File

@ -0,0 +1,453 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../far/stencilBuilder.h"
#include "../far/topologyRefiner.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
namespace Internal {
struct PointDerivWeight {
float p;
float du;
float dv;
PointDerivWeight()
: p(0.0f), du(0.0f), dv(0.0f)
{ }
PointDerivWeight(float w)
: p(w), du(w), dv(w)
{ }
PointDerivWeight(float w, float wDu, float wDv)
: p(w), du(wDu), dv(wDv)
{ }
friend PointDerivWeight operator*(PointDerivWeight lhs,
PointDerivWeight const& rhs) {
lhs.p *= rhs.p;
lhs.du *= rhs.du;
lhs.dv *= rhs.dv;
return lhs;
}
PointDerivWeight& operator+=(PointDerivWeight const& rhs) {
p += rhs.p;
du += rhs.du;
dv += rhs.dv;
return *this;
}
};
/// Stencil table constructor set.
///
class WeightTable {
public:
WeightTable(int coarseVerts,
bool genCtrlVertStencils,
bool compactWeights)
: _size(0)
, _lastOffset(0)
, _coarseVertCount(coarseVerts)
, _compactWeights(compactWeights)
{
// These numbers were chosen by profiling production assets at uniform
// level 3.
size_t n = std::max(coarseVerts,
std::min(int(5*1024*1024),
coarseVerts*2));
_dests.reserve(n);
_sources.reserve(n);
_weights.reserve(n);
if (!genCtrlVertStencils)
return;
// Generate trivial control vert stencils
_sources.resize(coarseVerts);
_weights.resize(coarseVerts);
_dests.resize(coarseVerts);
_indices.resize(coarseVerts);
_sizes.resize(coarseVerts);
for (int i = 0; i < coarseVerts; i++) {
_indices[i] = i;
_sizes[i] = 1;
_dests[i] = i;
_sources[i] = i;
_weights[i] = 1.0;
}
_size = _sources.size();
_lastOffset = _sources.size() - 1;
}
template <class W, class WACCUM>
void AddWithWeight(int src, int dest, W weight, WACCUM weights)
{
// Factorized stencils are expressed purely in terms of the control
// mesh verts. Without this flattening, level_i's weights would point
// to level_i-1, which would point to level_i-2, until the final level
// points to the control verts.
//
// So here, we check if the incoming vert (src) is in the control mesh,
// if it is, we can simply merge it without attempting to resolve it
// first.
if (src < _coarseVertCount) {
merge(src, dest, weight, W(1.0), _lastOffset, _size, weights);
return;
}
// src is not in the control mesh, so resolve all contributing coarse
// verts (src itself is made up of many control vert weights).
//
// Find the src stencil and number of contributing CVs.
int len = _sizes[src];
int start = _indices[src];
for (int i = start; i < start+len; i++) {
// Invariant: by processing each level in order and each vertex in
// dependent order, any src stencil vertex reference is guaranteed
// to consist only of coarse verts: therefore resolving src verts
// must yield verts in the coarse mesh.
assert(_sources[i] < _coarseVertCount);
// Merge each of src's contributing verts into this stencil.
merge(_sources[i], dest, weights.Get(i), weight,
_lastOffset, _size, weights);
}
}
class PointDerivAccumulator {
WeightTable* _tbl;
public:
PointDerivAccumulator(WeightTable* tbl) : _tbl(tbl)
{ }
void PushBack(PointDerivWeight weight) {
_tbl->_weights.push_back(weight.p);
_tbl->_duWeights.push_back(weight.du);
_tbl->_dvWeights.push_back(weight.dv);
}
void Add(size_t i, PointDerivWeight weight) {
_tbl->_weights[i] += weight.p;
_tbl->_duWeights[i] += weight.du;
_tbl->_dvWeights[i] += weight.dv;
}
PointDerivWeight Get(size_t index) {
return PointDerivWeight(_tbl->_weights[index],
_tbl->_duWeights[index],
_tbl->_dvWeights[index]);
}
};
PointDerivAccumulator GetPointDerivAccumulator() {
return PointDerivAccumulator(this);
};
class ScalarAccumulator {
WeightTable* _tbl;
public:
ScalarAccumulator(WeightTable* tbl) : _tbl(tbl)
{ }
void PushBack(PointDerivWeight weight) {
_tbl->_weights.push_back(weight.p);
}
void Add(size_t i, float w) {
_tbl->_weights[i] += w;
}
float Get(size_t index) {
return _tbl->_weights[index];
}
};
ScalarAccumulator GetScalarAccumulator() {
return ScalarAccumulator(this);
};
std::vector<int> const&
GetOffsets() const { return _indices; }
std::vector<int> const&
GetSizes() const { return _sizes; }
std::vector<int> const&
GetSources() const { return _sources; }
std::vector<float> const&
GetWeights() const { return _weights; }
std::vector<float> const&
GetDuWeights() const { return _duWeights; }
std::vector<float> const&
GetDvWeights() const { return _dvWeights; }
private:
// Merge a vertex weight into the stencil table, if there is an existing
// weight for a given source vertex it will be combined.
//
// PERFORMANCE: caution, this function is super hot.
template <class W, class WACCUM>
void merge(int src, int dst, W weight,
// Delaying weight*factor multiplication hides memory latency of
// accessing weight[i], yielding more stable performance.
W weightFactor,
// Similarly, passing offset & tableSize as params yields higher
// performance than accessing the class members directly.
int lastOffset, int tableSize, WACCUM weights)
{
// The lastOffset is the vertex we're currently processing, by
// leveraging this we need not lookup the dest stencil size or offset.
//
// Additionally, if the client does not want the resulting verts
// compacted, do not attempt to combine weights.
if (_compactWeights and _dests[lastOffset] == dst) {
// tableSize is exactly _sources.size(), but using tableSize is
// significantly faster.
for (int i = lastOffset; i < tableSize; i++) {
// If we find an existing vertex that matches src, we need to
// combine the weights to avoid duplicate entries for src.
if (_sources[i] == src) {
weights.Add(i, weight*weightFactor);
return;
}
}
}
// We haven't seen src yet, insert it as a new vertex weight.
add(src, dst, weight*weightFactor, weights);
}
// Add a new vertex weight to the stencil table.
template <class W, class WACCUM>
void add(int src, int dst, W weight, WACCUM weights)
{
// The _dests array has num(weights) elements mapping each individual
// element back to a specific stencil. The array is constructed in such
// a way that the current stencil being built is always at the end of
// the array, so if the dests array is empty or back() doesn't match
// dst, then we just started building a new stencil.
if (_dests.empty() or dst != _dests.back()) {
// _indices and _sizes always have num(stencils) elements so that
// stencils can be directly looked up by their index in these
// arrays. So here, ensure that they are large enough to hold the
// new stencil about to be built.
if (dst+1 > (int)_indices.size()) {
_indices.resize(dst+1);
_sizes.resize(dst+1);
}
// Initialize the new stencil's meta-data (offset, size).
_indices[dst] = _sources.size();
_sizes[dst] = 0;
// Keep track of where the current stencil begins, which lets us
// avoid having to look it up later.
_lastOffset = _sources.size();
}
// Cache the number of elements as an optimization, it's faster than
// calling size() on any of the vectors.
_size++;
// Increment the current stencil element size.
_sizes[dst]++;
// Track this element as belonging to the stencil "dst".
_dests.push_back(dst);
// Store the actual stencil data.
_sources.push_back(src);
weights.PushBack(weight);
}
// The following vectors are explicitly stored as non-interleaved elements
// to reduce cache misses.
// Stencil to destination vertex map.
std::vector<int> _dests;
// The actual stencil data.
std::vector<int> _sources;
std::vector<float> _weights;
std::vector<float> _duWeights;
std::vector<float> _dvWeights;
// Index data used to recover stencil-to-vertex mapping.
std::vector<int> _indices;
std::vector<int> _sizes;
// Acceleration members to avoid pointer chasing and reverse loops.
int _size;
int _lastOffset;
int _coarseVertCount;
bool _compactWeights;
};
StencilBuilder::StencilBuilder(int coarseVertCount,
bool isVarying,
bool genCtrlVertStencils,
bool compactWeights)
: _weightTable(new WeightTable(coarseVertCount,
genCtrlVertStencils,
compactWeights))
, _isVarying(isVarying)
{
}
StencilBuilder::~StencilBuilder()
{
delete _weightTable;
}
size_t
StencilBuilder::GetNumVerticesTotal() const
{
return _weightTable->GetWeights().size();
}
int
StencilBuilder::GetNumVertsInStencil(size_t stencilIndex) const
{
if (stencilIndex > _weightTable->GetSizes().size() - 1)
return 0;
return (int)_weightTable->GetSizes()[stencilIndex];
}
std::vector<int> const&
StencilBuilder::GetStencilOffsets() const {
return _weightTable->GetOffsets();
}
std::vector<int> const&
StencilBuilder::GetStencilSizes() const {
return _weightTable->GetSizes();
}
std::vector<int> const&
StencilBuilder::GetStencilSources() const {
return _weightTable->GetSources();
}
std::vector<float> const&
StencilBuilder::GetStencilWeights() const {
return _weightTable->GetWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDuWeights() const {
return _weightTable->GetDuWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDvWeights() const {
return _weightTable->GetDvWeights();
}
void
StencilBuilder::Index::AddWithWeight(Index const & src, float weight)
{
if (_owner->_isVarying)
return;
// Ignore no-op weights.
if (weight == 0)
return;
_owner->_weightTable->AddWithWeight(src._index, _index, weight,
_owner->_weightTable->GetScalarAccumulator());
}
void
StencilBuilder::Index::AddWithWeight(Stencil const& src, float weight)
{
if(weight == 0.0f) {
return;
}
int srcSize = *src.GetSizePtr();
Vtr::Index const * srcIndices = src.GetVertexIndices();
float const * srcWeights = src.GetWeights();
for (int i = 0; i < srcSize; ++i) {
float w = srcWeights[i];
if (w == 0.0f) {
continue;
}
Vtr::Index srcIndex = srcIndices[i];
float wgt = weight * w;
_owner->_weightTable->AddWithWeight(srcIndex, _index, wgt,
_owner->_weightTable->GetScalarAccumulator());
}
}
void
StencilBuilder::Index::AddWithWeight(Stencil const& src,
float weight, float du, float dv)
{
if(weight == 0.0f and du == 0.0f and dv == 0.0f) {
return;
}
int srcSize = *src.GetSizePtr();
Vtr::Index const * srcIndices = src.GetVertexIndices();
float const * srcWeights = src.GetWeights();
for (int i = 0; i < srcSize; ++i) {
float w = srcWeights[i];
if (w == 0.0f) {
continue;
}
Vtr::Index srcIndex = srcIndices[i];
PointDerivWeight wgt = PointDerivWeight(weight, du, dv) * w;
_owner->_weightTable->AddWithWeight(srcIndex, _index, wgt,
_owner->_weightTable->GetPointDerivAccumulator());
}
}
void
StencilBuilder::Index::AddVaryingWithWeight(Index const &src, float weight)
{
if (not _owner->_isVarying)
return;
// Ignore no-op weights.
if (weight == 0)
return;
_owner->_weightTable->AddWithWeight(src._index, _index, weight,
_owner->_weightTable->GetScalarAccumulator());
}
void
StencilBuilder::Index::AddFaceVaryingWithWeight(Index const &, float)
{
// Not supported.
}
} // end namespace Internal
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -0,0 +1,110 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef OPENSUBDIV3_FAR_STENCILBUILDER_H
#define OPENSUBDIV3_FAR_STENCILBUILDER_H
#include <vector>
#include "../version.h"
#include "../far/stencilTable.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
namespace Internal {
class WeightTable;
class StencilBuilder {
public:
StencilBuilder(int coarseVertCount,
bool isVarying=false,
bool genCtrlVertStencils=true,
bool compactWeights=true);
~StencilBuilder();
// TODO: noncopyable.
size_t GetNumVerticesTotal() const;
int GetNumVertsInStencil(size_t stencilIndex) const;
// Mapping from stencil[i] to it's starting offset in the sources[] and weights[] arrays;
std::vector<int> const& GetStencilOffsets() const;
// The number of contributing sources and weights in stencil[i]
std::vector<int> const& GetStencilSizes() const;
// The absolute source vertex offsets.
std::vector<int> const& GetStencilSources() const;
// The individual vertex weights, each weight is paired with one source.
std::vector<float> const& GetStencilWeights() const;
std::vector<float> const& GetStencilDuWeights() const;
std::vector<float> const& GetStencilDvWeights() const;
// Vertex Facade.
class Index {
public:
Index(StencilBuilder* owner, int index)
: _owner(owner)
, _index(index)
{}
// Add with point/vertex weight only.
void AddWithWeight(Index const & src, float weight);
void AddWithWeight(Stencil const& src, float weight);
// Add with first derivative.
void AddWithWeight(Stencil const& src,
float weight, float du, float dv);
void AddVaryingWithWeight(Index const &, float);
void AddFaceVaryingWithWeight(Index const &, float);
Index operator[](int index) const {
return Index(_owner, index+_index);
}
int GetOffset() const { return _index; }
void Clear() {/*nothing to do here*/}
private:
StencilBuilder* _owner;
int _index;
};
private:
WeightTable* _weightTable;
bool _isVarying;
};
} // end namespace Internal
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv
#endif // FAR_STENCILBUILDER_H

View File

@ -22,24 +22,102 @@
// language governing permissions and limitations under the Apache License.
//
#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

View File

@ -0,0 +1,482 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../far/stencilTableFactory.h"
#include "../far/stencilBuilder.h"
#include "../far/endCapGregoryBasisPatchFactory.h"
#include "../far/patchTable.h"
#include "../far/patchTableFactory.h"
#include "../far/patchMap.h"
#include "../far/topologyRefiner.h"
#include <cassert>
#include <algorithm>
#include <iostream>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
//------------------------------------------------------------------------------
void
StencilTableFactory::generateControlVertStencils(
int numControlVerts, Stencil & dst) {
// Control vertices contribute a single index with a weight of 1.0
for (int i=0; i<numControlVerts; ++i) {
*dst._size = 1;
*dst._indices = i;
*dst._weights = 1.0f;
dst.Next();
}
}
//
// StencilTable factory
//
StencilTable const *
StencilTableFactory::Create(TopologyRefiner const & refiner,
Options options) {
int maxlevel = std::min(int(options.maxLevel), refiner.GetMaxLevel());
if (maxlevel==0 and (not options.generateControlVerts)) {
StencilTable * result = new StencilTable;
result->_numControlVertices = refiner.GetLevel(0).GetNumVertices();
return result;
}
bool interpolateVarying = options.interpolationMode==INTERPOLATE_VARYING;
Internal::StencilBuilder builder(refiner.GetLevel(0).GetNumVertices(),
interpolateVarying,
/*genControlVerts*/ true,
/*compactWeights*/ true);
//
// Interpolate stencils for each refinement level using
// TopologyRefiner::InterpolateLevel<>()
//
Internal::StencilBuilder::Index srcIndex(&builder, 0);
Internal::StencilBuilder::Index dstIndex(&builder,
refiner.GetLevel(0).GetNumVertices());
for (int level=1; level<=maxlevel; ++level) {
if (not interpolateVarying) {
refiner.Interpolate(level, srcIndex, dstIndex);
} else {
refiner.InterpolateVarying(level, srcIndex, dstIndex);
}
srcIndex = dstIndex;
dstIndex = dstIndex[refiner.GetLevel(level).GetNumVertices()];
}
size_t firstOffset = refiner.GetLevel(0).GetNumVertices();
if (not options.generateIntermediateLevels)
firstOffset = srcIndex.GetOffset();
// Copy stencils from the pool allocator into the tables
// always initialize numControlVertices (useful for torus case)
StencilTable * result =
new StencilTable(refiner.GetLevel(0).GetNumVertices(),
builder.GetStencilOffsets(),
builder.GetStencilSizes(),
builder.GetStencilSources(),
builder.GetStencilWeights(),
options.generateControlVerts,
firstOffset);
return result;
}
//------------------------------------------------------------------------------
StencilTable const *
StencilTableFactory::Create(int numTables, StencilTable const ** tables) {
// XXXtakahito:
// This function returns NULL for empty inputs or erroneous condition.
// It's convenient for skipping varying stencils etc, however,
// other Create() API returns an empty stencil instead of NULL.
// They need to be consistent.
if ( (numTables<=0) or (not tables)) {
return NULL;
}
int ncvs = -1,
nstencils = 0,
nelems = 0;
for (int i=0; i<numTables; ++i) {
StencilTable const * st = tables[i];
// allow the tables could have a null entry.
if (!st) continue;
if (ncvs >= 0 and st->GetNumControlVertices() != ncvs) {
return NULL;
}
ncvs = st->GetNumControlVertices();
nstencils += st->GetNumStencils();
nelems += (int)st->GetControlIndices().size();
}
if (ncvs == -1) {
return NULL;
}
StencilTable * result = new StencilTable;
result->resize(nstencils, nelems);
int * sizes = &result->_sizes[0];
Index * indices = &result->_indices[0];
float * weights = &result->_weights[0];
for (int i=0; i<numTables; ++i) {
StencilTable const * st = tables[i];
if (!st) continue;
int st_nstencils = st->GetNumStencils(),
st_nelems = (int)st->_indices.size();
memcpy(sizes, &st->_sizes[0], st_nstencils*sizeof(int));
memcpy(indices, &st->_indices[0], st_nelems*sizeof(Index));
memcpy(weights, &st->_weights[0], st_nelems*sizeof(float));
sizes += st_nstencils;
indices += st_nelems;
weights += st_nelems;
}
result->_numControlVertices = ncvs;
// have to re-generate offsets from scratch
result->generateOffsets();
return result;
}
//------------------------------------------------------------------------------
StencilTable const *
StencilTableFactory::AppendEndCapStencilTable(
TopologyRefiner const &refiner,
StencilTable const * baseStencilTable,
StencilTable const * endCapStencilTable,
bool factorize) {
// factorize and append.
if (baseStencilTable == NULL or
endCapStencilTable == NULL) return NULL;
// endcap stencils have indices that are relative to the level
// (maxlevel) of subdivision. These indices need to be offset to match
// the indices from the multi-level adaptive stencil table.
// In addition: stencil table can be built with singular stencils
// (single weight of 1.0f) as place-holders for coarse mesh vertices,
// which also needs to be accounted for.
int stencilsIndexOffset = 0;
int controlVertsIndexOffset = 0;
int nBaseStencils = baseStencilTable->GetNumStencils();
int nBaseStencilsElements = (int)baseStencilTable->_indices.size();
{
int maxlevel = refiner.GetMaxLevel();
int nverts = refiner.GetNumVerticesTotal();
if (nBaseStencils == nverts) {
// the table contain stencils for the control vertices
//
// <----------------- nverts ------------------>
//
// +---------------+----------------------------+-----------------+
// | control verts | refined verts : (max lv) | endcap points |
// +---------------+----------------------------+-----------------+
// | base stencil table | endcap stencils |
// +--------------------------------------------+-----------------+
// : ^ /
// : \_________/
// <-------------------------------->
// stencilsIndexOffset
//
//
stencilsIndexOffset = nverts - refiner.GetLevel(maxlevel).GetNumVertices();
controlVertsIndexOffset = stencilsIndexOffset;
} else if (nBaseStencils == (nverts -refiner.GetLevel(0).GetNumVertices())) {
// the table does not contain stencils for the control vertices
//
// <----------------- nverts ------------------>
// <------ nBaseStencils ------->
// +---------------+----------------------------+-----------------+
// | control verts | refined verts : (max lv) | endcap points |
// +---------------+----------------------------+-----------------+
// | base stencil table | endcap stencils |
// +----------------------------+-----------------+
// : ^ /
// : \_________/
// <---------------->
// stencilsIndexOffset
// <-------------------------------->
// controlVertsIndexOffset
//
stencilsIndexOffset = nBaseStencils - refiner.GetLevel(maxlevel).GetNumVertices();
controlVertsIndexOffset = nverts - refiner.GetLevel(maxlevel).GetNumVertices();
} else {
// these are not the stencils you are looking for.
assert(0);
return NULL;
}
}
// copy all endcap stencils to proto stencils, and factorize if needed.
int nEndCapStencils = endCapStencilTable->GetNumStencils();
int nEndCapStencilsElements = 0;
Internal::StencilBuilder builder(refiner.GetLevel(0).GetNumVertices(),
/*isVarying*/ false,
/*genControlVerts*/ false,
/*compactWeights*/ factorize);
Internal::StencilBuilder::Index origin(&builder, 0);
Internal::StencilBuilder::Index dst = origin;
Internal::StencilBuilder::Index srcIdx = origin;
for (int i = 0 ; i < nEndCapStencils; ++i) {
Stencil src = endCapStencilTable->GetStencil(i);
dst = origin[i];
for (int j = 0; j < src.GetSize(); ++j) {
Index index = src.GetVertexIndices()[j];
float weight = src.GetWeights()[j];
if (weight == 0.0) continue;
if (factorize) {
dst.AddWithWeight(
baseStencilTable->GetStencil(index+stencilsIndexOffset),
weight);
} else {
srcIdx = origin[index + controlVertsIndexOffset];
dst.AddWithWeight(srcIdx, weight);
}
}
nEndCapStencilsElements += builder.GetNumVertsInStencil(i);
}
// create new stencil table
StencilTable * result = new StencilTable;
result->_numControlVertices = refiner.GetLevel(0).GetNumVertices();
result->resize(nBaseStencils + nEndCapStencils,
nBaseStencilsElements + nEndCapStencilsElements);
int* sizes = &result->_sizes[0];
Index * indices = &result->_indices[0];
float * weights = &result->_weights[0];
// put base stencils first
memcpy(sizes, &baseStencilTable->_sizes[0],
nBaseStencils*sizeof(int));
memcpy(indices, &baseStencilTable->_indices[0],
nBaseStencilsElements*sizeof(Index));
memcpy(weights, &baseStencilTable->_weights[0],
nBaseStencilsElements*sizeof(float));
sizes += nBaseStencils;
indices += nBaseStencilsElements;
weights += nBaseStencilsElements;
// endcap stencils second
for (int i = 0 ; i < nEndCapStencils; ++i) {
int size = builder.GetNumVertsInStencil(i);
int idx = builder.GetStencilOffsets()[i];
for (int j = 0; j < size; ++j) {
*indices++ = builder.GetStencilSources()[idx+j];
*weights++ = builder.GetStencilWeights()[idx+j];
}
*sizes++ = size;
}
// have to re-generate offsets from scratch
result->generateOffsets();
return result;
}
//------------------------------------------------------------------------------
LimitStencilTable const *
LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
LocationArrayVec const & locationArrays, StencilTable const * cvStencilsIn,
PatchTable const * patchTableIn) {
// Compute the total number of stencils to generate
int numStencils=0, numLimitStencils=0;
for (int i=0; i<(int)locationArrays.size(); ++i) {
assert(locationArrays[i].numLocations>=0);
numStencils += locationArrays[i].numLocations;
}
if (numStencils<=0) {
return 0;
}
bool uniform = refiner.IsUniform();
int maxlevel = refiner.GetMaxLevel();
StencilTable const * cvstencils = cvStencilsIn;
if (not cvstencils) {
// Generate stencils for the control vertices - this is necessary to
// properly factorize patches with control vertices at level 0 (natural
// regular patches, such as in a torus)
// note: the control vertices of the mesh are added as single-index
// stencils of weight 1.0f
StencilTableFactory::Options options;
options.generateIntermediateLevels = uniform ? false :true;
options.generateControlVerts = true;
options.generateOffsets = true;
// PERFORMANCE: We could potentially save some mem-copies by not
// instanciating the stencil tables and work directly off the source
// data.
cvstencils = StencilTableFactory::Create(refiner, options);
} else {
// Sanity checks
if (cvstencils->GetNumStencils() != (uniform ?
refiner.GetLevel(maxlevel).GetNumVertices() :
refiner.GetNumVerticesTotal())) {
return 0;
}
}
// If a stencil table was given, use it, otherwise, create a new one
PatchTable const * patchtable = patchTableIn;
if (not patchtable) {
// XXXX (manuelk) If no patch-table was passed, we should be able to
// infer the patches fairly easily from the refiner. Once more tags
// have been added to the refiner, maybe we can remove the need for the
// patch table.
PatchTableFactory::Options options;
options.SetEndCapType(
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
patchtable = PatchTableFactory::Create(refiner, options);
if (not cvStencilsIn) {
// if cvstencils is just created above, append endcap stencils
if (StencilTable const *endCapStencilTable =
patchtable->GetEndCapVertexStencilTable()) {
StencilTable const *table =
StencilTableFactory::AppendEndCapStencilTable(
refiner, cvstencils, endCapStencilTable);
delete cvstencils;
cvstencils = table;
}
}
} else {
// Sanity checks
if (patchtable->IsFeatureAdaptive()==uniform) {
if (not cvStencilsIn) {
assert(cvstencils and cvstencils!=cvStencilsIn);
delete cvstencils;
}
return 0;
}
}
assert(patchtable and cvstencils);
// Create a patch-map to locate sub-patches faster
PatchMap patchmap( *patchtable );
//
// Generate limit stencils for locations
//
Internal::StencilBuilder builder(refiner.GetLevel(0).GetNumVertices(),
/*isVarying*/ false,
/*genControlVerts*/ false,
/*compactWeights*/ true);
Internal::StencilBuilder::Index origin(&builder, 0);
Internal::StencilBuilder::Index dst = origin;
float wP[20], wDs[20], wDt[20];
for (size_t i=0; i<locationArrays.size(); ++i) {
LocationArray const & array = locationArrays[i];
assert(array.ptexIdx>=0);
for (int j=0; j<array.numLocations; ++j) {
float s = array.s[j],
t = array.t[j];
PatchMap::Handle const * handle =
patchmap.FindPatch(array.ptexIdx, s, t);
if (handle) {
ConstIndexArray cvs = patchtable->GetPatchVertices(*handle);
patchtable->EvaluateBasis(*handle, s, t, wP, wDs, wDt);
StencilTable const & src = *cvstencils;
dst = origin[numLimitStencils];
dst.Clear();
for (int k = 0; k < cvs.size(); ++k) {
dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k]);
}
++numLimitStencils;
}
}
}
if (not cvStencilsIn) {
delete cvstencils;
}
if (not patchTableIn) {
delete patchtable;
}
//
// Copy the proto-stencils into the limit stencil table
//
size_t firstOffset = refiner.GetLevel(0).GetNumVertices();
LimitStencilTable * result = new LimitStencilTable(
refiner.GetLevel(0).GetNumVertices(),
builder.GetStencilOffsets(),
builder.GetStencilSizes(),
builder.GetStencilSources(),
builder.GetStencilWeights(),
builder.GetStencilDuWeights(),
builder.GetStencilDvWeights(),
/*ctrlVerts*/false,
firstOffset);
return result;
}
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -27,7 +27,7 @@
#include "../version.h"
#include "../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);
};

View File

@ -1,573 +0,0 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "../far/stencilTablesFactory.h"
#include "../far/endCapGregoryBasisPatchFactory.h"
#include "../far/patchTables.h"
#include "../far/patchTablesFactory.h"
#include "../far/patchMap.h"
#include "../far/protoStencil.h"
#include "../far/topologyRefiner.h"
#include <cassert>
#include <algorithm>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
//------------------------------------------------------------------------------
void
StencilTablesFactory::generateControlVertStencils(
int numControlVerts, Stencil & dst) {
// Control vertices contribute a single index with a weight of 1.0
for (int i=0; i<numControlVerts; ++i) {
*dst._size = 1;
*dst._indices = i;
*dst._weights = 1.0f;
dst.Next();
}
}
//
// StencilTables factory
//
StencilTables const *
StencilTablesFactory::Create(TopologyRefiner const & refiner,
Options options) {
StencilTables * result = new StencilTables;
// always initialize numControlVertices (useful for torus case)
result->_numControlVertices = refiner.GetNumVertices(0);
int maxlevel = std::min(int(options.maxLevel), refiner.GetMaxLevel());
if (maxlevel==0 and (not options.generateControlVerts)) {
return result;
}
// 'maxsize' reflects the size of the default supporting basis factorized
// in the stencils, with a little bit of head-room. Each subdivision scheme
// has a set valence for 'regular' vertices, which drives the size of the
// supporting basis of control-vertices. The goal is to reduce the number
// of incidences where the pool allocator has to switch to dynamically
// allocated heap memory when encountering extraordinary vertices that
// require a larger supporting basis.
//
// The maxsize settings we use follow the assumption that the vast
// majority of the vertices in a mesh are regular, and that the valence
// of the extraordinary vertices is only higher by 1 edge.
int maxsize = 0;
bool interpolateVarying = false;
switch (options.interpolationMode) {
case INTERPOLATE_VERTEX: {
Sdc::SchemeType type = refiner.GetSchemeType();
switch (type) {
case Sdc::SCHEME_BILINEAR : maxsize = 5; break;
case Sdc::SCHEME_CATMARK : maxsize = 17; break;
case Sdc::SCHEME_LOOP : maxsize = 10; break;
default:
assert(0);
}
} break;
case INTERPOLATE_VARYING: maxsize = 5; interpolateVarying=true; break;
default:
assert(0);
}
std::vector<StencilAllocator> allocators(
options.generateIntermediateLevels ? maxlevel+1 : 2,
StencilAllocator(maxsize, interpolateVarying));
StencilAllocator * srcAlloc = &allocators[0],
* dstAlloc = &allocators[1];
//
// Interpolate stencils for each refinement level using
// TopologyRefiner::InterpolateLevel<>()
//
for (int level=1;level<=maxlevel; ++level) {
dstAlloc->Resize(refiner.GetNumVertices(level));
if (options.interpolationMode==INTERPOLATE_VERTEX) {
refiner.Interpolate(level, *srcAlloc, *dstAlloc);
} else {
refiner.InterpolateVarying(level, *srcAlloc, *dstAlloc);
}
if (options.generateIntermediateLevels) {
if (level<maxlevel) {
if (options.factorizeIntermediateLevels) {
srcAlloc = &allocators[level];
} else {
// if the stencils are dependent on the previous level of
// subdivision, pass an empty allocator to treat all parent
// vertices as control vertices
assert(allocators[0].GetNumStencils()==0);
}
dstAlloc = &allocators[level+1];
}
} else {
std::swap(srcAlloc, dstAlloc);
}
}
// Copy stencils from the pool allocator into the tables
{
// Add total number of stencils, weights & indices
int nelems = 0, nstencils=0;
if (options.generateIntermediateLevels) {
for (int level=0; level<=maxlevel; ++level) {
nstencils += allocators[level].GetNumStencils();
nelems += allocators[level].GetNumVerticesTotal();
}
} else {
nstencils = (int)srcAlloc->GetNumStencils();
nelems = srcAlloc->GetNumVerticesTotal();
}
// Allocate
result->_numControlVertices = refiner.GetNumVertices(0);
if (options.generateControlVerts) {
nstencils += result->_numControlVertices;
nelems += result->_numControlVertices;
}
result->resize(nstencils, nelems);
// Copy stencils
Stencil dst(&result->_sizes.at(0),
&result->_indices.at(0), &result->_weights.at(0));
if (options.generateControlVerts) {
generateControlVertStencils(result->_numControlVertices, dst);
}
if (options.generateIntermediateLevels) {
for (int level=1; level<=maxlevel; ++level) {
for (int i=0; i<allocators[level].GetNumStencils(); ++i) {
*dst._size = allocators[level].CopyStencil(i, dst._indices, dst._weights);
dst.Next();
}
}
} else {
for (int i=0; i<srcAlloc->GetNumStencils(); ++i) {
*dst._size = srcAlloc->CopyStencil(i, dst._indices, dst._weights);
dst.Next();
}
}
if (options.generateOffsets) {
result->generateOffsets();
}
}
return result;
}
//------------------------------------------------------------------------------
StencilTables const *
StencilTablesFactory::Create(int numTables, StencilTables const ** tables) {
// XXXtakahito:
// This function returns NULL for empty inputs or erroneous condition.
// It's convenient for skipping varying stencils etc, however,
// other Create() API returns an empty stencil instead of NULL.
// They need to be consistent.
if ( (numTables<=0) or (not tables)) {
return NULL;
}
int ncvs = -1,
nstencils = 0,
nelems = 0;
for (int i=0; i<numTables; ++i) {
StencilTables const * st = tables[i];
// allow the tables could have a null entry.
if (!st) continue;
if (ncvs >= 0 and st->GetNumControlVertices() != ncvs) {
return NULL;
}
ncvs = st->GetNumControlVertices();
nstencils += st->GetNumStencils();
nelems += (int)st->GetControlIndices().size();
}
if (ncvs == -1) {
return NULL;
}
StencilTables * result = new StencilTables;
result->resize(nstencils, nelems);
int * sizes = &result->_sizes[0];
Index * indices = &result->_indices[0];
float * weights = &result->_weights[0];
for (int i=0; i<numTables; ++i) {
StencilTables const * st = tables[i];
if (!st) continue;
int st_nstencils = st->GetNumStencils(),
st_nelems = (int)st->_indices.size();
memcpy(sizes, &st->_sizes[0], st_nstencils*sizeof(int));
memcpy(indices, &st->_indices[0], st_nelems*sizeof(Index));
memcpy(weights, &st->_weights[0], st_nelems*sizeof(float));
sizes += st_nstencils;
indices += st_nelems;
weights += st_nelems;
}
result->_numControlVertices = ncvs;
// have to re-generate offsets from scratch
result->generateOffsets();
return result;
}
//------------------------------------------------------------------------------
StencilTables const *
StencilTablesFactory::AppendEndCapStencilTables(
TopologyRefiner const &refiner,
StencilTables const *baseStencilTables,
StencilTables const *endCapStencilTables,
bool factorize) {
// factorize and append.
if (baseStencilTables == NULL or
endCapStencilTables == NULL) return NULL;
// endcap stencils have indices that are relative to the level
// (maxlevel) of subdivision. These indices need to be offset to match
// the indices from the multi-level adaptive stencil tables.
// In addition: stencil tables can be built with singular stencils
// (single weight of 1.0f) as place-holders for coarse mesh vertices,
// which also needs to be accounted for.
int stencilsIndexOffset = 0;
int controlVertsIndexOffset = 0;
int nBaseStencils = baseStencilTables->GetNumStencils();
int nBaseStencilsElements = (int)baseStencilTables->_indices.size();
{
int maxlevel = refiner.GetMaxLevel();
int nverts = refiner.GetNumVerticesTotal();
if (nBaseStencils == nverts) {
// the table contain stencils for the control vertices
//
// <----------------- nverts ------------------>
//
// +---------------+----------------------------+-----------------+
// | control verts | refined verts : (max lv) | endcap points |
// +---------------+----------------------------+-----------------+
// | base stencil tables | endcap stencils |
// +--------------------------------------------+-----------------+
// : ^ /
// : \_________/
// <-------------------------------->
// stencilsIndexOffset
//
//
stencilsIndexOffset = nverts - refiner.GetNumVertices(maxlevel);
controlVertsIndexOffset = stencilsIndexOffset;
} else if (nBaseStencils == (nverts -refiner.GetNumVertices(0))) {
// the table does not contain stencils for the control vertices
//
// <----------------- nverts ------------------>
// <------ nBaseStencils ------->
// +---------------+----------------------------+-----------------+
// | control verts | refined verts : (max lv) | endcap points |
// +---------------+----------------------------+-----------------+
// | base stencil tables | endcap stencils |
// +----------------------------+-----------------+
// : ^ /
// : \_________/
// <---------------->
// stencilsIndexOffset
// <-------------------------------->
// controlVertsIndexOffset
//
stencilsIndexOffset = nBaseStencils - refiner.GetNumVertices(maxlevel);
controlVertsIndexOffset = nverts - refiner.GetNumVertices(maxlevel);
} else {
// these are not the stencils you are looking for.
assert(0);
return NULL;
}
}
// copy all endcap stencils to proto stencils, and factorize if needed.
int nEndCapStencils = endCapStencilTables->GetNumStencils();
int nEndCapStencilsElements = 0;
// we exclude zero weight stencils. the resulting number of
// stencils of endcap may be different from input.
StencilAllocator allocator(16);
allocator.Resize(nEndCapStencils);
for (int i = 0 ; i < nEndCapStencils; ++i) {
Stencil src = endCapStencilTables->GetStencil(i);
allocator[i].Clear();
for (int j = 0; j < src.GetSize(); ++j) {
Index index = src.GetVertexIndices()[j];
float weight = src.GetWeights()[j];
if (weight == 0.0) continue;
if (factorize) {
allocator[i].AddWithWeight(*baseStencilTables,
index + stencilsIndexOffset,
weight);
} else {
allocator.PushBackVertex(i,
index + controlVertsIndexOffset,
weight);
}
}
nEndCapStencilsElements += allocator.GetSize(i);
}
// create new stencil tables
StencilTables * result = new StencilTables;
result->_numControlVertices = refiner.GetNumVertices(0);
result->resize(nBaseStencils + nEndCapStencils,
nBaseStencilsElements + nEndCapStencilsElements);
int* sizes = &result->_sizes[0];
Index * indices = &result->_indices[0];
float * weights = &result->_weights[0];
// put base stencils first
memcpy(sizes, &baseStencilTables->_sizes[0],
nBaseStencils*sizeof(int));
memcpy(indices, &baseStencilTables->_indices[0],
nBaseStencilsElements*sizeof(Index));
memcpy(weights, &baseStencilTables->_weights[0],
nBaseStencilsElements*sizeof(float));
sizes += nBaseStencils;
indices += nBaseStencilsElements;
weights += nBaseStencilsElements;
// endcap stencils second
for (int i = 0 ; i < nEndCapStencils; ++i) {
int size = allocator.GetSize(i);
for (int j = 0; j < size; ++j) {
*indices++ = allocator.GetIndices(i)[j];
*weights++ = allocator.GetWeights(i)[j];
}
*sizes++ = size;
}
// have to re-generate offsets from scratch
result->generateOffsets();
return result;
}
//------------------------------------------------------------------------------
LimitStencilTables const *
LimitStencilTablesFactory::Create(TopologyRefiner const & refiner,
LocationArrayVec const & locationArrays, StencilTables const * cvStencils,
PatchTables const * patchTables) {
// Compute the total number of stencils to generate
int numStencils=0, numLimitStencils=0;
for (int i=0; i<(int)locationArrays.size(); ++i) {
assert(locationArrays[i].numLocations>=0);
numStencils += locationArrays[i].numLocations;
}
if (numStencils<=0) {
return 0;
}
bool uniform = refiner.IsUniform();
int maxlevel = refiner.GetMaxLevel(), maxsize=17;
StencilTables const * cvstencils = cvStencils;
if (not cvstencils) {
// Generate stencils for the control vertices - this is necessary to
// properly factorize patches with control vertices at level 0 (natural
// regular patches, such as in a torus)
// note: the control vertices of the mesh are added as single-index
// stencils of weight 1.0f
StencilTablesFactory::Options options;
options.generateIntermediateLevels = uniform ? false :true;
options.generateControlVerts = true;
options.generateOffsets = true;
// XXXX (manuelk) We could potentially save some mem-copies by not
// instanciating the stencil tables and work directly off the pool
// allocators.
cvstencils = StencilTablesFactory::Create(refiner, options);
} else {
// Sanity checks
if (cvstencils->GetNumStencils() != (uniform ?
refiner.GetNumVertices(maxlevel) :
refiner.GetNumVerticesTotal())) {
return 0;
}
}
// If a stencil table was given, use it, otherwise, create a new one
PatchTables const * patchtables = patchTables;
if (not patchTables) {
// XXXX (manuelk) If no patch-tables was passed, we should be able to
// infer the patches fairly easily from the refiner. Once more tags
// have been added to the refiner, maybe we can remove the need for the
// patch tables.
PatchTablesFactory::Options options;
options.SetEndCapType(
Far::PatchTablesFactory::Options::ENDCAP_GREGORY_BASIS);
patchtables = PatchTablesFactory::Create(refiner, options);
if (not cvStencils) {
// if cvstencils is just created above, append endcap stencils
if (StencilTables const *endCapStencilTables =
patchtables->GetEndCapVertexStencilTables()) {
StencilTables const *tables =
StencilTablesFactory::AppendEndCapStencilTables(
refiner, cvstencils, endCapStencilTables);
delete cvstencils;
cvstencils = tables;
}
}
} else {
// Sanity checks
if (patchTables->IsFeatureAdaptive()==uniform) {
if (not cvStencils) {
assert(cvstencils and cvstencils!=cvStencils);
delete cvstencils;
}
return 0;
}
}
assert(patchtables and cvstencils);
// Create a patch-map to locate sub-patches faster
PatchMap patchmap( *patchtables );
//
// Generate limit stencils for locations
//
// Create a pool allocator to accumulate ProtoLimitStencils
LimitStencilAllocator alloc(maxsize);
alloc.Resize(numStencils);
// XXXX (manuelk) we can make uniform (bilinear) stencils faster with a
// dedicated code path that does not use PatchTables or the PatchMap
float wP[20], wDs[20], wDt[20];
for (int i=0, currentStencil=0; i<(int)locationArrays.size(); ++i) {
LocationArray const & array = locationArrays[i];
assert(array.ptexIdx>=0);
for (int j=0; j<array.numLocations; ++j, ++currentStencil) {
float s = array.s[j],
t = array.t[j];
PatchMap::Handle const * handle = patchmap.FindPatch(array.ptexIdx, s, t);
if (handle) {
ConstIndexArray cvs = patchTables->GetPatchVertices(*handle);
patchTables->EvaluateBasis(*handle, s, t, wP, wDs, wDt);
StencilTables const & src = *cvstencils;
ProtoLimitStencil dst = alloc[currentStencil];
dst.Clear();
for (int k = 0; k < cvs.size(); ++k) {
dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k]);
}
++numLimitStencils;
}
}
}
if (not cvStencils) {
delete cvstencils;
}
if (not patchTables) {
delete patchtables;
}
//
// Copy the proto-stencils into the limit stencil tables
//
LimitStencilTables * result = new LimitStencilTables;
int nelems = alloc.GetNumVerticesTotal();
if (nelems>0) {
// Allocate
result->resize(numLimitStencils, nelems);
// Copy stencils
LimitStencil dst(&result->_sizes.at(0), &result->_indices.at(0),
&result->_weights.at(0), &result->_duWeights.at(0),
&result->_dvWeights.at(0));
for (int i=0; i<alloc.GetNumStencils(); ++i) {
*dst._size = alloc.CopyLimitStencil(i, dst._indices, dst._weights,
dst._duWeights, dst._dvWeights);
dst.Next();
}
// XXXX manuelk should offset creation be optional ?
result->generateOffsets();
}
result->_numControlVertices = refiner.GetNumVertices(0);
return result;
}
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -192,18 +192,6 @@ TopologyRefiner::GetNumFVarValuesTotal(int channel) const {
return sum;
}
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:

View File

@ -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();
}
}

View File

@ -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];

View File

@ -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;

View File

@ -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,
CLStencilTable::CLStencilTable(Far::StencilTable const *stencilTable,
cl_context clContext) {
_numStencils = stencilTables->GetNumStencils();
_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);

View File

@ -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,
static CLStencilTable *Create(Far::StencilTable const *stencilTable,
DEVICE_CONTEXT context) {
return new CLStencilTables(stencilTables, context->GetContext());
return new CLStencilTable(stencilTable, context->GetContext());
}
CLStencilTables(Far::StencilTables const *stencilTables,
CLStencilTable(Far::StencilTable const *stencilTable,
cl_context clContext);
~CLStencilTables();
~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

View File

@ -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;
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 ++() {
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;
}

View File

@ -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,73 +111,43 @@ public:
/*end = */ stencilTable->GetNumStencils());
}
/// stencil evaluate function.
static bool EvalStencils(const float *src,
VertexBufferDescriptor const &srcDesc,
float *dst,
VertexBufferDescriptor const &dstDesc,
const int * sizes,
const int * offsets,
const int * indices,
const float * weights,
int start,
int end);
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,
STENCIL_TABLE const *stencilTable,
const CpuEvaluator *evaluator = NULL,
void * deviceContext = NULL) {
(void)evaluator; // unused
(void)deviceContext; // unused
return EvalStencils(srcBuffer->BindCpuBuffer(),
srcDesc,
dstBuffer->BindCpuBuffer(),
dstDesc,
dstDuBuffer->BindCpuBuffer(),
dstDuDesc,
dstDvBuffer->BindCpuBuffer(),
dstDvDesc,
&stencilTable->GetSizes()[0],
&stencilTable->GetOffsets()[0],
&stencilTable->GetControlIndices()[0],
&stencilTable->GetWeights()[0],
&stencilTable->GetDuWeights()[0],
&stencilTable->GetDvWeights()[0],
/*start = */ 0,
/*end = */ stencilTable->GetNumStencils());
}
static bool EvalStencils(const float *src,
VertexBufferDescriptor const &srcDesc,
float *dst,
VertexBufferDescriptor const &dstDesc,
float *dstDu,
VertexBufferDescriptor const &dstDuDesc,
float *dstDv,
VertexBufferDescriptor const &dstDvDesc,
const int * sizes,
const int * offsets,
const int * indices,
const float * weights,
const float * duWeights,
const float * dvWeights,
int start,
int end);
/// \brief Generic limit eval function. This function has a same
/// signature as other device kernels have so that it can be called
/// transparently.
/// \brief Static eval stencils function which takes raw CPU pointers for
/// input and output.
///
/// XXX: This interface is still work in progress. XXX
/// @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,
VertexBufferDescriptor const &dstDesc,
const int * sizes,
const int * offsets,
const int * indices,
const float * weights,
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
@ -188,21 +161,148 @@ public:
///
/// @param dstDesc vertex buffer descriptor for the output buffer
///
/// @param patchCoord array of locations to be evaluated.
/// @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 *dstDsBuffer,
VertexBufferDescriptor const &dstDsDesc,
DST_BUFFER *dstDtBuffer,
VertexBufferDescriptor const &dstDtDesc,
STENCIL_TABLE const *stencilTable,
const CpuEvaluator *evaluator = NULL,
void * deviceContext = NULL) {
(void)evaluator; // unused
(void)deviceContext; // unused
return EvalStencils(srcBuffer->BindCpuBuffer(),
srcDesc,
dstBuffer->BindCpuBuffer(),
dstDesc,
dstDsBuffer->BindCpuBuffer(),
dstDsDesc,
dstDtBuffer->BindCpuBuffer(),
dstDtDesc,
&stencilTable->GetSizes()[0],
&stencilTable->GetOffsets()[0],
&stencilTable->GetControlIndices()[0],
&stencilTable->GetWeights()[0],
&stencilTable->GetDuWeights()[0],
&stencilTable->GetDvWeights()[0],
/*start = */ 0,
/*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 *dstDs,
VertexBufferDescriptor const &dstDsDesc,
float *dstDt,
VertexBufferDescriptor const &dstDtDesc,
const int * sizes,
const int * offsets,
const int * indices,
const float * weights,
const float * duWeights,
const float * dvWeights,
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
/// 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 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,
static bool EvalPatches(SRC_BUFFER *srcBuffer,
VertexBufferDescriptor const &srcDesc,
DST_BUFFER *dstBuffer,
VertexBufferDescriptor const &dstDesc,
PatchCoordArray const &patchCoords,
Far::PatchTables const *patchTable,
int numPatchCoords,
PatchCoord const *patchCoords,
Far::PatchTable const *patchTable,
CpuEvaluator const *instance,
void * deviceContext = NULL) {
(void)instance; // unused
@ -212,17 +312,158 @@ public:
srcDesc,
dstBuffer->BindCpuBuffer(),
dstDesc,
numPatchCoords,
patchCoords,
patchTable);
}
/// \brief limit eval function.
static int EvalPatches(const float *src,
/// \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,
PatchCoordArray const &patchCoords,
Far::PatchTables const *patchTable);
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*/) {

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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,
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

View File

@ -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,
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);

View File

@ -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

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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; }

View File

@ -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,
vertexStencils = Far::StencilTableFactory::Create(*_refiner,
options);
}
if (numVaryingElements>0) {
options.interpolationMode =
Far::StencilTablesFactory::INTERPOLATE_VARYING;
Far::StencilTableFactory::INTERPOLATE_VARYING;
varyingStencils = Far::StencilTablesFactory::Create(*_refiner,
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;

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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();
}
}
};

View File

@ -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));

View File

@ -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 {

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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());
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}
//------------------------------------------------------------------------------

View File

@ -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)

View File

@ -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();

View File

@ -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;
}
//------------------------------------------------------------------------------

View File

@ -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;
}