Taking a first stab at a doxygen config file and matching cmake rules.

Also reformatting a chunk of FAR's comments to work w/ doxygen.

Closes #75
This commit is contained in:
Manuel Kraemer 2012-10-06 17:53:51 -07:00
parent 5f5207999f
commit 7fd99b421f
17 changed files with 2061 additions and 141 deletions

View File

@ -311,3 +311,5 @@ add_subdirectory(opensubdiv)
add_subdirectory(regression)
add_subdirectory(examples)
add_subdirectory(documentation)

View File

@ -0,0 +1,76 @@
#
# Copyright (C) Pixar. All rights reserved.
#
# This license governs use of the accompanying software. If you
# use the software, you accept this license. If you do not accept
# the license, do not use the software.
#
# 1. Definitions
# The terms "reproduce," "reproduction," "derivative works," and
# "distribution" have the same meaning here as under U.S.
# copyright law. A "contribution" is the original software, or
# any additions or changes to the software.
# A "contributor" is any person or entity that distributes its
# contribution under this license.
# "Licensed patents" are a contributor's patent claims that read
# directly on its contribution.
#
# 2. Grant of Rights
# (A) Copyright Grant- Subject to the terms of this license,
# including the license conditions and limitations in section 3,
# each contributor grants you a non-exclusive, worldwide,
# royalty-free copyright license to reproduce its contribution,
# prepare derivative works of its contribution, and distribute
# its contribution or any derivative works that you create.
# (B) Patent Grant- Subject to the terms of this license,
# including the license conditions and limitations in section 3,
# each contributor grants you a non-exclusive, worldwide,
# royalty-free license under its licensed patents to make, have
# made, use, sell, offer for sale, import, and/or otherwise
# dispose of its contribution in the software or derivative works
# of the contribution in the software.
#
# 3. Conditions and Limitations
# (A) No Trademark License- This license does not grant you
# rights to use any contributor's name, logo, or trademarks.
# (B) If you bring a patent claim against any contributor over
# patents that you claim are infringed by the software, your
# patent license from such contributor to the software ends
# automatically.
# (C) If you distribute any portion of the software, you must
# retain all copyright, patent, trademark, and attribution
# notices that are present in the software.
# (D) If you distribute any portion of the software in source
# code form, you may do so only under this license by including a
# complete copy of this license with your distribution. If you
# distribute any portion of the software in compiled or object
# code form, you may only do so under a license that complies
# with this license.
# (E) The software is licensed "as-is." You bear the risk of
# using it. The contributors give no express warranties,
# guarantees or conditions. You may have additional consumer
# rights under your local laws which this license cannot change.
# To the extent permitted under your local laws, the contributors
# exclude the implied warranties of merchantability, fitness for
# a particular purpose and non-infringement.
#
find_package(Doxygen)
if (DOXYGEN_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/OpenSubdiv.doxy ${CMAKE_CURRENT_BINARY_DIR}/OpenSubdiv.doxy @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE}
${CMAKE_CURRENT_BINARY_DIR}/OpenSubdiv.doxy
WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
else()
message(WARNING
"Doxyen was not found : support for Doxygen automated API documentation is disabled.")
endif()

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View File

