OpenSubdiv: opensubdiv/bfr/vertexDescriptor.h Source File

| OpenSubdiv

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