mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-12 23:20:10 +00:00
Merge pull request #663 from c64kernal/dev_doxfar
Simplifying Porting Guide
This commit is contained in:
commit
fc45b4c79b
@ -140,16 +140,32 @@ situations where mesh data is not defined in a boundary representation, a
|
||||
simple container for raw mesh data is provided (TopologyDescriptor) along
|
||||
with a Factory specialized to construct TopologyRefiners from it.
|
||||
|
||||
So there are two ways to create TopologyRefiners:
|
||||
There are three ways to create TopologyRefiners:
|
||||
|
||||
* use the existing TopologyRefinerFactory<TopologyDescriptor> with a
|
||||
populated instance of TopologyDescriptor
|
||||
* specialize TopologyRefinerFactory<class MESH> for more efficient
|
||||
conversion, using only face-vertex information
|
||||
* fully specialize TopologyRefinerFactor<class MESH> for most control over
|
||||
conversion
|
||||
|
||||
TopologyDescriptor is a simple struct with pointers to raw mesh data in a
|
||||
form common to mesh constructors. Topologically, the minimal requirement
|
||||
consists of:
|
||||
These approaches are detailed below:
|
||||
|
||||
Factories to Build Far::TopologyRefiners
|
||||
****************************************
|
||||
|
||||
Here we outline the three approaches for converting mesh topology into the
|
||||
required Far::TopologyRefiner. Additional documentation is provided with
|
||||
the Far::TopologyRefinerFactory<MESH> class template used by all, and each
|
||||
has a concrete example provided in one of the tutorials or in the Far code
|
||||
itself.
|
||||
|
||||
**Use the Far::TopologyDescriptor**
|
||||
|
||||
Far::TopologyDescriptor is a simple struct that can be initialized to refer
|
||||
to raw mesh topology information -- primarily a face-vertex list -- and then
|
||||
passed to a provided factory class to create a TopologyRefiner from each.
|
||||
Topologically, the minimal requirement consists of:
|
||||
|
||||
* the number of vertices and faces of the mesh
|
||||
* an array containing the number of vertices per face
|
||||
@ -161,34 +177,90 @@ Additional members are available to assign sharpness values per edge and/or
|
||||
vertex, hole tags to faces, or to define multiple sets (channels) of
|
||||
face-varying data.
|
||||
|
||||
Almost all of the Far tutorials (i.e. tutorials/far/tutorial_*) illustrate
|
||||
use of the TopologyDescriptor and its factory for creating TopologyRefiners,
|
||||
i.e. TopologyRefinerFactory<TopologyDescriptor>.
|
||||
|
||||
For situations when users have raw mesh data and have not yet constructed a
|
||||
boundary representation of their own, it is hoped that this will suffice.
|
||||
Options have even been provided to indicate that raw topology information
|
||||
has been defined in a left-hand winding order and the factory will handle
|
||||
the conversion to right-hand (counter-clockwise) winding on-the-fly to avoid
|
||||
unnecessary data duplication.
|
||||
|
||||
**Custom Factory for Face Vertices**
|
||||
|
||||
If the nature of the TopologyDescriptor's data expectations is not helpful,
|
||||
and so conversion to large temporary arrays would be necessary to properly
|
||||
make use of it, it may be worth writing a custom factory.
|
||||
|
||||
Specialization of TopologyRefinerFactory<class MESH> should be done with care
|
||||
as the goal here is to maximize the performance of the conversion and so
|
||||
minimize overhead due to runtime validation. The template provides the
|
||||
high-level construction of the required topology vectors of the underlying
|
||||
Vtr. It requires the specification/specialization of two methods with the
|
||||
following purpose:
|
||||
Vtr.
|
||||
|
||||
There are two ways to write such a factory: provide only the face-vertex
|
||||
information for topology and let the factory infer all edges and other
|
||||
relationships, or provide the complete edge list and all other topological
|
||||
relationships directly. The latter is considerably more involved and
|
||||
described in a following section.
|
||||
|
||||
The definition of TopologyRefinerFactory<TopologyDescriptor> provides a clear
|
||||
and complete example of constructing a TopologyRefiner with minimal topology
|
||||
information, i.e. the face-vertex list. The class template
|
||||
TopologyRefinerFactory<MESH> documents the needs here and the
|
||||
TopologyDescriptor instantiation and specialization should illustrate that.
|
||||
|
||||
|
||||
**Custom Factory for Direct Conversion**
|
||||
|
||||
Fully specializing a factory for direct conversion is needed only for
|
||||
those requiring ultimate control and is not generally recommended.
|
||||
It is recommended that one of the previous two methods initially be used to
|
||||
convert your mesh topology into a TopologyRefiner. If the conversion
|
||||
performance is critical, or significant enough to warrant improvement, then
|
||||
it is worth writing a factory for full topological conversion.
|
||||
|
||||
Writing a custom factory requires the specification/specialization of two
|
||||
methods with the following purpose:
|
||||
|
||||
* specify the sizes of topological data so that vectors can be pre-allocated
|
||||
* assign the topological data to the newly allocated vectors
|
||||
|
||||
As noted above, the assumption here is that the client's boundary-rep knows best
|
||||
how to retrieve the data that we require most efficiently. After the factory class
|
||||
gathers sizing information and allocates appropriate memory, the factory provides
|
||||
the client with locations of the appropriate tables to be populated (using the
|
||||
same `Array <vtr_overview.html#arry-type>`__ classes and interface used to access
|
||||
the tables). The client is expected to load a complete topological description
|
||||
along with additional optional data, i.e.:
|
||||
As noted above, the assumption here is that the client's boundary-rep knows
|
||||
best how to retrieve the data that we require most efficiently. After the
|
||||
factory class gathers sizing information and allocates appropriate memory, the
|
||||
factory provides the client with locations of the appropriate tables to be
|
||||
populated (using the same `Array <vtr_overview.html#arry-type>`__ classes and
|
||||
interface used to access the tables). The client is expected to load a
|
||||
complete topological description along with additional optional data, i.e.:
|
||||
|
||||
* the six topological relations required by Vtr, oriented when manifold
|
||||
* sharpness values for edges and/or vertices (optional)
|
||||
* additional tags related to the components, e.g. holes (optional)
|
||||
* values-per-face for face-varying channels (optional)
|
||||
|
||||
This approach requires dealing directly with edges, unlike the other two. In
|
||||
order to convert edges into a TopologyRefiner's representation, the edges need
|
||||
to be expressed as a collection of known size N -- each of which is referred to
|
||||
directly by indices [0,N-1]. This can be awkward for representations such as
|
||||
half-edge or quad-edge that do not treat the instance of an edge uniquely.
|
||||
|
||||
Particular care is also necessary when representing non-manifold features. The
|
||||
previous two approaches will construct non-manifold features as required from
|
||||
the face-vertex list -- dealing with degenerate edges and other non-manifold
|
||||
features as encountered. When directly translating full topology it is
|
||||
necessary to tag non-manifold features, and also to ensure that certain
|
||||
edge relationships are satisfied in their presence. More details are
|
||||
available with the assembly methods of the factory class template.
|
||||
|
||||
While there is plenty of opportunity for user error here, that is no different
|
||||
from any other conversion process. Given that Far controls the construction
|
||||
process through the Factory class, we do have ample opportunity to insert
|
||||
runtime validation, and to vary that level of validation at any time on an
|
||||
instance of the Factory.
|
||||
instance of the Factory. The factory does provide run-time validation on the
|
||||
topology constructed that can be used for debugging purposes.
|
||||
|
||||
A common base class has been created for the factory class, i.e.:
|
||||
|
||||
|
@ -68,6 +68,7 @@
|
||||
<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-topologyrefinerfactory">Topology Refiner Factory</a></li>
|
||||
<li><a href="far_overview.html#far-primvarrefiner">Primvar Refiner</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>
|
||||
|
@ -28,6 +28,10 @@ Porting Guide: 2.x to 3.0
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
|
||||
Porting Guide: 2.x to 3.0
|
||||
=========================
|
||||
|
||||
This document is a high-level description of how to port exiting OpenSubdiv 2.x
|
||||
code to use OpenSubdiv 3.0.
|
||||
|
||||
@ -39,7 +43,7 @@ Source Code Organization
|
||||
========================
|
||||
|
||||
Given the scale of functional changes that were being made to the public
|
||||
interface, we took the oppoortunity in 3.0 to update the coding style and
|
||||
interface, we took the opportunity in 3.0 to update the coding style and
|
||||
organization -- most notably making use of namespaces for each library.
|
||||
|
||||
================= ==================== ===============================================
|
||||
@ -56,9 +60,8 @@ osd/ Osd Revised, similar functionality with new A
|
||||
Hbr Layer Translation
|
||||
=====================
|
||||
|
||||
With HbrMesh having been the source of a number of functional and performance
|
||||
issues, client mesh topology is now translated into an instance of the new
|
||||
TopologyRefiner class in the Far level.
|
||||
Client mesh topology is now translated into an instance of Far::TopologyRefiner
|
||||
instead of HbrMesh.
|
||||
|
||||
================= ====================
|
||||
OpenSubdiv 2.x OpenSubdiv 3.0
|
||||
@ -81,13 +84,11 @@ directly into the TopologyRefiners representation. While this is now possible,
|
||||
this also represents the most complex construction process and is only
|
||||
recommended for usage where this conversion process is critical.
|
||||
|
||||
There are three ways to construct a TopologyRefiner -- ranging from the very
|
||||
simple but less optimal to the more complex just noted. The first involves
|
||||
use of a predefined factory class provided in Far, while the others require
|
||||
writing custom factories, i.e. Far::TopologyRefinerFactory<MESH>. These are
|
||||
typically stateless factories with a static Create() method that will be used
|
||||
to instantiate a new TopologyRefiner. All three are illustrated in either
|
||||
tutorials or examples as noted in the subsections that follow.
|
||||
Details on how to construct a TopologyRefiner can be found in the
|
||||
`Far overview <far_overview.html#far-topologyrefinerfactory>`__ documentation.
|
||||
Additionally, documentation for Far::TopologyRefinerFactory<MESH> outlines the
|
||||
requirements and a Far tutorial (tutorials/far/tutorial_1) provides an example
|
||||
of a factory for directly converting HbrMeshes to TopologyRefiners.
|
||||
|
||||
Its worth a reminder here that Far::TopologyRefiner contains only topological
|
||||
information (which does include sharpness, since that is considered relating
|
||||
@ -100,11 +101,10 @@ data specification at all.
|
||||
Subdivision Schemes and Options in Sdc
|
||||
++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Before detailing the topology conversion, since the creation of a new
|
||||
TopologyRefiner requires specification of a subdivision scheme and a set of
|
||||
options that are applicable to all schemes. With HbrMesh, the scheme was
|
||||
specified by declaring a static instance of a specific subclass of a
|
||||
subdivision object, while the options were specified with a number of
|
||||
The creation of a new TopologyRefiner requires specification of a subdivision
|
||||
scheme and a set of options that are applicable to all schemes. With HbrMesh,
|
||||
the scheme was specified by declaring a static instance of a specific subclass
|
||||
of a subdivision object, and the options were specified with a number of
|
||||
methods on the different classes.
|
||||
|
||||
Such general information about the schemes has now been encapsulated in the
|
||||
@ -121,85 +121,6 @@ HbrMesh<T>::SetFVarInterpolateBoundaryMethod() Sdc::Options::SetFVarLinearInte
|
||||
HbrSubdivision<T>::SetCreaseSubdivisionMethod() Sdc::Options::SetCreasingMethod()
|
||||
=============================================== ===========================================
|
||||
|
||||
Regardless of the three construction choices outlined below, the specification
|
||||
of both the scheme and all options related to it is the same.
|
||||
|
||||
Factories to Build Far::TopologyRefiners
|
||||
++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Here we outline the three approaches for converting mesh topology into the
|
||||
required Far::TopologyRefiner. Additional documentation is provided with
|
||||
the Far::TopologyRefinerFactory<MESH> class template used by all, and each
|
||||
has a concrete example provided in one of the tutorials or in the Far code
|
||||
itself. Please contact the OpenSubdiv forum if questions are not answered
|
||||
here or in the other documentation and examples cited.
|
||||
|
||||
**Use the Far::TopologyDescriptor**
|
||||
|
||||
Far::TopologyDescriptor is a simple struct that can be initialized to refer
|
||||
to raw mesh topology information -- primarily a face-vertex list -- and then
|
||||
passed to a provided factory class to create a TopologyRefiner from each.
|
||||
The minimum information required is typical of what many mesh construction
|
||||
tools require: the number of vertices and faces, the number of vertices per
|
||||
face, and the complete set of face-vertices for all faces.
|
||||
|
||||
Almost all of the Far tutorials (i.e. tutorials/far/tutorial_*) illustrate
|
||||
use of the TopologyDescriptor and its factory for creating TopologyRefiners,
|
||||
i.e. TopologyRefinerFactory<TopologyDescriptor>.
|
||||
|
||||
For situations when users have raw mesh data and have not yet constructed a
|
||||
boundary representation of their own, it is hoped that this will suffice.
|
||||
Options have even been provided to indicate that raw topology information
|
||||
has been defined in a left-hand winding order and the factory will handle
|
||||
the conversion to right-hand (counter-clockwise) winding on-the-fly to avoid
|
||||
unnecessary data duplication.
|
||||
|
||||
**Custom Factory for Face Vertices**
|
||||
|
||||
If the nature of the TopologyDescriptor's data expectations is not helpful,
|
||||
and so conversion to large temporary arrays would be necessary to properly
|
||||
make use of it, it may be worth writing a custom factory.
|
||||
|
||||
There are two ways to write such a factory: provide only the face-vertex
|
||||
information for topology and let the factory infer all edges and other
|
||||
relationships, or provide the complete edge list and all other topological
|
||||
relationships directly. The latter is considerably more involved and
|
||||
described in a following section.
|
||||
|
||||
The definition of TopologyRefinerFactory<TopologyDescriptor> provides a clear
|
||||
and complete example of constructing a TopologyRefiner with minimal topology
|
||||
information, i.e. the face-vertex list. The class template
|
||||
TopologyRefinerFactory<MESH> documents the needs here and the
|
||||
TopologyDescriptor instantiation and specialization should illustrate that.
|
||||
|
||||
**Custom Factory for Direct Conversion**
|
||||
|
||||
This is not recommended as an introduction to 3.0. It is recommended that
|
||||
one of the previous two methods initially be used to convert your mesh
|
||||
topology into a TopologyRefiner and get other aspects of 3.0 working first.
|
||||
If the conversion performance is critical, or significant enough to warrant
|
||||
improvement, then its worth writing a factory for full topological conversion.
|
||||
|
||||
Documentation for Far::TopologyRefinerFactory<MESH> outlines the requirements
|
||||
and a Far tutorial (tutorials/far/tutorial_1) provides an example of a factory
|
||||
for directly converting HbrMeshes to TopologyRefiners.
|
||||
|
||||
This approach requires dealing directly with edges, unlike the other two. In
|
||||
order to convert edges into a TopologyRefiner's representation, the edges need
|
||||
to be expressed as a collection of known size N -- each of which is referred to
|
||||
directly by indices [0,N-1]. This can be awkward for representations such as
|
||||
half-edge or quad-edge that do not treat the instance of an edge uniquely.
|
||||
|
||||
Particular care is also necessary when representing non-manifold features. The
|
||||
previous two approaches will construct non-manifold features as required from
|
||||
the face-vertex list -- dealing with degenerate edges and other non-manifold
|
||||
features as encountered. When directly translating full topology it is
|
||||
necessary to tag non-manifold features, and also to ensure that certain
|
||||
edge relationships are satisfied in their presence. More details are
|
||||
available with the assembly methods of the factory class template.
|
||||
|
||||
The factory does provide run-time validation on the topology constructed that
|
||||
can be used for debugging purposes.
|
||||
|
||||
Specifying Face Varying Topology and Options
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
@ -249,7 +170,7 @@ The FarMesh was previously responsible for refining an HbrMesh -- generating
|
||||
new vertices and faces in successive levels of refinement in the
|
||||
FarSubdivisionTables. Vertices were grouped and reordered from the native
|
||||
ordering of HbrMesh so that vertices requiring similar processing were
|
||||
consecutive. Such grouping alleviated most of the idiosyncracies of
|
||||
consecutive. Such grouping alleviated most of the idiosyncrasies of
|
||||
HbrMesh's native ordering but not all.
|
||||
|
||||
Far::ToplogyRefiner is inherently a collection of refinement levels, and
|
||||
@ -265,7 +186,7 @@ still grouped for the same reasons. There are two issues here though:
|
||||
Vertices in a refined level are grouped according the type of component in
|
||||
the parent level from which they originated, i.e. some vertices originate
|
||||
from the center of a face (face-vertices), some from an edge (edge-vertices)
|
||||
and some from a vertex (vertex-vertices). (Note that there is a confict in
|
||||
and some from a vertex (vertex-vertices). (Note that there is a conflict in
|
||||
terminology here -- face-vertices and edge-vertices most often refer to
|
||||
vertices incident a face or edge -- but for the sake of this discussion, we
|
||||
use them to refer to the component from which a child vertex originates.)
|
||||
@ -297,7 +218,7 @@ first as it depended on the order in which HbrMesh traversed the parent faces
|
||||
and generated them, and given one face, HbrMesh would often visit neighboring
|
||||
faces first before moving to the next intended face.
|
||||
|
||||
The ordering with Far::TopologyRefiner is much clearer and predictible. Using
|
||||
The ordering with Far::TopologyRefiner is much clearer and predictable. Using
|
||||
the face-vertices as an example, the order of the face-vertices in level *N+1*
|
||||
is identical to the order of the parent faces in level *N* from which they
|
||||
originated. So if we have face-vertices *V'i*, *V'j* and *V'k* at some level,
|
||||
|
Loading…
Reference in New Issue
Block a user