@ -67,28 +67,31 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// Bilinear tables store the indexing tables required in order to compute
// the refined positions of a mesh without the help of a hierarchical data
// structure. The advantage of this representation is its ability to be executed
// in a massively parallel environment without data dependencies.
//
/// \brief Bilinear subdivision scheme tables.
///
/// Bilinear tables store the indexing tables required in order to compute
/// the refined positions of a mesh without the help of a hierarchical data
/// structure. The advantage of this representation is its ability to be executed
/// in a massively parallel environment without data dependencies.
///
template <class U> class FarBilinearSubdivisionTables : public FarSubdivisionTables<U> {
public:
// Memory required to store the indexing tables
/// Memory required to store the indexing tables
virtual int GetMemoryUsed() const;
// Compute the positions of refined vertices using the specified kernels
/// Compute the positions of refined vertices using the specified kernels
virtual void Apply( int level, void * data=0 ) const;
// Table accessors
/// Face-vertices indexing table accessor
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
/// Face-vertices indexing table accessor
FarTable<int> const & Get_F_ITa( ) const { return _F_ITa; }
// Returns the number of indexing tables needed to represent this particular
// subdivision scheme.
/// Returns the number of indexing tables needed to represent this particular
/// subdivision scheme.
virtual int GetNumTables() const { return 7; }
private:

View File

@ -70,10 +70,13 @@ namespace OPENSUBDIV_VERSION {
template <class T, class U> class FarMeshFactory;
// A specialized factory for FarBilinearSubdivisionTables
// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
//
/// \brief A specialized factory for FarBilinearSubdivisionTables
///
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
///
template <class T, class U> struct FarBilinearSubdivisionTablesFactory {
/// Creates a FarBilinearSubdivisiontables instance.
static FarBilinearSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
};

View File

@ -67,28 +67,31 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// Catmull-Clark tables store the indexing tables required in order to compute
// the refined positions of a mesh without the help of a hierarchical data
// structure. The advantage of this representation is its ability to be executed
// in a massively parallel environment without data dependencies.
//
/// \brief Catmark subdivision scheme tables.
///
/// Catmull-Clark tables store the indexing tables required in order to compute
/// the refined positions of a mesh without the help of a hierarchical data
/// structure. The advantage of this representation is its ability to be executed
/// in a massively parallel environment without data dependencies.
///
template <class U> class FarCatmarkSubdivisionTables : public FarSubdivisionTables<U> {
public:
// Memory required to store the indexing tables
/// Memory required to store the indexing tables
virtual int GetMemoryUsed() const;
// Compute the positions of refined vertices using the specified kernels
/// Compute the positions of refined vertices using the specified kernels
virtual void Apply( int level, void * data=0 ) const;
// Table accessors
/// Face-vertices indexing table accessor
FarTable<unsigned int> const & Get_F_IT( ) const { return _F_IT; }
/// Face-vertices indexing table accessor
FarTable<int> const & Get_F_ITa( ) const { return _F_ITa; }
// Returns the number of indexing tables needed to represent this particular
// subdivision scheme.
/// Returns the number of indexing tables needed to represent this particular
/// subdivision scheme.
virtual int GetNumTables() const { return 7; }
private:

View File

@ -70,10 +70,13 @@ namespace OPENSUBDIV_VERSION {
template <class T, class U> class FarMeshFactory;
// A specialized factory for FarCatmarkSubdivisionTables
// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
//
/// \brief A specialized factory for FarCatmarkSubdivisionTables
///
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
///
template <class T, class U> struct FarCatmarkSubdivisionTablesFactory {
/// Creates a FarCatmarkSubdivisiontables instance.
static FarCatmarkSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
};

View File

@ -68,18 +68,21 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// Compute dispatcher : allows client code to customize parts or the entire
// computation process. This pattern aims at hiding the logic specific to
// the subdivision algorithms and expose a simplified access to minimalistic
// compute kernels. By default, meshes revert to a default dispatcher that
// implements single-threaded CPU kernels.
//
// - derive a dispatcher class from this one
// - override the virtual functions
// - pass the derived dispatcher to the factory (one instance can be shared by many meshes)
// - call the FarMesh::Subdivide() to trigger computations
//
// Note : the caller is responsible for deleting a custom dispatcher
/// \brief Subdivision process encapsulation layer.
///
/// The Compute dispatcher allows client code to customize parts or the entire
/// computation process. This pattern aims at hiding the logic specific to
/// the subdivision algorithms and expose a simplified access to minimalistic
/// compute kernels. By default, meshes revert to a default dispatcher that
/// implements single-threaded CPU kernels.
///
/// - derive a dispatcher class from this one
/// - override the virtual functions
/// - pass the derived dispatcher to the factory (one instance can be shared by many meshes)
/// - call the FarMesh::Subdivide() to trigger computations
///
/// Note : the caller is responsible for deleting a custom dispatcher
///
template <class U> class FarDispatcher {
protected:

View File

@ -68,17 +68,19 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// Loop tables store the indexing tables required in order to compute
// the refined positions of a mesh without the help of a hierarchical data
// structure. The advantage of this representation is its ability to be executed
// in a massively parallel environment without data dependencies.
//
/// \brief Loop subdivision scheme tables.
///
/// Loop tables store the indexing tables required in order to compute
/// the refined positions of a mesh without the help of a hierarchical data
/// structure. The advantage of this representation is its ability to be executed
/// in a massively parallel environment without data dependencies.
///
template <class U> class FarLoopSubdivisionTables : public FarSubdivisionTables<U> {
public:
// Compute the positions of refined vertices using the specified kernels
/// Compute the positions of refined vertices using the specified kernels
virtual void Apply( int level, void * data=0 ) const;

View File

@ -70,10 +70,13 @@ namespace OPENSUBDIV_VERSION {
template <class T, class U> class FarMeshFactory;
// A specialized factory for FarLoopSubdivisionTables
// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
//
/// \brief A specialized factory for FarLoopSubdivisionTables
///
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
///
template <class T, class U> struct FarLoopSubdivisionTablesFactory {
/// Creates a FarLoopSubdivisiontables instance.
static FarLoopSubdivisionTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
};

View File

@ -69,23 +69,23 @@ namespace OPENSUBDIV_VERSION {
template <class U> class FarDispatcher;
// Core serialized subdivision mesh class.
//
// In order to support both interleaved & non-interleaved vertex access,
// classes are dual-templated : T corresponds to the Hbr vertex representation
// while U correcsponds to this library's vertex representation. In some cases,
// the actual positions of the vertices are irrelevant, so passing an "empty"
// vertex class to Hbr is perfectly acceptable and saves some data-copy steps.
/// \brief Feature Adaptive Mesh class.
///
/// FarMesh is a serialized instantiation of an HbrMesh. The HbrMesh contains
/// all the topological data in a highly interconnected data structure for
/// ease of access and modification. When instantiating a FarMesh, the factory
/// analyzes this data structure and serializes the topology into a linear
/// buffers that are ready for efficient parallel processing.
template <class U> class FarMesh {
public:
~FarMesh();
// returns the subdivision method
/// Returns the subdivision method
FarSubdivisionTables<U> const * GetSubdivision() const { return _subdivisionTables; }
// returns the compute dispatcher
/// Returns the compute dispatcher
FarDispatcher<U> const * GetDispatcher() const { return _dispatcher; }
enum PatchType {
@ -94,33 +94,33 @@ public:
k_Triangles,
};
// returns the type of patches described by the face vertices list
/// Returns the type of patches described by the face vertices list
PatchType GetPatchType() const { return _patchtype; }
// returns the list of vertices in the mesh (from subdiv level 0 to N)
/// Returns the list of vertices in the mesh (from subdiv level 0 to N)
std::vector<U> & GetVertices() { return _vertices; }
U & GetVertex(int index) { return _vertices[index]; }
// returns the list of indices of the vertices of the faces in the mesh
/// Returns the list of indices of the vertices of the faces in the mesh
std::vector<int> const & GetFaceVertices(int level) const;
// returns the ptex coordinates for each face at a given level. The coordinates
// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
/// Returns the ptex coordinates for each face at a given level. The coordinates
/// are stored as : (int) faceindex / (ushort) u_index / (ushort) v_index
std::vector<int> const & GetPtexCoordinates(int level) const;
// returns vertex edit tables
/// Returns vertex edit tables
FarVertexEditTables<U> const * GetVertexEdit() const { return _vertexEditTables; }
// returns the number of coarse vertices held at the beginning of the vertex
// buffer.
/// Returns the number of coarse vertices held at the beginning of the vertex
/// buffer.
int GetNumCoarseVertices() const;
// returns the total number of vertices in the mesh across across all depths
/// Returns the total number of vertices in the mesh across across all depths
int GetNumVertices() const { return (int)(_vertices.size()); }
// apply the subdivision tables to compute the positions of the vertices up
// to 'level'
/// Apply the subdivision tables to compute the positions of the vertices up
/// to 'level'
void Subdivide(int level=-1);
private:

View File

@ -76,12 +76,16 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// The meshFactory institutes a 2 steps process in the conversion of a mesh from
// an HbrMesh<T>. The main reason is that client code may want to have access
// to the remapping table that correlates vertices from both meshes for reasons
// of their own. This is also useful to the unit-test code which can match the
// subdivision results of both code paths for correctness.
/// \brief Instantiates a FarMesh from an HbrMesh.
///
/// FarMeshFactory requires a 2 steps process :
/// 1. Instantiate a FarMeshFactory object from an HbrMesh
/// 2. Call "Create" to obtain the FarMesh instance
///
/// This tiered factory approach offers client-code the opportunity to access
/// useful transient information tied to the lifespan of the factory instance.
/// Specifically, regression code needs to access the remapping tables that
/// tie HbrMesh vertices to their FarMesh counterparts for comparison.
template <class T, class U=T> class FarMeshFactory {
@ -93,39 +97,39 @@ public:
// object can be deleted safely.
FarMeshFactory(HbrMesh<T> * mesh, int maxlevel);
// Create a table-based mesh representation
/// Create a table-based mesh representation
FarMesh<U> * Create( FarDispatcher<U> * dispatch=0 );
// Maximum level of subidivision supported by this factory
/// Maximum level of subidivision supported by this factory
int GetMaxLevel() const { return _maxlevel; }
// Total number of face vertices up to 'level'
/// Total number of face vertices up to 'level'
int GetNumFaceVerticesTotal(int level) const {
return sumList<HbrVertex<T> *>(_faceVertsList, level);
}
// Total number of edge vertices up to 'level'
/// Total number of edge vertices up to 'level'
int GetNumEdgeVerticesTotal(int level) const {
return sumList<HbrVertex<T> *>(_edgeVertsList, level);
}
// Total number of vertex vertices up to 'level'
/// Total number of vertex vertices up to 'level'
int GetNumVertexVerticesTotal(int level) const {
return sumList<HbrVertex<T> *>(_vertVertsList, level);
}
// Valence summation up to 'level'
/// Valence summation up to 'level'
int GetNumAdjacentVertVerticesTotal(int level) const;
// Total number of faces across up to a level
/// Total number of faces across up to a level
int GetNumFacesTotal(int level) const {
return sumList<HbrFace<T> *>(_facesList, level);
}
// Return the corresponding index of the HbrVertex<T> in the new mesh
/// Return the corresponding index of the HbrVertex<T> in the new mesh
int GetVertexID( HbrVertex<T> * v );
// Returns a the mapping between HbrVertex<T>->GetID() and Far vertices indices
/// Returns a the mapping between HbrVertex<T>->GetID() and Far vertices indices
std::vector<int> const & GetRemappingTable( ) const { return _remapTable; }
private:

View File

@ -70,76 +70,85 @@ namespace OPENSUBDIV_VERSION {
template <class U> class FarMesh;
template <class U> class FarDispatcher;
// Catmull-Clark tables store the indexing tables required in order to compute
// the refined positions of a mesh without the help of a hierarchical data
// structure. The advantage of this representation is its ability to be executed
// in a massively parallel environment without data dependencies.
//
// The vertex indexing tables require the vertex buffer to be sorted based on the
// nature of the parent of a given vertex : either a face, an edge, or a vertex.
//
// [...Child of a Face...]|[... Child of an Edge ...]|[... Child of a Vertex ...]
//
// Each segment of the buffer is associated the following tables (<T> is the type):
// _<T>_IT : indices of all the adjacent vertices required by the compute kernels
// _<T>_W : fractional weight of the vertex (based on sharpness & topology)
// _<T>_ITa : codex for the two previous tables
// For more details see : "Feature Adaptive GPU Rendering of Catmull-Clark
// Subdivision Surfaces" p.3 - par. 3.2
/// \brief FarSubdivisionTables are a serialized topological data representation.
///
/// Subdivision tables store the indexing tables required in order to compute
/// the refined positions of a mesh without the help of a hierarchical data
/// structure. The advantage of this representation is its ability to be executed
/// in a massively parallel environment without data dependencies.
///
/// The vertex indexing tables require the vertex buffer to be sorted based on the
/// nature of the parent of a given vertex : either a face, an edge, or a vertex.
/// (note : the Loop subdivision scheme does not create vertices as a child of a
/// face).
///
/// Each type of vertex in the buffer is associated the following tables :
/// - _<T>_IT : indices of all the adjacent vertices required by the compute kernels
/// - _<T>_W : fractional weight of the vertex (based on sharpness & topology)
/// - _<T>_ITa : codex for the two previous tables
/// (where T denotes a face-vertex / edge-vertex / vertex-vertex)
///
///
/// Because each subdivision scheme (Catmark / Loop / Bilinear) introduces variations
/// in the subdivision rules, a derived class specialization is associated with
/// each scheme.
///
/// For more details see : "Feature Adaptive GPU Rendering of Catmull-Clark
/// Subdivision Surfaces" (p.3 - par. 3.2)
///
template <class U> class FarSubdivisionTables {
public:
// Destructor
/// Destructor
virtual ~FarSubdivisionTables<U>() {}
// Return the highest level of subdivision possible with these tables
/// Return the highest level of subdivision possible with these tables
int GetMaxLevel() const { return (int)(_vertsOffsets.size()); }
// Memory required to store the indexing tables
/// Memory required to store the indexing tables
virtual int GetMemoryUsed() const;
// Compute the positions of refined vertices using the specified kernels
/// Compute the positions of refined vertices using the specified kernels
virtual void Apply( int level, void * clientdata=0 ) const=0;
// Pointer back to the mesh owning the table
/// Pointer back to the mesh owning the table
FarMesh<U> * GetMesh() { return _mesh; }
// The index of the first vertex that belongs to the level of subdivision
// represented by this set of FarCatmarkSubdivisionTables
/// The index of the first vertex that belongs to the level of subdivision
/// represented by this set of FarCatmarkSubdivisionTables
int GetFirstVertexOffset( int level ) const;
// Number of vertices children of a face at a given level (always 0 for Loop)
/// Number of vertices children of a face at a given level (always 0 for Loop)
int GetNumFaceVertices( int level ) const;
// Number of vertices children of an edge at a given level
/// Number of vertices children of an edge at a given level
int GetNumEdgeVertices( int level ) const;
// Number of vertices children of a vertex at a given level
/// Number of vertices children of a vertex at a given level
int GetNumVertexVertices( int level ) const;
// Total number of vertices at a given level
int GetNumVertices( int level ) const;
// Indexing tables accessors
/// Indexing tables accessors
// Returns the edge vertices indexing table
/// Returns the edge vertices indexing table
FarTable<int> const & Get_E_IT() const { return _E_IT; }
// Returns the edge vertices weights table
/// Returns the edge vertices weights table
FarTable<float> const & Get_E_W() const { return _E_W; }
// Returns the vertex vertices codex table
/// Returns the vertex vertices codex table
FarTable<int> const & Get_V_ITa() const { return _V_ITa; }
// Returns the vertex vertices indexing table
/// Returns the vertex vertices indexing table
FarTable<unsigned int> const & Get_V_IT() const { return _V_IT; }
// Returns the vertex vertices weights table
/// Returns the vertex vertices weights table
FarTable<float> const & Get_V_W() const { return _V_W; }
// Returns the number of indexing tables needed to represent this particular
// subdivision scheme.
/// Returns the number of indexing tables needed to represent this particular
/// subdivision scheme.
virtual int GetNumTables() const { return 5; }
protected:

View File

@ -62,11 +62,16 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// Generic multi-level indexing table : the indices across all the subdivision
// levels are stored in a single std::vector. The table class holds a sequence
// of markers pointing to the first index at the beginning of the sequence
// describing a given level (note that "level 1" vertices are obtained by using
// the indices starting at "level 0" of the tables)
/// \brief A generic "table" with markers.
///
/// Generic multi-level indexing table : the indices across all the subdivision
/// levels are stored in a flat std::vector.
///
/// The table class also holds a sequence of markers pointing to the first index
/// at the beginning of the sequence describing a given level.
/// (note that "level 1" vertices are obtained by using the indices starting at
/// "level 0" of the tables)
///
template <typename Type> class FarTable {
std::vector<Type> _data; // table data
std::vector<Type *> _markers; // pointers to the first datum at each level
@ -76,44 +81,44 @@ public:
FarTable(int maxlevel) : _markers(maxlevel) { }
// Reset max level and clear data
/// Reset max level and clear data
void SetMaxLevel(int maxlevel) {
_data.clear();
_markers.resize(maxlevel);
}
// Returns the memory required to store the data in this table.
/// Returns the memory required to store the data in this table.
int GetMemoryUsed() const {
return (int)_data.size() * sizeof(Type);
}
// Returns the number of elements in level "level"
/// Returns the number of elements in level "level"
int GetNumElements(int level) const {
assert(level>=0 and level<((int)_markers.size()-1));
return (int)(_markers[level+1] - _markers[level]);
}
// Saves a pointer indicating the beginning of data pertaining to "level"
// of subdivision
/// Saves a pointer indicating the beginning of data pertaining to "level"
/// of subdivision
void SetMarker(int level, Type * marker) {
_markers[level] = marker;
}
// Resize the table to size (also resets markers)
/// Resize the table to size (also resets markers)
void Resize(int size) {
_data.resize(size);
_markers[0] = &_data[0];
}
// Returns a pointer to the data at the beginning of level "level" of
// subdivision
/// Returns a pointer to the data at the beginning of level "level" of
/// subdivision
Type * operator[](int level) {
assert(level>=0 and level<(int)_markers.size());
return _markers[level];
}
// Returns a const pointer to the data at the beginning of level "level"
// of subdivision
/// Returns a const pointer to the data at the beginning of level "level"
/// of subdivision
const Type * operator[](int level) const {
return const_cast<FarTable *>(this)->operator[](level);
}

View File

@ -71,25 +71,32 @@ namespace OPENSUBDIV_VERSION {
template <class U> class FarMesh;
template <class U> class FarDispatcher;
/// \brief A serialized container for hierarchical edits.
///
/// Some of the hierarchical edits are resolved into the vertex weights computed
/// into the FarSubdivision tables. Certain edits however have to be "post-processed"
/// after the tables are applied to the vertices and require their HBR representation
/// to be serialized into a specific container.
///
class FarVertexEdit {
public:
// Type of edit operation - equivalent to HbrHiearachicalEdit<T>::Operation
/// Type of edit operation - equivalent to HbrHiearachicalEdit<T>::Operation
enum Operation {
Set,
Add
// Note : subtract edits are converted to Add edits for better serialization
/// Note : subtract edits are converted to Add edits for better serialization
};
// Get the type of operation
/// Get the type of operation
Operation GetOperation() const { return _op; }
// Return index of variable this edit applies to
/// Return index of variable this edit applies to
int GetIndex() const { return _index; }
// Return width of the variable
/// Return width of the variable
int GetWidth() const { return _width; }
// Get the numerical value of the edit
/// Get the numerical value of the edit
const float* GetEdit() const { return _edit; }
private:

View File

@ -69,13 +69,16 @@
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
// A specialized factory for FarVertexEditTables
// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
//
/// \brief A specialized factory for FarVertexEditTables
///
/// Separating the factory allows us to isolate Far data structures from Hbr dependencies.
///
template <class T, class U> struct FarVertexEditTablesFactory {
/// Compares the number of subfaces in an edit (for sorting purposes)
static bool compareEdits(HbrVertexEdit<T> const *a, HbrVertexEdit<T> const *b);
/// Creates a FarVertexEditTables instance.
static FarVertexEditTables<U> * Create( FarMeshFactory<T,U> const * factory, FarMesh<U> * mesh, int maxlevel );
};