| OpenSubdiv

Loading...
Searching...
No Matches
vertexDescriptor.h
Go to the documentation of this file.
1//
2// Copyright 2021 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://opensubdiv.org/license.
6//
7
8#ifndef OPENSUBDIV3_BFR_VERTEX_DESCRIPTOR_H
9#define OPENSUBDIV3_BFR_VERTEX_DESCRIPTOR_H
10
11#include "../version.h"
12
13#include "../vtr/stackBuffer.h"
14
15 namespace OpenSubdiv {
16 namespace OPENSUBDIV_VERSION {
17
18 namespace Bfr {
19
33//
34// WIP - need to migrate some of these comments into Doxygen
35// - others will be moved to the external documentation
36//
37// It is used by subclasses of SurfaceFactory to provide a complete
38// topological description for each vertex of a face, i.e. invoked via
39// the virtual method:
40//
41// int populateFaceVertexDescriptor(Index baseFace,
42// int cornerVertex,
43// VertexDescriptor & v) const;
44//
45// Assignment of the full topology can be involved in the presence of
46// irregular faces, non-manifold topology or creasing around a vertex, but
47// many cases will be simple. For example, to specify a regular boundary
48// vertex of a Catmark mesh without any optional sharpness:
49//
50// int numIncidentFaces = 2;
51// bool vertexOnBoundary = true;
52//
53// vd.Initialize(numIncidentFaces);
54// vd.SetManifold(true);
55// vd.SetBoundary(vertexOnBoundary);
56// vd.ClearIncidentFaceSizes();
57// vd.Finalize();
58//
59// For a more general example, to assign a vertex of some valence whose
60// incident faces are of different sizes (e.g. required when triangles
61// appear around a vertex in an otherwise quad-dominant Catmark mesh):
62//
63// int numIncidentFaces = meshVertex.GetNumIncidentFaces();
64// bool vertexOnBoundary = meshVertex.IsBoundar();
65//
66// vd.Initialize(numIncidentFaces);
67// vd.SetManifold(true);
68// vd.SetBoundary(vertexOnBoundary);
69//
70// for (int i = 0; i < numIncidentFaces; ++i) {
71// vd.SetIncidentFaceSize(i, meshVertex.GetIncidentFaceSize(i));
72// }
73// vd.Finalize();
74//
75// These examples specify the incident faces as forming a manifold ring
76// (or half-ring) around the vertex, i.e. they can be specified as a
77// continuous, connected sequence in counter-clockwise order (and also
78// without degeneracies). In the case of a boundary vertex, the first
79// face must be on the leading edge of the boundary while the last is on
80// the trailing edge. For an interior vertex, which face is specified
81// first does not matter (since the set is periodic).
82//
83// In both cases, the location of the base face in this sequence -- the
84// face whose corner vertex is being described here -- must be specified
85// in the return value to populateFaceVertexDescriptor() (e.g. when a
86// boundary vertex has 3 incident faces, a return value of 0, 1 or 2
87// will indicate which is the base face).
88//
89// The corresponding methods to specify mesh control vertex indices (or
90// face-varying indices) complete the specification of the neighborhood:
91//
92// int getFaceCornerVertexIndices(Index baseFace, int cornerVertex,
93// Index vertexIndices[]) const;
94//
95// int getFaceCornerFVarValueIndices(Index baseFace, int cornerVertex,
96// Index fvarValueIndices[],
97// int fvarChannel) const;
98//
99// and are invoked by the Factory when needed.
100//
101// For each incident face, the indices for all vertices of that face are
102// to be specified (not the one-ring or some other subset). These indices
103// must also be specified in an orientation relative to the vertex, i.e.
104// for a vertex A and an incident face with face-vertices that may be
105// stored internally as {D, C, A, B}, they must be specified with A first
106// as {A, B, C, D}. This may seem a bit cumbersome, but it has clear
107// advantages when dealing with face-varying indices and unordered faces.
108//
109// More compact ways of specifying vertex indices for ordered, manifold
110// cases may be worth exploring in future, but face-varying indices and
111// non-manifold (unordered) vertices will always require such a full set,
112// so both methods will need to co-exist.
113//
114 class VertexDescriptor {
115 public:
116 // The full declaration must be enclosed by calls to these methods:
117 //
118 // Note that vertex valences or face sizes in excess of those defined
119 // in Bfr::Limits (typically 16-bits) are not valid. When specifying
120 // values in excess of these limits, initialization will fail and/or
121 // the descriptor will be marked invalid and finalization will fail.
122 //
123
125
132
134 bool Initialize(int numIncidentFaces);
135
137 bool Finalize();
138
140 bool IsValid() const;
142
143 //
144 // WIP - need to migrate these comments into Doxygen
145 //
146 // Three groups of methods describe the topology around a vertex:
147 // - simple properties (vertex is a boundary, manifold, etc.)
148 // - sizes of incident faces (constant or size for each face)
149 // - sharpness of the vertex and its incident edges (optional)
150 //
151
152 // Manifold and boundary conditions:
153 //
154 // The manifold property is a strict condition but preferred for
155 // efficiency and is usually available from common connected mesh
156 // representations. When declaring the topology as "manifold",
157 // the Factory assumes the following:
158 //
159 // - all incident faces are "ordered" (counter-clockwise)
160 // - all incident faces are consistently oriented
161 // - all incident edges are non-degenerate
162 //
163 // If not certain that all of these conditions are met, it is best
164 // to not declare manifold -- leaving the Factory to make sense of
165 // the set of incident faces from the face-vertex indices that are
166 // provided elsewhere.
167 //
168
170
174
176 void SetManifold(bool isManifold);
177
179 void SetBoundary(bool isOnBoundary);
180
182 void SetIncidentFaceSize(int faceIndex, int faceSize);
183
185 void ClearIncidentFaceSizes();
186
188 void SetVertexSharpness(float sharpness);
189
191 void ClearVertexSharpness();
192
204 void SetManifoldEdgeSharpness(int edgeIndex, float edgeSharpness);
205
221 void SetIncidentFaceEdgeSharpness(int faceIndex, float leadingEdgeSharp,
222 float trailingEdgeSharp);
223
225 void ClearEdgeSharpness();
227
229
234
236 bool IsManifold() const;
237
239 bool IsBoundary() const;
240
242 bool HasIncidentFaceSizes() const;
243
245 int GetIncidentFaceSize(int faceIndex) const;
246
248 bool HasVertexSharpness() const;
249
251 float GetVertexSharpness() const;
252
254 bool HasEdgeSharpness() const;
255
257 float GetManifoldEdgeSharpness(int edgeIndex) const;
258
260 void GetIncidentFaceEdgeSharpness(int faceIndex,
261 float * leadingEdgeSharp, float * trailingEdgeSharp) const;
263
264 protected:
266 friend class FaceVertex;
267
268 VertexDescriptor() { }
269 ~VertexDescriptor() { }
270
271 typedef Vtr::internal::StackBuffer<int,8,true> IntBuffer;
272 typedef Vtr::internal::StackBuffer<float,16,true> FloatBuffer;
273
274 void initFaceSizes();
275 void initEdgeSharpness();
277
278 protected:
280 // Member variables assigned through the above interface:
281 unsigned short _isValid : 1;
282 unsigned short _isInitialized : 1;
283 unsigned short _isFinalized : 1;
284
285 unsigned short _isManifold : 1;
286 unsigned short _isBoundary : 1;
287
288 unsigned short _hasFaceSizes : 1;
289 unsigned short _hasEdgeSharpness : 1;
290
291 short _numFaces;
292 float _vertSharpness;
293
294 FloatBuffer _faceEdgeSharpness;
295 IntBuffer _faceSizeOffsets;
297};
298
299//
300// Public inline methods for simple assignment:
301//
302 inline bool
303 VertexDescriptor::IsValid() const {
304 return _isValid;
305}
306
307 inline void
308 VertexDescriptor::SetManifold(bool isManifold) {
309 _isManifold = isManifold;
310}
311 inline bool
312 VertexDescriptor::IsManifold() const {
313 return _isManifold;
314}
315
316 inline void
317 VertexDescriptor::SetBoundary(bool isBoundary) {
318 _isBoundary = isBoundary;
319}
320 inline bool
321 VertexDescriptor::IsBoundary() const {
322 return _isBoundary;
323}
324
325//
326// Public inline methods involving sizes of incident faces:
327//
328 inline bool
329 VertexDescriptor::HasIncidentFaceSizes() const {
330 return _hasFaceSizes;
331}
332 inline void
333 VertexDescriptor::ClearIncidentFaceSizes() {
334 _hasFaceSizes = false;
335}
336
337 inline void
338 VertexDescriptor::SetIncidentFaceSize(int incFaceIndex, int faceSize) {
339
340 if (!_hasFaceSizes) initFaceSizes();
341
342 _faceSizeOffsets[incFaceIndex] = faceSize;
343}
344 inline int
345 VertexDescriptor::GetIncidentFaceSize(int incFaceIndex) const {
346
347 return _isFinalized ?
348 (_faceSizeOffsets[incFaceIndex+1] - _faceSizeOffsets[incFaceIndex]) :
349 _faceSizeOffsets[incFaceIndex];
350}
351
352//
353// Public inline methods involving vertex sharpness:
354//
355 inline bool
356 VertexDescriptor::HasVertexSharpness() const {
357 return _vertSharpness > 0.0f;
358}
359 inline void
360 VertexDescriptor::ClearVertexSharpness() {
361 _vertSharpness = 0.0f;
362}
363
364 inline void
365 VertexDescriptor::SetVertexSharpness(float vertSharpness) {
366 _vertSharpness = vertSharpness;
367}
368 inline float
369 VertexDescriptor::GetVertexSharpness() const {
370 return _vertSharpness;
371}
372
373//
374// Public inline methods involving vertex sharpness:
375//
376 inline bool
377 VertexDescriptor::HasEdgeSharpness() const {
378 return _hasEdgeSharpness;
379}
380 inline void
381 VertexDescriptor::ClearEdgeSharpness() {
382 _hasEdgeSharpness = false;
383}
384
385 inline void
386 VertexDescriptor::SetManifoldEdgeSharpness(int edgeIndex, float sharpness) {
387
388 if (!_hasEdgeSharpness) initEdgeSharpness();
389
390 // Assign the leading edge of the face after the edge (even index):
391 if (edgeIndex < _numFaces) {
392 _faceEdgeSharpness[2*edgeIndex] = sharpness;
393 }
394
395 // Assign the trailing edge of the face before the edge (odd index):
396 if (edgeIndex > 0) {
397 _faceEdgeSharpness[2*edgeIndex-1] = sharpness;
398 } else if (!IsBoundary()) {
399 _faceEdgeSharpness[2*_numFaces-1] = sharpness;
400 }
401}
402 inline float
403 VertexDescriptor::GetManifoldEdgeSharpness(int edgeIndex) const {
404
405 // All edges are first of the pair (even index) except last of boundary
406 return _faceEdgeSharpness[2*edgeIndex - (edgeIndex == _numFaces)];
407}
408
409 inline void
410 VertexDescriptor::SetIncidentFaceEdgeSharpness(int faceIndex,
411 float leadingEdgeSharpness, float trailingEdgeSharpness) {
412
413 if (!_hasEdgeSharpness) initEdgeSharpness();
414
415 _faceEdgeSharpness[2*faceIndex ] = leadingEdgeSharpness;
416 _faceEdgeSharpness[2*faceIndex+1] = trailingEdgeSharpness;
417}
418 inline void
419 VertexDescriptor::GetIncidentFaceEdgeSharpness(int faceIndex,
420 float * leadingEdgeSharpness, float * trailingEdgeSharpness) const {
421
422 *leadingEdgeSharpness = _faceEdgeSharpness[2*faceIndex];
423 *trailingEdgeSharpness = _faceEdgeSharpness[2*faceIndex+1];
424}
425
426} // end namespace Bfr
427
428} // end namespace OPENSUBDIV_VERSION
429 using namespace OPENSUBDIV_VERSION;
430} // end namespace OpenSubdiv
431
432#endif /* OPENSUBDIV3_BFR_VERTEX_DESCRIPTOR_H */
stackBuffer.h
OpenSubdiv
Definition limits.h:15
OpenSubdiv::OPENSUBDIV_VERSION
Definition limits.h:16
OpenSubdiv::OPENSUBDIV_VERSION::Bfr
Definition limits.h:18
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor
Simple class used by subclasses of SurfaceFactory to describe a vertex.
Definition vertexDescriptor.h:114
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::GetVertexSharpness
float GetVertexSharpness() const
Return the sharpness of the vertex.
Definition vertexDescriptor.h:369
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::Finalize
bool Finalize()
Terminate the sequence of specifications.
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::SetManifold
void SetManifold(bool isManifold)
Declare the vertex neighborhood as manifold (ordered).
Definition vertexDescriptor.h:308
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::Initialize
bool Initialize(int numIncidentFaces)
Initialize specification with the number of incident faces.
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::IsManifold
bool IsManifold() const
Return if vertex neighborhood is manifold.
Definition vertexDescriptor.h:312
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::HasEdgeSharpness
bool HasEdgeSharpness() const
Return if sharpness was assigned to the incident edges.
Definition vertexDescriptor.h:377
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::GetIncidentFaceSize
int GetIncidentFaceSize(int faceIndex) const
Return the size of an incident face.
Definition vertexDescriptor.h:345
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::GetManifoldEdgeSharpness
float GetManifoldEdgeSharpness(int edgeIndex) const
Return the sharpness assigned to a manifold edge.
Definition vertexDescriptor.h:403
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::SetIncidentFaceEdgeSharpness
void SetIncidentFaceEdgeSharpness(int faceIndex, float leadingEdgeSharp, float trailingEdgeSharp)
Assign sharpness to the edges of an incident face.
Definition vertexDescriptor.h:410
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::HasVertexSharpness
bool HasVertexSharpness() const
Return if sharpness was assigned to the vertex.
Definition vertexDescriptor.h:356
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::ClearIncidentFaceSizes
void ClearIncidentFaceSizes()
Remove any assigned sizes of incident faces.
Definition vertexDescriptor.h:333
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::SetVertexSharpness
void SetVertexSharpness(float sharpness)
Assign sharpness to the vertex.
Definition vertexDescriptor.h:365
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::ClearVertexSharpness
void ClearVertexSharpness()
Remove any sharpness assigned to the vertex.
Definition vertexDescriptor.h:360
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::ClearEdgeSharpness
void ClearEdgeSharpness()
Remove any sharpness assigned to the incident edges.
Definition vertexDescriptor.h:381
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::GetIncidentFaceEdgeSharpness
void GetIncidentFaceEdgeSharpness(int faceIndex, float *leadingEdgeSharp, float *trailingEdgeSharp) const
Return the sharpness assigned to edges of an incident face.
Definition vertexDescriptor.h:419
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::IsBoundary
bool IsBoundary() const
Return if vertex neighborhood is on a boundary.
Definition vertexDescriptor.h:321
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::IsValid
bool IsValid() const
Return if instance is valid.
Definition vertexDescriptor.h:303
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::HasIncidentFaceSizes
bool HasIncidentFaceSizes() const
Return if the sizes of incident faces are assigned.
Definition vertexDescriptor.h:329
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::SetBoundary
void SetBoundary(bool isOnBoundary)
Declare the vertex neighborhood as being on a boundary.
Definition vertexDescriptor.h:317
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::SetIncidentFaceSize
void SetIncidentFaceSize(int faceIndex, int faceSize)
Assign the size of an incident face.
Definition vertexDescriptor.h:338
OpenSubdiv::OPENSUBDIV_VERSION::Bfr::VertexDescriptor::SetManifoldEdgeSharpness
void SetManifoldEdgeSharpness(int edgeIndex, float edgeSharpness)
Assign sharpness to the edge of a manifold neighborhood.
Definition vertexDescriptor.h:386