OpenSubdiv
Loading...
Searching...
No Matches
level.h
Go to the documentation of this file.
1//
2// Copyright 2014 DreamWorks Animation LLC.
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://opensubdiv.org/license.
6//
7#ifndef OPENSUBDIV3_VTR_LEVEL_H
8#define OPENSUBDIV3_VTR_LEVEL_H
9
10#include "../version.h"
11
12#include "../sdc/types.h"
13#include "../sdc/crease.h"
14#include "../sdc/options.h"
15#include "../vtr/types.h"
16
17#include <algorithm>
18#include <vector>
19#include <cassert>
20#include <cstring>
21
22
23namespace OpenSubdiv {
24namespace OPENSUBDIV_VERSION {
25
26namespace Vtr {
27namespace internal {
28
29class Refinement;
30class TriRefinement;
31class QuadRefinement;
32class FVarRefinement;
33class FVarLevel;
34
35//
36// Level:
37// A refinement level includes a vectorized representation of the topology
38// for a particular subdivision level. The topology is "complete" in that any
39// level can be used as the base level of another subdivision hierarchy and can
40// be considered a complete mesh independent of its ancestors. It currently
41// does contain a "depth" member -- as some inferences can then be made about
42// the topology (i.e. all quads or all tris if not level 0).
43//
44// This class is intended for private use within the library. There are still
45// opportunities to specialize levels -- e.g. those supporting N-sided faces vs
46// those that are purely quads or tris -- so we prefer to insulate it from public
47// access.
48//
49// The representation of topology here is to store six topological relationships
50// in tables of integers. Each is stored in its own array(s) so the result is
51// a SOA representation of the topology. The six relations are:
52//
53// - face-verts: vertices incident/comprising a face
54// - face-edges: edges incident a face
55// - edge-verts: vertices incident/comprising an edge
56// - edge-faces: faces incident an edge
57// - vert-faces: faces incident a vertex
58// - vert-edges: edges incident a vertex
59//
60// There is some redundancy here but the intent is not that this be a minimal
61// representation, the intent is that it be amenable to refinement. Classes in
62// the Far layer essentially store 5 of these 6 in a permuted form -- we add
63// the face-edges here to simplify refinement.
64//
65
66class Level {
67
68public:
69 //
70 // Simple nested types to hold the tags for each component type -- some of
71 // which are user-specified features (e.g. whether a face is a hole or not)
72 // while others indicate the topological nature of the component, how it
73 // is affected by creasing in its neighborhood, etc.
74 //
75 // Most of these properties are passed down to child components during
76 // refinement, but some -- notably the designation of a component as semi-
77 // sharp -- require re-determination as sharpness values are reduced at each
78 // level.
79 //
80 struct VTag {
81 VTag() { }
82
83 // When cleared, the VTag ALMOST represents a smooth, regular, interior
84 // vertex -- the Type enum requires a bit be explicitly set for Smooth,
85 // so that must be done explicitly if desired on initialization.
86 void clear() { std::memset((void*) this, 0, sizeof(VTag)); }
87
88 typedef unsigned short VTagSize;
89
90 VTagSize _nonManifold : 1; // fixed
91 VTagSize _xordinary : 1; // fixed
92 VTagSize _boundary : 1; // fixed
93 VTagSize _corner : 1; // fixed
94 VTagSize _infSharp : 1; // fixed
95 VTagSize _semiSharp : 1; // variable
96 VTagSize _semiSharpEdges : 1; // variable
97 VTagSize _rule : 4; // variable when _semiSharp
98
99 // These next to tags are complementary -- the "incomplete" tag is only
100 // relevant for refined levels while the "incident an irregular face" tag
101 // is only relevant for the base level. They could be combined as both
102 // indicate "no full regular ring" around a vertex
103 VTagSize _incomplete : 1; // variable only set in refined levels
104 VTagSize _incidIrregFace : 1; // variable only set in base level
105
106 // Tags indicating incident infinitely-sharp (permanent) features
107 VTagSize _infSharpEdges : 1; // fixed
108 VTagSize _infSharpCrease : 1; // fixed
109 VTagSize _infIrregular : 1; // fixed
110
111 // Alternate constructor and accessor for dealing with integer bits directly:
112 explicit VTag(VTagSize bits) {
113 std::memcpy(this, &bits, sizeof(bits));
114 }
115 VTagSize getBits() const {
116 VTagSize bits;
117 std::memcpy(&bits, this, sizeof(bits));
118 return bits;
119 }
120
121 static VTag BitwiseOr(VTag const vTags[], int size = 4);
122 };
123 struct ETag {
124 ETag() { }
125
126 // When cleared, the ETag represents a smooth, manifold, interior edge
127 void clear() { std::memset((void*) this, 0, sizeof(ETag)); }
128
129 typedef unsigned char ETagSize;
130
131 ETagSize _nonManifold : 1; // fixed
132 ETagSize _boundary : 1; // fixed
133 ETagSize _infSharp : 1; // fixed
134 ETagSize _semiSharp : 1; // variable
135
136 // Alternate constructor and accessor for dealing with integer bits directly:
137 explicit ETag(ETagSize bits) {
138 std::memcpy(this, &bits, sizeof(bits));
139 }
140 ETagSize getBits() const {
141 ETagSize bits;
142 std::memcpy(&bits, this, sizeof(bits));
143 return bits;
144 }
145
146 static ETag BitwiseOr(ETag const eTags[], int size = 4);
147 };
148 struct FTag {
149 FTag() { }
150
151 void clear() { std::memset((void*) this, 0, sizeof(FTag)); }
152
153 typedef unsigned char FTagSize;
154
155 FTagSize _hole : 1; // fixed
156
157 // On deck -- coming soon...
158 //FTagSize _hasEdits : 1; // variable
159 };
160
161 // Additional simple struct to identify a "span" around a vertex, i.e. a
162 // subset of the faces around a vertex delimited by some property (e.g. a
163 // face-varying discontinuity, an inf-sharp edge, etc.)
164 //
165 // The span requires an "origin" and a "size" to fully define its extent.
166 // Use of the size is required over a leading/trailing pair as the valence
167 // around a non-manifold vertex cannot be trivially determined from two
168 // extremeties. Similarly a start face is chosen over an edge as starting
169 // with a manifold edge is ambiguous. Additional tags also support
170 // non-manifold cases, e.g. periodic spans at the apex of a double cone.
171 //
172 // Currently setting the size to 0 or leaving the span "unassigned" is an
173 // indication to use the full neighborhood rather than a subset -- prefer
174 // use of the const method here to direct inspection of the member.
175 //
176 struct VSpan {
177 VSpan() { std::memset((void*) this, 0, sizeof(VSpan)); }
178
179 void clear() { std::memset((void*) this, 0, sizeof(VSpan)); }
180 bool isAssigned() const { return _numFaces > 0; }
181
182 LocalIndex _numFaces;
183 LocalIndex _startFace;
184 LocalIndex _cornerInSpan;
185
186 unsigned short _periodic : 1;
187 unsigned short _sharp : 1;
188 };
189
190public:
191 Level();
192 ~Level();
193
194 // Simple accessors:
195 int getDepth() const { return _depth; }
196
197 int getNumVertices() const { return _vertCount; }
198 int getNumFaces() const { return _faceCount; }
199 int getNumEdges() const { return _edgeCount; }
200
201 // More global sizes may prove useful...
202 int getNumFaceVerticesTotal() const { return (int) _faceVertIndices.size(); }
203 int getNumFaceEdgesTotal() const { return (int) _faceEdgeIndices.size(); }
204 int getNumEdgeVerticesTotal() const { return (int) _edgeVertIndices.size(); }
205 int getNumEdgeFacesTotal() const { return (int) _edgeFaceIndices.size(); }
206 int getNumVertexFacesTotal() const { return (int) _vertFaceIndices.size(); }
207 int getNumVertexEdgesTotal() const { return (int) _vertEdgeIndices.size(); }
208
209 int getMaxValence() const { return _maxValence; }
210 int getMaxEdgeFaces() const { return _maxEdgeFaces; }
211
212 // Methods to access the relation tables/indices -- note that for some relations
213 // (i.e. those where a component is "contained by" a neighbor, or more generally
214 // when the neighbor is a simplex of higher dimension) we store an additional
215 // "local index", e.g. for the case of vert-faces if one of the faces F[i] is
216 // incident a vertex V, then L[i] is the "local index" in F[i] of vertex V.
217 // Once have only quads (or tris), this local index need only occupy two bits
218 // and could conceivably be packed into the same integer as the face index, but
219 // for now, given the need to support faces of potentially high valence we'll
220 // use an 8- or 16-bit integer.
221 //
222 // Methods to access the six topological relations:
223 ConstIndexArray getFaceVertices(Index faceIndex) const;
224 ConstIndexArray getFaceEdges(Index faceIndex) const;
225 ConstIndexArray getEdgeVertices(Index edgeIndex) const;
226 ConstIndexArray getEdgeFaces(Index edgeIndex) const;
227 ConstIndexArray getVertexFaces(Index vertIndex) const;
228 ConstIndexArray getVertexEdges(Index vertIndex) const;
229
230 ConstLocalIndexArray getEdgeFaceLocalIndices(Index edgeIndex) const;
231 ConstLocalIndexArray getVertexFaceLocalIndices(Index vertIndex) const;
232 ConstLocalIndexArray getVertexEdgeLocalIndices(Index vertIndex) const;
233
234 // Replace these with access to sharpness buffers/arrays rather than elements:
235 float getEdgeSharpness(Index edgeIndex) const;
236 float getVertexSharpness(Index vertIndex) const;
237 Sdc::Crease::Rule getVertexRule(Index vertIndex) const;
238
239 Index findEdge(Index v0Index, Index v1Index) const;
240
241 // Holes
242 void setFaceHole(Index faceIndex, bool b);
243 bool isFaceHole(Index faceIndex) const;
244
245 // Face-varying
246 Sdc::Options getFVarOptions(int channel) const;
247 int getNumFVarChannels() const { return (int) _fvarChannels.size(); }
248 int getNumFVarValues(int channel) const;
249 ConstIndexArray getFaceFVarValues(Index faceIndex, int channel) const;
250
251 FVarLevel & getFVarLevel(int channel) { return *_fvarChannels[channel]; }
252 FVarLevel const & getFVarLevel(int channel) const { return *_fvarChannels[channel]; }
253
254 // Manifold/non-manifold tags:
255 void setEdgeNonManifold(Index edgeIndex, bool b);
256 bool isEdgeNonManifold(Index edgeIndex) const;
257
258 void setVertexNonManifold(Index vertIndex, bool b);
259 bool isVertexNonManifold(Index vertIndex) const;
260
261 // General access to all component tags:
262 VTag const & getVertexTag(Index vertIndex) const { return _vertTags[vertIndex]; }
263 ETag const & getEdgeTag(Index edgeIndex) const { return _edgeTags[edgeIndex]; }
264 FTag const & getFaceTag(Index faceIndex) const { return _faceTags[faceIndex]; }
265
266 VTag & getVertexTag(Index vertIndex) { return _vertTags[vertIndex]; }
267 ETag & getEdgeTag(Index edgeIndex) { return _edgeTags[edgeIndex]; }
268 FTag & getFaceTag(Index faceIndex) { return _faceTags[faceIndex]; }
269
270public:
271
272 // Debugging aides:
273 enum TopologyError {
274 TOPOLOGY_MISSING_EDGE_FACES=0,
275 TOPOLOGY_MISSING_EDGE_VERTS,
276 TOPOLOGY_MISSING_FACE_EDGES,
277 TOPOLOGY_MISSING_FACE_VERTS,
278 TOPOLOGY_MISSING_VERT_FACES,
279 TOPOLOGY_MISSING_VERT_EDGES,
280
281 TOPOLOGY_FAILED_CORRELATION_EDGE_FACE,
282 TOPOLOGY_FAILED_CORRELATION_FACE_VERT,
283 TOPOLOGY_FAILED_CORRELATION_FACE_EDGE,
284
285 TOPOLOGY_FAILED_ORIENTATION_INCIDENT_EDGE,
286 TOPOLOGY_FAILED_ORIENTATION_INCIDENT_FACE,
287 TOPOLOGY_FAILED_ORIENTATION_INCIDENT_FACES_EDGES,
288
289 TOPOLOGY_DEGENERATE_EDGE,
290 TOPOLOGY_NON_MANIFOLD_EDGE,
291
292 TOPOLOGY_INVALID_CREASE_EDGE,
293 TOPOLOGY_INVALID_CREASE_VERT
294 };
295
296 static char const * getTopologyErrorString(TopologyError errCode);
297
298 typedef void (* ValidationCallback)(TopologyError errCode, char const * msg, void const * clientData);
299
300 bool validateTopology(ValidationCallback callback=0, void const * clientData=0) const;
301
302 void print(const Refinement* parentRefinement = 0) const;
303
304public:
305 // High-level topology queries -- these may be moved elsewhere:
306
307 bool isSingleCreasePatch(Index face, float* sharpnessOut=NULL, int* rotationOut=NULL) const;
308
309 //
310 // When inspecting topology, the component tags -- particularly VTag and ETag -- are most
311 // often inspected in groups for the face to which they belong. They are designed to be
312 // bitwise OR'd (the result then referred to as a "composite" tag) to make quick decisions
313 // about the face as a whole to avoid tedious topological inspection.
314 //
315 // The same logic can be applied to topology in a FVar channel when tags specific to that
316 // channel are used. Note that the VTags apply to the FVar values assigned to the corners
317 // of the face and not the vertex as a whole. The "composite" face-varying VTag for a
318 // vertex is the union of VTags of all distinct FVar values for that vertex.
319 //
320 bool doesVertexFVarTopologyMatch(Index vIndex, int fvarChannel) const;
321 bool doesFaceFVarTopologyMatch( Index fIndex, int fvarChannel) const;
322 bool doesEdgeFVarTopologyMatch( Index eIndex, int fvarChannel) const;
323
324 void getFaceVTags(Index fIndex, VTag vTags[], int fvarChannel = -1) const;
325 void getFaceETags(Index fIndex, ETag eTags[], int fvarChannel = -1) const;
326
327 VTag getFaceCompositeVTag(Index fIndex, int fvarChannel = -1) const;
328 VTag getFaceCompositeVTag(ConstIndexArray & fVerts) const;
329
330 VTag getVertexCompositeFVarVTag(Index vIndex, int fvarChannel) const;
331
332 //
333 // When gathering "patch points" we may want the indices of the vertices or the corresponding
334 // FVar values for a particular channel. Both are represented and equally accessible within
335 // the faces, so we allow all to be returned through these methods. Setting the optional FVar
336 // channel to -1 will retrieve indices of vertices instead of FVar values:
337 //
338 int gatherQuadLinearPatchPoints(Index fIndex, Index patchPoints[], int rotation = 0,
339 int fvarChannel = -1) const;
340
341 int gatherQuadRegularInteriorPatchPoints(Index fIndex, Index patchPoints[], int rotation = 0,
342 int fvarChannel = -1) const;
343 int gatherQuadRegularBoundaryPatchPoints(Index fIndex, Index patchPoints[], int boundaryEdgeInFace,
344 int fvarChannel = -1) const;
345 int gatherQuadRegularCornerPatchPoints( Index fIndex, Index patchPoints[], int cornerVertInFace,
346 int fvarChannel = -1) const;
347
348 int gatherQuadRegularRingAroundVertex(Index vIndex, Index ringPoints[],
349 int fvarChannel = -1) const;
350 int gatherQuadRegularPartialRingAroundVertex(Index vIndex, VSpan const & span, Index ringPoints[],
351 int fvarChannel = -1) const;
352
353 // WIP -- for future use, need to extend for face-varying...
354 int gatherTriRegularInteriorPatchPoints( Index fIndex, Index patchVerts[], int rotation = 0) const;
355 int gatherTriRegularBoundaryVertexPatchPoints(Index fIndex, Index patchVerts[], int boundaryVertInFace) const;
356 int gatherTriRegularBoundaryEdgePatchPoints( Index fIndex, Index patchVerts[], int boundaryEdgeInFace) const;
357 int gatherTriRegularCornerVertexPatchPoints( Index fIndex, Index patchVerts[], int cornerVertInFace) const;
358 int gatherTriRegularCornerEdgePatchPoints( Index fIndex, Index patchVerts[], int cornerEdgeInFace) const;
359
360public:
361 // Sizing methods used to construct a level to populate:
362 void resizeFaces( int numFaces);
363 void resizeFaceVertices(int numFaceVertsTotal);
364 void resizeFaceEdges( int numFaceEdgesTotal);
365
366 void resizeEdges( int numEdges);
367 void resizeEdgeVertices(); // always 2*edgeCount
368 void resizeEdgeFaces(int numEdgeFacesTotal);
369
370 void resizeVertices( int numVertices);
371 void resizeVertexFaces(int numVertexFacesTotal);
372 void resizeVertexEdges(int numVertexEdgesTotal);
373
374 void setMaxValence(int maxValence);
375
376 // Modifiers to populate the relations for each component:
377 IndexArray getFaceVertices(Index faceIndex);
378 IndexArray getFaceEdges(Index faceIndex);
379 IndexArray getEdgeVertices(Index edgeIndex);
380 IndexArray getEdgeFaces(Index edgeIndex);
381 IndexArray getVertexFaces(Index vertIndex);
382 IndexArray getVertexEdges(Index vertIndex);
383
384 LocalIndexArray getEdgeFaceLocalIndices(Index edgeIndex);
385 LocalIndexArray getVertexFaceLocalIndices(Index vertIndex);
386 LocalIndexArray getVertexEdgeLocalIndices(Index vertIndex);
387
388 // Replace these with access to sharpness buffers/arrays rather than elements:
389 float& getEdgeSharpness(Index edgeIndex);
390 float& getVertexSharpness(Index vertIndex);
391
392 // Create, destroy and populate face-varying channels:
393 int createFVarChannel(int fvarValueCount, Sdc::Options const& options);
394 void destroyFVarChannel(int channel);
395
396 IndexArray getFaceFVarValues(Index faceIndex, int channel);
397
398 void completeFVarChannelTopology(int channel, int regBoundaryValence);
399
400 // Counts and offsets for all relation types:
401 // - these may be unwarranted if we let Refinement access members directly...
402 int getNumFaceVertices( Index faceIndex) const { return _faceVertCountsAndOffsets[2*faceIndex]; }
403 int getOffsetOfFaceVertices(Index faceIndex) const { return _faceVertCountsAndOffsets[2*faceIndex + 1]; }
404
405 int getNumFaceEdges( Index faceIndex) const { return getNumFaceVertices(faceIndex); }
406 int getOffsetOfFaceEdges(Index faceIndex) const { return getOffsetOfFaceVertices(faceIndex); }
407
408 int getNumEdgeVertices( Index ) const { return 2; }
409 int getOffsetOfEdgeVertices(Index edgeIndex) const { return 2 * edgeIndex; }
410
411 int getNumEdgeFaces( Index edgeIndex) const { return _edgeFaceCountsAndOffsets[2*edgeIndex]; }
412 int getOffsetOfEdgeFaces(Index edgeIndex) const { return _edgeFaceCountsAndOffsets[2*edgeIndex + 1]; }
413
414 int getNumVertexFaces( Index vertIndex) const { return _vertFaceCountsAndOffsets[2*vertIndex]; }
415 int getOffsetOfVertexFaces(Index vertIndex) const { return _vertFaceCountsAndOffsets[2*vertIndex + 1]; }
416
417 int getNumVertexEdges( Index vertIndex) const { return _vertEdgeCountsAndOffsets[2*vertIndex]; }
418 int getOffsetOfVertexEdges(Index vertIndex) const { return _vertEdgeCountsAndOffsets[2*vertIndex + 1]; }
419
420 ConstIndexArray getFaceVertices() const;
421
422 //
423 // Note that for some relations, the size of the relations for a child component
424 // can vary radically from its parent due to the sparsity of the refinement. So
425 // in these cases a few additional utilities are provided to help define the set
426 // of incident components. Assuming adequate memory has been allocated, the
427 // "resize" methods here initialize the set of incident components by setting
428 // both the size and the appropriate offset, while "trim" is use to quickly lower
429 // the size from an upper bound and nothing else.
430 //
431 void resizeFaceVertices(Index FaceIndex, int count);
432
433 void resizeEdgeFaces(Index edgeIndex, int count);
434 void trimEdgeFaces( Index edgeIndex, int count);
435
436 void resizeVertexFaces(Index vertIndex, int count);
437 void trimVertexFaces( Index vertIndex, int count);
438
439 void resizeVertexEdges(Index vertIndex, int count);
440 void trimVertexEdges( Index vertIndex, int count);
441
442public:
443 //
444 // Initial plans were to have a few specific classes properly construct the
445 // topology from scratch, e.g. the Refinement class and a Factory class for
446 // the base level, by populating all topological relations. The need to have
447 // a class construct full topology given only a simple face-vertex list, made
448 // it necessary to write code to define and orient all relations -- and most
449 // of that seemed best placed here.
450 //
451 bool completeTopologyFromFaceVertices();
452 Index findEdge(Index v0, Index v1, ConstIndexArray v0Edges) const;
453
454 // Methods supporting the above:
455 void orientIncidentComponents();
456 bool orderVertexFacesAndEdges(Index vIndex, Index* vFaces, Index* vEdges) const;
457 bool orderVertexFacesAndEdges(Index vIndex);
458 bool testVertexNonManifoldCrease(Index vIndex) const;
459 void populateLocalIndices();
460
461 IndexArray shareFaceVertCountsAndOffsets() const;
462
463private:
464 // Refinement classes (including all subclasses) build a Level:
465 friend class Refinement;
466 friend class TriRefinement;
467 friend class QuadRefinement;
468
469 //
470 // A Level is independent of subdivision scheme or options. While it may have been
471 // affected by them in its construction, they are not associated with it -- a Level
472 // is pure topology and any subdivision parameters are external.
473 //
474
475 // Simple members for inventory, etc.
476 int _faceCount;
477 int _edgeCount;
478 int _vertCount;
479
480 // The "depth" member is clearly useful in both the topological splitting and the
481 // stencil queries, but arguably it ties the Level to a hierarchy which counters
482 // the idea of it being independent.
483 int _depth;
484
485 // Maxima to help clients manage sizing of data buffers. Given "max valence",
486 // the "max edge faces" is strictly redundant as it will always be less, but
487 // since it will typically be so much less (i.e. 2) it is kept for now.
488 int _maxEdgeFaces;
489 int _maxValence;
490
491 //
492 // Topology vectors:
493 // Note that of all of these, only data for the face-edge relation is not
494 // stored in the osd::FarTables in any form. The FarTable vectors combine
495 // the edge-vert and edge-face relations. The eventual goal is that this
496 // data be part of the osd::Far classes and be a superset of the FarTable
497 // vectors, i.e. no data duplication or conversion. The fact that FarTable
498 // already stores 5 of the 6 possible relations should make the topology
499 // storage as a whole a non-issue.
500 //
501 // The vert-face-child and vert-edge-child indices are also arguably not
502 // a topology relation but more one for parent/child relations. But it is
503 // a topological relationship, and if named differently would not likely
504 // raise this. It has been named with "child" in the name as it does play
505 // a more significant role during subdivision in mapping between parent
506 // and child components, and so has been named to reflect that more clearly.
507 //
508
509 // Per-face:
510 std::vector<Index> _faceVertCountsAndOffsets; // 2 per face, redundant after level 0
511 std::vector<Index> _faceVertIndices; // 3 or 4 per face, variable at level 0
512 std::vector<Index> _faceEdgeIndices; // matches face-vert indices
513 std::vector<FTag> _faceTags; // 1 per face: includes "hole" tag
514
515 // Per-edge:
516 std::vector<Index> _edgeVertIndices; // 2 per edge
517 std::vector<Index> _edgeFaceCountsAndOffsets; // 2 per edge
518 std::vector<Index> _edgeFaceIndices; // varies with faces per edge
519 std::vector<LocalIndex> _edgeFaceLocalIndices; // varies with faces per edge
520
521 std::vector<float> _edgeSharpness; // 1 per edge
522 std::vector<ETag> _edgeTags; // 1 per edge: manifold, boundary, etc.
523
524 // Per-vertex:
525 std::vector<Index> _vertFaceCountsAndOffsets; // 2 per vertex
526 std::vector<Index> _vertFaceIndices; // varies with valence
527 std::vector<LocalIndex> _vertFaceLocalIndices; // varies with valence, 8-bit for now
528
529 std::vector<Index> _vertEdgeCountsAndOffsets; // 2 per vertex
530 std::vector<Index> _vertEdgeIndices; // varies with valence
531 std::vector<LocalIndex> _vertEdgeLocalIndices; // varies with valence, 8-bit for now
532
533 std::vector<float> _vertSharpness; // 1 per vertex
534 std::vector<VTag> _vertTags; // 1 per vertex: manifold, Sdc::Rule, etc.
535
536 // Face-varying channels:
537 std::vector<FVarLevel*> _fvarChannels;
538};
539
540//
541// Access/modify the vertices incident a given face:
542//
543inline ConstIndexArray
544Level::getFaceVertices(Index faceIndex) const {
545 return ConstIndexArray(&_faceVertIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
546 _faceVertCountsAndOffsets[faceIndex*2]);
547}
548inline IndexArray
549Level::getFaceVertices(Index faceIndex) {
550 return IndexArray(&_faceVertIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
551 _faceVertCountsAndOffsets[faceIndex*2]);
552}
553
554inline void
555Level::resizeFaceVertices(Index faceIndex, int count) {
556
557 int* countOffsetPair = &_faceVertCountsAndOffsets[faceIndex*2];
558
559 countOffsetPair[0] = count;
560 countOffsetPair[1] = (faceIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
561
562 _maxValence = std::max(_maxValence, count);
563}
564
565inline ConstIndexArray
566Level::getFaceVertices() const {
567 return ConstIndexArray(&_faceVertIndices[0], (int)_faceVertIndices.size());
568}
569
570//
571// Access/modify the edges incident a given face:
572//
573inline ConstIndexArray
574Level::getFaceEdges(Index faceIndex) const {
575 return ConstIndexArray(&_faceEdgeIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
576 _faceVertCountsAndOffsets[faceIndex*2]);
577}
578inline IndexArray
579Level::getFaceEdges(Index faceIndex) {
580 return IndexArray(&_faceEdgeIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
581 _faceVertCountsAndOffsets[faceIndex*2]);
582}
583
584//
585// Access/modify the faces incident a given vertex:
586//
587inline ConstIndexArray
588Level::getVertexFaces(Index vertIndex) const {
589 return ConstIndexArray( (&_vertFaceIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
590 _vertFaceCountsAndOffsets[vertIndex*2]);
591}
592inline IndexArray
593Level::getVertexFaces(Index vertIndex) {
594 return IndexArray( (&_vertFaceIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
595 _vertFaceCountsAndOffsets[vertIndex*2]);
596}
597
599Level::getVertexFaceLocalIndices(Index vertIndex) const {
600 return ConstLocalIndexArray( (&_vertFaceLocalIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
601 _vertFaceCountsAndOffsets[vertIndex*2]);
602}
603inline LocalIndexArray
604Level::getVertexFaceLocalIndices(Index vertIndex) {
605 return LocalIndexArray( (&_vertFaceLocalIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
606 _vertFaceCountsAndOffsets[vertIndex*2]);
607}
608
609inline void
610Level::resizeVertexFaces(Index vertIndex, int count) {
611 int* countOffsetPair = &_vertFaceCountsAndOffsets[vertIndex*2];
612
613 countOffsetPair[0] = count;
614 countOffsetPair[1] = (vertIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
615}
616inline void
617Level::trimVertexFaces(Index vertIndex, int count) {
618 _vertFaceCountsAndOffsets[vertIndex*2] = count;
619}
620
621//
622// Access/modify the edges incident a given vertex:
623//
624inline ConstIndexArray
625Level::getVertexEdges(Index vertIndex) const {
626 return ConstIndexArray( (&_vertEdgeIndices[0]) +_vertEdgeCountsAndOffsets[vertIndex*2+1],
627 _vertEdgeCountsAndOffsets[vertIndex*2]);
628}
629inline IndexArray
630Level::getVertexEdges(Index vertIndex) {
631 return IndexArray( (&_vertEdgeIndices[0]) +_vertEdgeCountsAndOffsets[vertIndex*2+1],
632 _vertEdgeCountsAndOffsets[vertIndex*2]);
633}
634
636Level::getVertexEdgeLocalIndices(Index vertIndex) const {
637 return ConstLocalIndexArray( (&_vertEdgeLocalIndices[0]) + _vertEdgeCountsAndOffsets[vertIndex*2+1],
638 _vertEdgeCountsAndOffsets[vertIndex*2]);
639}
640inline LocalIndexArray
641Level::getVertexEdgeLocalIndices(Index vertIndex) {
642 return LocalIndexArray( (&_vertEdgeLocalIndices[0]) + _vertEdgeCountsAndOffsets[vertIndex*2+1],
643 _vertEdgeCountsAndOffsets[vertIndex*2]);
644}
645
646inline void
647Level::resizeVertexEdges(Index vertIndex, int count) {
648 int* countOffsetPair = &_vertEdgeCountsAndOffsets[vertIndex*2];
649
650 countOffsetPair[0] = count;
651 countOffsetPair[1] = (vertIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
652
653 _maxValence = std::max(_maxValence, count);
654}
655inline void
656Level::trimVertexEdges(Index vertIndex, int count) {
657 _vertEdgeCountsAndOffsets[vertIndex*2] = count;
658}
659
660inline void
661Level::setMaxValence(int valence) {
662 _maxValence = valence;
663}
664
665//
666// Access/modify the vertices incident a given edge:
667//
668inline ConstIndexArray
669Level::getEdgeVertices(Index edgeIndex) const {
670 return ConstIndexArray(&_edgeVertIndices[edgeIndex*2], 2);
671}
672inline IndexArray
673Level::getEdgeVertices(Index edgeIndex) {
674 return IndexArray(&_edgeVertIndices[edgeIndex*2], 2);
675}
676
677//
678// Access/modify the faces incident a given edge:
679//
680inline ConstIndexArray
681Level::getEdgeFaces(Index edgeIndex) const {
682 return ConstIndexArray(&_edgeFaceIndices[0] +
683 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
684 _edgeFaceCountsAndOffsets[edgeIndex*2]);
685}
686inline IndexArray
687Level::getEdgeFaces(Index edgeIndex) {
688 return IndexArray(&_edgeFaceIndices[0] +
689 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
690 _edgeFaceCountsAndOffsets[edgeIndex*2]);
691}
692
694Level::getEdgeFaceLocalIndices(Index edgeIndex) const {
695 return ConstLocalIndexArray(&_edgeFaceLocalIndices[0] +
696 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
697 _edgeFaceCountsAndOffsets[edgeIndex*2]);
698}
699inline LocalIndexArray
700Level::getEdgeFaceLocalIndices(Index edgeIndex) {
701 return LocalIndexArray(&_edgeFaceLocalIndices[0] +
702 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
703 _edgeFaceCountsAndOffsets[edgeIndex*2]);
704}
705
706inline void
707Level::resizeEdgeFaces(Index edgeIndex, int count) {
708 int* countOffsetPair = &_edgeFaceCountsAndOffsets[edgeIndex*2];
709
710 countOffsetPair[0] = count;
711 countOffsetPair[1] = (edgeIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
712
713 _maxEdgeFaces = std::max(_maxEdgeFaces, count);
714}
715inline void
716Level::trimEdgeFaces(Index edgeIndex, int count) {
717 _edgeFaceCountsAndOffsets[edgeIndex*2] = count;
718}
719
720//
721// Access/modify sharpness values:
722//
723inline float
724Level::getEdgeSharpness(Index edgeIndex) const {
725 return _edgeSharpness[edgeIndex];
726}
727inline float&
728Level::getEdgeSharpness(Index edgeIndex) {
729 return _edgeSharpness[edgeIndex];
730}
731
732inline float
733Level::getVertexSharpness(Index vertIndex) const {
734 return _vertSharpness[vertIndex];
735}
736inline float&
737Level::getVertexSharpness(Index vertIndex) {
738 return _vertSharpness[vertIndex];
739}
740
742Level::getVertexRule(Index vertIndex) const {
743 return (Sdc::Crease::Rule) _vertTags[vertIndex]._rule;
744}
745
746//
747// Access/modify hole tag:
748//
749inline void
750Level::setFaceHole(Index faceIndex, bool b) {
751 _faceTags[faceIndex]._hole = b;
752}
753inline bool
754Level::isFaceHole(Index faceIndex) const {
755 return _faceTags[faceIndex]._hole;
756}
757
758//
759// Access/modify non-manifold tags:
760//
761inline void
762Level::setEdgeNonManifold(Index edgeIndex, bool b) {
763 _edgeTags[edgeIndex]._nonManifold = b;
764}
765inline bool
766Level::isEdgeNonManifold(Index edgeIndex) const {
767 return _edgeTags[edgeIndex]._nonManifold;
768}
769
770inline void
771Level::setVertexNonManifold(Index vertIndex, bool b) {
772 _vertTags[vertIndex]._nonManifold = b;
773}
774inline bool
775Level::isVertexNonManifold(Index vertIndex) const {
776 return _vertTags[vertIndex]._nonManifold;
777}
778
779//
780// Sizing methods to allocate space:
781//
782inline void
783Level::resizeFaces(int faceCount) {
784 _faceCount = faceCount;
785 _faceVertCountsAndOffsets.resize(2 * faceCount);
786
787 _faceTags.resize(faceCount);
788 std::memset((void*) &_faceTags[0], 0, _faceCount * sizeof(FTag));
789}
790inline void
791Level::resizeFaceVertices(int totalFaceVertCount) {
792 _faceVertIndices.resize(totalFaceVertCount);
793}
794inline void
795Level::resizeFaceEdges(int totalFaceEdgeCount) {
796 _faceEdgeIndices.resize(totalFaceEdgeCount);
797}
798
799inline void
800Level::resizeEdges(int edgeCount) {
801
802 _edgeCount = edgeCount;
803 _edgeFaceCountsAndOffsets.resize(2 * edgeCount);
804
805 _edgeSharpness.resize(edgeCount);
806 _edgeTags.resize(edgeCount);
807
808 if (edgeCount>0) {
809 std::memset((void*) &_edgeTags[0], 0, _edgeCount * sizeof(ETag));
810 }
811}
812inline void
813Level::resizeEdgeVertices() {
814
815 _edgeVertIndices.resize(2 * _edgeCount);
816}
817inline void
818Level::resizeEdgeFaces(int totalEdgeFaceCount) {
819
820 _edgeFaceIndices.resize(totalEdgeFaceCount);
821 _edgeFaceLocalIndices.resize(totalEdgeFaceCount);
822}
823
824inline void
825Level::resizeVertices(int vertCount) {
826
827 _vertCount = vertCount;
828 _vertFaceCountsAndOffsets.resize(2 * vertCount);
829 _vertEdgeCountsAndOffsets.resize(2 * vertCount);
830
831 _vertSharpness.resize(vertCount);
832 _vertTags.resize(vertCount);
833 std::memset((void*) &_vertTags[0], 0, _vertCount * sizeof(VTag));
834}
835inline void
836Level::resizeVertexFaces(int totalVertFaceCount) {
837
838 _vertFaceIndices.resize(totalVertFaceCount);
839 _vertFaceLocalIndices.resize(totalVertFaceCount);
840}
841inline void
842Level::resizeVertexEdges(int totalVertEdgeCount) {
843
844 _vertEdgeIndices.resize(totalVertEdgeCount);
845 _vertEdgeLocalIndices.resize(totalVertEdgeCount);
846}
847
848inline IndexArray
849Level::shareFaceVertCountsAndOffsets() const {
850 // XXXX manuelk we have to force const casting here (classes don't 'share'
851 // members usually...)
852 return IndexArray(const_cast<Index *>(&_faceVertCountsAndOffsets[0]),
853 (int)_faceVertCountsAndOffsets.size());
854}
855
856} // end namespace internal
857} // end namespace Vtr
858
859} // end namespace OPENSUBDIV_VERSION
860using namespace OPENSUBDIV_VERSION;
861} // end namespace OpenSubdiv
862
863#endif /* OPENSUBDIV3_VTR_LEVEL_H */
ConstArray< LocalIndex > ConstLocalIndexArray
Definition types.h:66
Array< LocalIndex > LocalIndexArray
Definition types.h:65
ConstArray< Index > ConstIndexArray
Definition types.h:63