meshGeneratorBase.h
1 //
2 // Copyright 2022 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 #ifndef PXR_IMAGING_GEOM_UTIL_MESH_GENERATOR_BASE_H
25 #define PXR_IMAGING_GEOM_UTIL_MESH_GENERATOR_BASE_H
26 
27 #include "pxr/imaging/geomUtil/api.h"
28 
29 #include "pxr/base/gf/matrix4d.h"
30 #include "pxr/base/gf/vec3d.h"
31 #include "pxr/base/gf/vec3f.h"
32 
33 #include "pxr/pxr.h"
34 
35 #include <iterator>
36 #include <type_traits>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
40 class PxOsdMeshTopology;
41 
78 {
79 private:
80 
81  // Delete the implicit default c'tor. This class and its subclasses are
82  // only for grouping; there's never any need to make instances.
83  GeomUtilMeshGeneratorBase() = delete;
84 
85 protected:
86 
87  // SFINAE helper types, for more compact and readable template shenanigans
88  // in the subclasses.
89  template<typename IterType>
90  struct _IsGfVec3Iterator
91  {
92  using PointType = typename std::iterator_traits<IterType>::value_type;
93  static constexpr bool value =
94  std::is_same<PointType, GfVec3f>::value ||
95  std::is_same<PointType, GfVec3d>::value;
96  };
97 
98  template<typename IterType>
99  struct _EnableIfGfVec3Iterator
100  : public std::enable_if<_IsGfVec3Iterator<IterType>::value, void>
101  {};
102 
103  template<typename IterType>
104  struct _EnableIfNotGfVec3Iterator
105  : public std::enable_if<!_IsGfVec3Iterator<IterType>::value, void>
106  {};
107 
108  // Helper struct to provide iterator type erasure, allowing subclasses to
109  // implement their GeneratePoints methods privately. Usage doesn't require
110  // any heap allocation or virtual dispatch/runtime typing. In addition to
111  // erasing the iterator type, this also provides a convenient way to allow
112  // subclasses to offer GeneratePoints methods that can apply an additional
113  // frame transform without having to actually plumb that detail into the
114  // guts of their point generator code.
115  //
116  // Note: Ensuring the interoperability of the PointType with the IterType
117  // used at construction is the responsibility of the client. It's typically
118  // guaranteed by the client deriving PointType from IterType; see subclass
119  // use for examples and how they guarantee IterType dereferences to a
120  // supportable point type.
121  template<typename PointType>
122  struct _PointWriter
123  {
124  template<class IterType>
125  _PointWriter(
126  IterType& iter)
127  : _writeFnPtr(&_PointWriter<PointType>::_WritePoint<IterType>)
128  , _untypedIterPtr(static_cast<void*>(&iter))
129  {}
130 
131  template<class IterType>
132  _PointWriter(
133  IterType& iter,
134  const GfMatrix4d* const framePtr)
135  : _writeFnPtr(
136  &_PointWriter<PointType>::_TransformAndWritePoint<IterType>)
137  , _untypedIterPtr(static_cast<void*>(&iter))
138  , _framePtr(framePtr)
139  {}
140 
141  void Write(
142  const PointType& pt) const
143  {
144  (this->*_writeFnPtr)(pt);
145  }
146 
147  private:
148  template<class IterType>
149  void _WritePoint(
150  const PointType& pt) const
151  {
152  IterType& iter = *static_cast<IterType*>(_untypedIterPtr);
153  *iter = pt;
154  ++iter;
155  }
156 
157  template<class IterType>
158  void _TransformAndWritePoint(
159  const PointType& pt) const
160  {
161  IterType& iter = *static_cast<IterType*>(_untypedIterPtr);
162  *iter = _framePtr->Transform(pt);
163  ++iter;
164  }
165 
166  using _WriteFnPtr =
167  void (_PointWriter<PointType>::*)(const PointType &) const;
168  _WriteFnPtr _writeFnPtr;
169  void* _untypedIterPtr;
170  const GfMatrix4d* _framePtr;
171  };
172 
173  // Common topology helper method.
174  //
175  // Several of the subclasses make use of a common topology, specifically "a
176  // triangle fan around a 'bottom' point, some number of quad strips forming
177  // rings with shared edges, and another triangle fan surrounding a 'top'
178  // point." The two triangle fans can be considered "caps" on a "tube" of
179  // linked quad strips. This triangle fans + quad strips topology also
180  // describes the latitude/longitude topology of the globe, as another
181  // example.
182  //
183  // Because we currently rely on downstream machinery to infer surface
184  // normals from the topology, we sometimes want the "caps" to share their
185  // edge-ring with the adjacent quad strip, and other times need that edge-
186  // ring to not be shared between the "cap" and "body" surfaces. The edges
187  // are coincident in space but the surface is not continuous across that
188  // edge.
189  //
190  // Subclasses specify the "cap" conditions they require to support the
191  // surface-continuity condition described above, and other uses where a
192  // "cap" is not needed (e.g. the point-end of a cone).
193  //
194  // Subclasses also specify whether the surface is closed or open. This
195  // is typically exposed via a sweep parameter, wherein a sweep of a multiple
196  // of 2 * pi results in a "closed" surface. The generated points and by
197  // extension, the generated topology, differs for "open" and "closed"
198  // surfaces.
199  //
200  enum _CapStyle {
201  CapStyleNone,
202  CapStyleSharedEdge,
203  CapStyleSeparateEdge
204  };
205 
206  static PxOsdMeshTopology _GenerateCappedQuadTopology(
207  const size_t numRadial,
208  const size_t numQuadStrips,
209  const _CapStyle bottomCapStyle,
210  const _CapStyle topCapStyle,
211  const bool closedSweep);
212 
213 
214  // Subclasses that use the topology helper method above generate one or more
215  // circular arcs during point generation. The number of radial points on
216  // each arc depends on the number of radial segments and whether the arc
217  // is fully swept (i.e., a ring).
218  static size_t _ComputeNumRadialPoints(
219  const size_t numRadial,
220  const bool closedSweep);
221 
222 public:
223 
224  // This template provides a "fallback" for GeneratePoints(...) calls that
225  // do not meet the SFINAE requirement that the given point-container-
226  // iterator must dereference to a GfVec3f or GfVec3d. This version
227  // generates a helpful compile time assertion in such a scenario. As noted
228  // earlier, subclasses should explicitly add a "using" statement with
229  // this method to include it in overload resolution.
230  //
231  template<typename PointIterType,
232  typename Enabled =
233  typename _EnableIfNotGfVec3Iterator<PointIterType>::type>
234  static void GeneratePoints(
235  PointIterType iter, ...)
236  {
237  static_assert(_IsGfVec3Iterator<PointIterType>::value,
238  "This function only supports iterators to GfVec3f or GfVec3d "
239  "objects.");
240  }
241 
242 };
243 
244 
245 PXR_NAMESPACE_CLOSE_SCOPE
246 
247 #endif // PXR_IMAGING_GEOM_UTIL_MESH_GENERATOR_BASE_H
This class provides common implementation for the different mesh generator classes in GeomUtil.
Topology data for meshes.
Definition: meshTopology.h:69
Stores a 4x4 matrix of double elements.
Definition: matrix4d.h:87