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//
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
203
205 void SetVertexSharpness(float sharpness);
206
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() { }
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
321 return _isValid;
322}
323
324inline void
326 _isManifold = isManifold;
327}
328inline bool
330 return _isManifold;
331}
332
333inline void
335 _isBoundary = isBoundary;
336}
337inline bool
339 return _isBoundary;
340}
341
342//
343// Public inline methods involving sizes of incident faces:
344//
345inline bool
347 return _hasFaceSizes;
348}
349inline void
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
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
374 return _vertSharpness > 0.0f;
375}
376inline void
378 _vertSharpness = 0.0f;
379}
380
381inline void
383 _vertSharpness = vertSharpness;
384}
385inline float
387 return _vertSharpness;
388}
389
390//
391// Public inline methods involving vertex sharpness:
392//
393inline bool
395 return _hasEdgeSharpness;
396}
397inline void
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
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
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
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 */
Simple class used by subclasses of SurfaceFactory to describe a vertex.
float GetVertexSharpness() const
Return the sharpness of the vertex.
bool Finalize()
Terminate the sequence of specifications.
void SetManifold(bool isManifold)
Declare the vertex neighborhood as manifold (ordered)
bool Initialize(int numIncidentFaces)
Initialize specification with the number of incident faces.
bool IsManifold() const
Return if vertex neighborhood is manifold.
bool HasEdgeSharpness() const
Return if sharpness was assigned to the incident edges.
int GetIncidentFaceSize(int faceIndex) const
Return the size of an incident face.
float GetManifoldEdgeSharpness(int edgeIndex) const
Return the sharpness assigned to a manifold edge.
void SetIncidentFaceEdgeSharpness(int faceIndex, float leadingEdgeSharp, float trailingEdgeSharp)
Assign sharpness to the edges of an incident face.
bool HasVertexSharpness() const
Return if sharpness was assigned to the vertex.
void ClearIncidentFaceSizes()
Remove any assigned sizes of incident faces.
void SetVertexSharpness(float sharpness)
Assign sharpness to the vertex.
void ClearVertexSharpness()
Remove any sharpness assigned to the vertex.
void ClearEdgeSharpness()
Remove any sharpness assigned to the incident edges.
void GetIncidentFaceEdgeSharpness(int faceIndex, float *leadingEdgeSharp, float *trailingEdgeSharp) const
Return the sharpness assigned to edges of an incident face.
bool IsBoundary() const
Return if vertex neighborhood is on a boundary.
bool IsValid() const
Return if instance is valid.
bool HasIncidentFaceSizes() const
Return if the sizes of incident faces are assigned.
void SetBoundary(bool isOnBoundary)
Declare the vertex neighborhood as being on a boundary.
void SetIncidentFaceSize(int faceIndex, int faceSize)
Assign the size of an incident face.
void SetManifoldEdgeSharpness(int edgeIndex, float edgeSharpness)
Assign sharpness to the edge of a manifold neighborhood.