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