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