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