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