1 //
2 //   Copyright 2013 Pixar
3 //
4 //   Licensed under the Apache License, Version 2.0 (the "Apache License")
5 //   with the following modification; you may not use this file except in
6 //   compliance with the Apache License and the following modification to it:
7 //   Section 6. Trademarks. is deleted and replaced with:
8 //
9 //   6. Trademarks. This License does not grant permission to use the trade
10 //      names, trademarks, service marks, or product names of the Licensor
11 //      and its affiliates, except as required to comply with Section 4(c) of
12 //      the License and to reproduce the content of the NOTICE file.
13 //
14 //   You may obtain a copy of the Apache License at
15 //
16 //       http://www.apache.org/licenses/LICENSE-2.0
17 //
18 //   Unless required by applicable law or agreed to in writing, software
19 //   distributed under the Apache License with the above modification is
20 //   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 //   KIND, either express or implied. See the Apache License for the specific
22 //   language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H
26 #define OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H
27 
28 #include "../version.h"
29 
30 #include "../far/topologyRefiner.h"
31 #include "../far/patchTable.h"
32 
33 namespace OpenSubdiv {
34 namespace OPENSUBDIV_VERSION {
35 
36 namespace Far {
37 
38 /// \brief Factory for constructing a PatchTable from a TopologyRefiner
39 ///
40 class PatchTableFactory {
41 public:
42 
43     /// \brief Public options for the PatchTable factory
44     ///
45     struct Options {
46 
47         /// \brief Choice for approximating irregular patches (end-caps)
48         ///
49         /// This enum specifies how irregular patches (end-caps) are approximated.
50         /// A basis is chosen, rather than a specific patch type, and has a
51         /// corresponding patch type for each subdivision scheme, i.e. a quad and
52         /// triangular patch type exists for each basis.  These choices provide a
53         /// trade-off between surface quality and performance.
54         ///
55         enum EndCapType {
56             ENDCAP_NONE = 0,        ///< unspecified
57             ENDCAP_BILINEAR_BASIS,  ///< use linear patches (simple quads or tris)
58             ENDCAP_BSPLINE_BASIS,   ///< use BSpline-like patches (same patch type as regular)
59             ENDCAP_GREGORY_BASIS,   ///< use Gregory patches (highest quality, recommended default)
60             ENDCAP_LEGACY_GREGORY   ///< legacy option for 2.x style Gregory patches (Catmark only)
61         };
62 
63         Options(unsigned int maxIsolation=10) :
generateAllLevelsOptions64              generateAllLevels(false),
65              includeBaseLevelIndices(true),
66              includeFVarBaseLevelIndices(false),
67              triangulateQuads(false),
68              useSingleCreasePatch(false),
69              useInfSharpPatch(false),
70              maxIsolationLevel(maxIsolation),
71              endCapType(ENDCAP_GREGORY_BASIS),
72              shareEndCapPatchPoints(true),
73              generateVaryingTables(true),
74              generateVaryingLocalPoints(true),
75              generateFVarTables(false),
76              patchPrecisionDouble(false),
77              fvarPatchPrecisionDouble(false),
78              generateFVarLegacyLinearPatches(true),
79              generateLegacySharpCornerPatches(true),
80              numFVarChannels(-1),
81              fvarChannelIndices(0)
82         { }
83 
84         /// \brief Get endcap basis type
GetEndCapTypeOptions85         EndCapType GetEndCapType() const { return (EndCapType)endCapType; }
86 
87         /// \brief Set endcap basis type
SetEndCapTypeOptions88         void SetEndCapType(EndCapType e) { endCapType = e; }
89 
90         /// \brief Set precision of vertex patches
91         template <typename REAL> void SetPatchPrecision();
92 
93         /// \brief Set precision of face-varying patches
94         template <typename REAL> void SetFVarPatchPrecision();
95 
96         /// \brief Determine adaptive refinement options to match assigned patch options
GetRefineAdaptiveOptionsOptions97         TopologyRefiner::AdaptiveOptions GetRefineAdaptiveOptions() const {
98             TopologyRefiner::AdaptiveOptions adaptiveOptions(maxIsolationLevel);
99 
100             adaptiveOptions.useInfSharpPatch     = useInfSharpPatch;
101             adaptiveOptions.useSingleCreasePatch = useSingleCreasePatch;
102             adaptiveOptions.considerFVarChannels = generateFVarTables &&
103                                                   !generateFVarLegacyLinearPatches;
104             return adaptiveOptions;
105         }
106 
107         unsigned int generateAllLevels           : 1, ///< Generate levels from 'firstLevel' to 'maxLevel' (Uniform mode only)
108                      includeBaseLevelIndices     : 1, ///< Include base level in patch point indices (Uniform mode only)
109                      includeFVarBaseLevelIndices : 1, ///< Include base level in face-varying patch point indices (Uniform mode only)
110                      triangulateQuads            : 1, ///< Triangulate 'QUADS' primitives (Uniform mode only)
111 
112                      useSingleCreasePatch : 1, ///< Use single crease patch
113                      useInfSharpPatch     : 1, ///< Use infinitely-sharp patch
114                      maxIsolationLevel    : 4, ///< Cap adaptive feature isolation to the given level (max. 10)
115 
116                      // end-capping
117                      endCapType              : 3, ///< EndCapType
118                      shareEndCapPatchPoints  : 1, ///< Share endcap patch points among adjacent endcap patches.
119                                                   ///< currently only work with GregoryBasis.
120 
121                      // varying
122                      generateVaryingTables      : 1, ///< Generate varying patch tables
123                      generateVaryingLocalPoints : 1, ///< Generate local points with varying patches
124 
125                      // face-varying
126                      generateFVarTables  : 1, ///< Generate face-varying patch tables
127 
128                      // precision
129                      patchPrecisionDouble     : 1, ///< Generate double-precision stencils for vertex patches
130                      fvarPatchPrecisionDouble : 1, ///< Generate double-precision stencils for face-varying patches
131 
132                      // legacy behaviors (default to true)
133                      generateFVarLegacyLinearPatches  : 1, ///< Generate all linear face-varying patches (legacy)
134                      generateLegacySharpCornerPatches : 1; ///< Generate sharp regular patches at smooth corners (legacy)
135 
136         int          numFVarChannels;          ///< Number of channel indices and interpolation modes passed
137         int const *  fvarChannelIndices;       ///< List containing the indices of the channels selected for the factory
138     };
139 
140     /// \brief Instantiates a PatchTable from a client-provided TopologyRefiner.
141     ///
142     ///  A PatchTable can be constructed from a TopologyRefiner that has been
143     ///  either adaptively or uniformly refined.  In both cases, the resulting
144     ///  patches reference vertices in the various refined levels by index,
145     ///  and those indices accumulate with the levels in different ways.
146     ///
147     ///  For adaptively refined patches, patches are defined at different levels,
148     ///  including the base level, so the indices of patch vertices include
149     ///  vertices from all levels.  A sparse set of patches can be created by
150     ///  restricting the patches generated to those descending from a given set
151     ///  of faces at the base level.  This sparse set of base faces is expected
152     ///  to be a subset of the faces that were adaptively refined in the given
153     ///  TopologyRefiner, otherwise results are undefined.
154     ///
155     ///  For uniformly refined patches, all patches are completely defined within
156     ///  the last level.  There is often no use for intermediate levels and they
157     ///  can usually be ignored.  Indices of patch vertices might therefore be
158     ///  expected to be defined solely within the last level.  While this is true
159     ///  for face-varying patches, for historical reasons it is not the case for
160     ///  vertex and varying patches.  Indices for vertex and varying patches include
161     ///  the base level in addition to the last level while indices for face-varying
162     ///  patches include only the last level.
163     ///
164     /// @param refiner        TopologyRefiner from which to generate patches
165     ///
166     /// @param options        Options controlling the creation of the table
167     ///
168     /// @param selectedFaces  Only create patches for the given set of base faces.
169     ///
170     /// @return               A new instance of PatchTable
171     ///
172     static PatchTable * Create(TopologyRefiner const & refiner,
173                                Options options = Options(),
174                                ConstIndexArray selectedFaces = ConstIndexArray());
175 
176 public:
177     //  PatchFaceTag
178     //
179     //  This simple struct was previously used within the factory to take inventory of
180     //  various kinds of patches to fully allocate buffers prior to populating them.  It
181     //  was not intended to be exposed as part of the public interface.
182     //
183     //  It is no longer used internally and is being kept here to respect preservation
184     //  of the public interface, but it will be deprecated at the earliest opportunity.
185     //
186     /// \brief Obsolete internal struct not intended for public use -- due to
187     /// be deprecated.
188     //
189     struct PatchFaceTag {
190     public:
191         unsigned int   _hasPatch        : 1;
192         unsigned int   _isRegular       : 1;
193         unsigned int   _transitionMask  : 4;
194         unsigned int   _boundaryMask    : 4;
195         unsigned int   _boundaryIndex   : 2;
196         unsigned int   _boundaryCount   : 3;
197         unsigned int   _hasBoundaryEdge : 3;
198         unsigned int   _isSingleCrease  : 1;
199 
200         void clear();
201         void assignBoundaryPropertiesFromEdgeMask(int boundaryEdgeMask);
202         void assignBoundaryPropertiesFromVertexMask(int boundaryVertexMask);
203         void assignTransitionPropertiesFromEdgeMask(int boundaryVertexMask);
204     };
205     typedef std::vector<PatchFaceTag> PatchTagVector;
206 };
207 
208 
209 template <> inline void PatchTableFactory::Options::SetPatchPrecision<float>() {
210     patchPrecisionDouble = false;
211 }
212 template <> inline void PatchTableFactory::Options::SetFVarPatchPrecision<float>() {
213     fvarPatchPrecisionDouble = false;
214 }
215 
216 template <> inline void PatchTableFactory::Options::SetPatchPrecision<double>() {
217     patchPrecisionDouble = true;
218 }
219 template <> inline void PatchTableFactory::Options::SetFVarPatchPrecision<double>() {
220     fvarPatchPrecisionDouble = true;
221 }
222 
223 
224 } // end namespace Far
225 
226 } // end namespace OPENSUBDIV_VERSION
227 using namespace OPENSUBDIV_VERSION;
228 
229 } // end namespace OpenSubdiv
230 
231 
232 #endif /* OPENSUBDIV3_FAR_PATCH_TABLE_FACTORY_H */
233