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