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 {
VTagVTag98         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.
clearVTag103         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:
VTagVTag129         explicit VTag(VTagSize bits) {
130             std::memcpy(this, &bits, sizeof(bits));
131         }
getBitsVTag132         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 {
ETagETag141         ETag() { }
142 
143         //  When cleared, the ETag represents a smooth, manifold, interior edge
clearETag144         void clear() { std::memset(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:
ETagETag154         explicit ETag(ETagSize bits) {
155             std::memcpy(this, &bits, sizeof(bits));
156         }
getBitsETag157         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 {
FTagFTag166         FTag() { }
167 
clearFTag168         void clear() { std::memset(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 {
VSpanVSpan194         VSpan() { std::memset(this, 0, sizeof(VSpan)); }
195 
clearVSpan196         void clear()            { std::memset(this, 0, sizeof(VSpan)); }
isAssignedVSpan197         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:
getDepth()212     int getDepth() const { return _depth; }
213 
getNumVertices()214     int getNumVertices() const { return _vertCount; }
getNumFaces()215     int getNumFaces() const    { return _faceCount; }
getNumEdges()216     int getNumEdges() const    { return _edgeCount; }
217 
218     //  More global sizes may prove useful...
getNumFaceVerticesTotal()219     int getNumFaceVerticesTotal() const { return (int) _faceVertIndices.size(); }
getNumFaceEdgesTotal()220     int getNumFaceEdgesTotal() const    { return (int) _faceEdgeIndices.size(); }
getNumEdgeVerticesTotal()221     int getNumEdgeVerticesTotal() const { return (int) _edgeVertIndices.size(); }
getNumEdgeFacesTotal()222     int getNumEdgeFacesTotal() const    { return (int) _edgeFaceIndices.size(); }
getNumVertexFacesTotal()223     int getNumVertexFacesTotal() const  { return (int) _vertFaceIndices.size(); }
getNumVertexEdgesTotal()224     int getNumVertexEdgesTotal() const  { return (int) _vertEdgeIndices.size(); }
225 
getMaxValence()226     int getMaxValence() const { return _maxValence; }
getMaxEdgeFaces()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;
getNumFVarChannels()264     int getNumFVarChannels() const { return (int) _fvarChannels.size(); }
265     int getNumFVarValues(int channel) const;
266     ConstIndexArray getFaceFVarValues(Index faceIndex, int channel) const;
267 
getFVarLevel(int channel)268     FVarLevel & getFVarLevel(int channel) { return *_fvarChannels[channel]; }
getFVarLevel(int 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:
getVertexTag(Index vertIndex)279     VTag const & getVertexTag(Index vertIndex) const { return _vertTags[vertIndex]; }
getEdgeTag(Index edgeIndex)280     ETag const & getEdgeTag(Index edgeIndex) const { return _edgeTags[edgeIndex]; }
getFaceTag(Index faceIndex)281     FTag const & getFaceTag(Index faceIndex) const { return _faceTags[faceIndex]; }
282 
getVertexTag(Index vertIndex)283     VTag & getVertexTag(Index vertIndex) { return _vertTags[vertIndex]; }
getEdgeTag(Index edgeIndex)284     ETag & getEdgeTag(Index edgeIndex) { return _edgeTags[edgeIndex]; }
getFaceTag(Index faceIndex)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...
getNumFaceVertices(Index faceIndex)419     int getNumFaceVertices(     Index faceIndex) const { return _faceVertCountsAndOffsets[2*faceIndex]; }
getOffsetOfFaceVertices(Index faceIndex)420     int getOffsetOfFaceVertices(Index faceIndex) const { return _faceVertCountsAndOffsets[2*faceIndex + 1]; }
421 
getNumFaceEdges(Index faceIndex)422     int getNumFaceEdges(     Index faceIndex) const { return getNumFaceVertices(faceIndex); }
getOffsetOfFaceEdges(Index faceIndex)423     int getOffsetOfFaceEdges(Index faceIndex) const { return getOffsetOfFaceVertices(faceIndex); }
424 
getNumEdgeVertices(Index)425     int getNumEdgeVertices(     Index )          const { return 2; }
getOffsetOfEdgeVertices(Index edgeIndex)426     int getOffsetOfEdgeVertices(Index edgeIndex) const { return 2 * edgeIndex; }
427 
getNumEdgeFaces(Index edgeIndex)428     int getNumEdgeFaces(     Index edgeIndex) const { return _edgeFaceCountsAndOffsets[2*edgeIndex]; }
getOffsetOfEdgeFaces(Index edgeIndex)429     int getOffsetOfEdgeFaces(Index edgeIndex) const { return _edgeFaceCountsAndOffsets[2*edgeIndex + 1]; }
430 
getNumVertexFaces(Index vertIndex)431     int getNumVertexFaces(     Index vertIndex) const { return _vertFaceCountsAndOffsets[2*vertIndex]; }
getOffsetOfVertexFaces(Index vertIndex)432     int getOffsetOfVertexFaces(Index vertIndex) const { return _vertFaceCountsAndOffsets[2*vertIndex + 1]; }
433 
getNumVertexEdges(Index vertIndex)434     int getNumVertexEdges(     Index vertIndex) const { return _vertEdgeCountsAndOffsets[2*vertIndex]; }
getOffsetOfVertexEdges(Index 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
getFaceVertices(Index faceIndex)560 Level::getFaceVertices(Index faceIndex) const {
561     return ConstIndexArray(&_faceVertIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
562                           _faceVertCountsAndOffsets[faceIndex*2]);
563 }
564 inline IndexArray
getFaceVertices(Index faceIndex)565 Level::getFaceVertices(Index faceIndex) {
566     return IndexArray(&_faceVertIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
567                           _faceVertCountsAndOffsets[faceIndex*2]);
568 }
569 
570 inline void
resizeFaceVertices(Index faceIndex,int count)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
getFaceVertices()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
getFaceEdges(Index faceIndex)590 Level::getFaceEdges(Index faceIndex) const {
591     return ConstIndexArray(&_faceEdgeIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
592                           _faceVertCountsAndOffsets[faceIndex*2]);
593 }
594 inline IndexArray
getFaceEdges(Index faceIndex)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
getVertexFaces(Index vertIndex)604 Level::getVertexFaces(Index vertIndex) const {
605     return ConstIndexArray( (&_vertFaceIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
606                           _vertFaceCountsAndOffsets[vertIndex*2]);
607 }
608 inline IndexArray
getVertexFaces(Index vertIndex)609 Level::getVertexFaces(Index vertIndex) {
610     return IndexArray( (&_vertFaceIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
611                           _vertFaceCountsAndOffsets[vertIndex*2]);
612 }
613 
614 inline ConstLocalIndexArray
getVertexFaceLocalIndices(Index vertIndex)615 Level::getVertexFaceLocalIndices(Index vertIndex) const {
616     return ConstLocalIndexArray( (&_vertFaceLocalIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
617                                _vertFaceCountsAndOffsets[vertIndex*2]);
618 }
619 inline LocalIndexArray
getVertexFaceLocalIndices(Index vertIndex)620 Level::getVertexFaceLocalIndices(Index vertIndex) {
621     return LocalIndexArray( (&_vertFaceLocalIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
622                                _vertFaceCountsAndOffsets[vertIndex*2]);
623 }
624 
625 inline void
resizeVertexFaces(Index vertIndex,int count)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
trimVertexFaces(Index vertIndex,int count)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
getVertexEdges(Index vertIndex)641 Level::getVertexEdges(Index vertIndex) const {
642     return ConstIndexArray( (&_vertEdgeIndices[0]) +_vertEdgeCountsAndOffsets[vertIndex*2+1],
643                           _vertEdgeCountsAndOffsets[vertIndex*2]);
644 }
645 inline IndexArray
getVertexEdges(Index vertIndex)646 Level::getVertexEdges(Index vertIndex) {
647     return IndexArray( (&_vertEdgeIndices[0]) +_vertEdgeCountsAndOffsets[vertIndex*2+1],
648                           _vertEdgeCountsAndOffsets[vertIndex*2]);
649 }
650 
651 inline ConstLocalIndexArray
getVertexEdgeLocalIndices(Index vertIndex)652 Level::getVertexEdgeLocalIndices(Index vertIndex) const {
653     return ConstLocalIndexArray( (&_vertEdgeLocalIndices[0]) + _vertEdgeCountsAndOffsets[vertIndex*2+1],
654                                _vertEdgeCountsAndOffsets[vertIndex*2]);
655 }
656 inline LocalIndexArray
getVertexEdgeLocalIndices(Index vertIndex)657 Level::getVertexEdgeLocalIndices(Index vertIndex) {
658     return LocalIndexArray( (&_vertEdgeLocalIndices[0]) + _vertEdgeCountsAndOffsets[vertIndex*2+1],
659                                _vertEdgeCountsAndOffsets[vertIndex*2]);
660 }
661 
662 inline void
resizeVertexEdges(Index vertIndex,int count)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
trimVertexEdges(Index vertIndex,int count)672 Level::trimVertexEdges(Index vertIndex, int count) {
673     _vertEdgeCountsAndOffsets[vertIndex*2] = count;
674 }
675 
676 inline void
setMaxValence(int valence)677 Level::setMaxValence(int valence) {
678     _maxValence = valence;
679 }
680 
681 //
682 //  Access/modify the vertices incident a given edge:
683 //
684 inline ConstIndexArray
getEdgeVertices(Index edgeIndex)685 Level::getEdgeVertices(Index edgeIndex) const {
686     return ConstIndexArray(&_edgeVertIndices[edgeIndex*2], 2);
687 }
688 inline IndexArray
getEdgeVertices(Index edgeIndex)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
getEdgeFaces(Index edgeIndex)697 Level::getEdgeFaces(Index edgeIndex) const {
698     return ConstIndexArray(&_edgeFaceIndices[0] +
699                            _edgeFaceCountsAndOffsets[edgeIndex*2+1],
700                            _edgeFaceCountsAndOffsets[edgeIndex*2]);
701 }
702 inline IndexArray
getEdgeFaces(Index edgeIndex)703 Level::getEdgeFaces(Index edgeIndex) {
704     return IndexArray(&_edgeFaceIndices[0] +
705                       _edgeFaceCountsAndOffsets[edgeIndex*2+1],
706                       _edgeFaceCountsAndOffsets[edgeIndex*2]);
707 }
708 
709 inline ConstLocalIndexArray
getEdgeFaceLocalIndices(Index edgeIndex)710 Level::getEdgeFaceLocalIndices(Index edgeIndex) const {
711     return ConstLocalIndexArray(&_edgeFaceLocalIndices[0] +
712                                 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
713                                 _edgeFaceCountsAndOffsets[edgeIndex*2]);
714 }
715 inline LocalIndexArray
getEdgeFaceLocalIndices(Index edgeIndex)716 Level::getEdgeFaceLocalIndices(Index edgeIndex) {
717     return LocalIndexArray(&_edgeFaceLocalIndices[0] +
718                            _edgeFaceCountsAndOffsets[edgeIndex*2+1],
719                            _edgeFaceCountsAndOffsets[edgeIndex*2]);
720 }
721 
722 inline void
resizeEdgeFaces(Index edgeIndex,int count)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
trimEdgeFaces(Index edgeIndex,int count)732 Level::trimEdgeFaces(Index edgeIndex, int count) {
733     _edgeFaceCountsAndOffsets[edgeIndex*2] = count;
734 }
735 
736 //
737 //  Access/modify sharpness values:
738 //
739 inline float
getEdgeSharpness(Index edgeIndex)740 Level::getEdgeSharpness(Index edgeIndex) const {
741     return _edgeSharpness[edgeIndex];
742 }
743 inline float&
getEdgeSharpness(Index edgeIndex)744 Level::getEdgeSharpness(Index edgeIndex) {
745     return _edgeSharpness[edgeIndex];
746 }
747 
748 inline float
getVertexSharpness(Index vertIndex)749 Level::getVertexSharpness(Index vertIndex) const {
750     return _vertSharpness[vertIndex];
751 }
752 inline float&
getVertexSharpness(Index vertIndex)753 Level::getVertexSharpness(Index vertIndex) {
754     return _vertSharpness[vertIndex];
755 }
756 
757 inline Sdc::Crease::Rule
getVertexRule(Index vertIndex)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
setFaceHole(Index faceIndex,bool b)766 Level::setFaceHole(Index faceIndex, bool b) {
767     _faceTags[faceIndex]._hole = b;
768 }
769 inline bool
isFaceHole(Index faceIndex)770 Level::isFaceHole(Index faceIndex) const {
771     return _faceTags[faceIndex]._hole;
772 }
773 
774 //
775 //  Access/modify non-manifold tags:
776 //
777 inline void
setEdgeNonManifold(Index edgeIndex,bool b)778 Level::setEdgeNonManifold(Index edgeIndex, bool b) {
779     _edgeTags[edgeIndex]._nonManifold = b;
780 }
781 inline bool
isEdgeNonManifold(Index edgeIndex)782 Level::isEdgeNonManifold(Index edgeIndex) const {
783     return _edgeTags[edgeIndex]._nonManifold;
784 }
785 
786 inline void
setVertexNonManifold(Index vertIndex,bool b)787 Level::setVertexNonManifold(Index vertIndex, bool b) {
788     _vertTags[vertIndex]._nonManifold = b;
789 }
790 inline bool
isVertexNonManifold(Index vertIndex)791 Level::isVertexNonManifold(Index vertIndex) const {
792     return _vertTags[vertIndex]._nonManifold;
793 }
794 
795 //
796 //  Sizing methods to allocate space:
797 //
798 inline void
resizeFaces(int faceCount)799 Level::resizeFaces(int faceCount) {
800     _faceCount = faceCount;
801     _faceVertCountsAndOffsets.resize(2 * faceCount);
802 
803     _faceTags.resize(faceCount);
804     std::memset(&_faceTags[0], 0, _faceCount * sizeof(FTag));
805 }
806 inline void
resizeFaceVertices(int totalFaceVertCount)807 Level::resizeFaceVertices(int totalFaceVertCount) {
808     _faceVertIndices.resize(totalFaceVertCount);
809 }
810 inline void
resizeFaceEdges(int totalFaceEdgeCount)811 Level::resizeFaceEdges(int totalFaceEdgeCount) {
812     _faceEdgeIndices.resize(totalFaceEdgeCount);
813 }
814 
815 inline void
resizeEdges(int edgeCount)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(&_edgeTags[0], 0, _edgeCount * sizeof(ETag));
826     }
827 }
828 inline void
resizeEdgeVertices()829 Level::resizeEdgeVertices() {
830 
831     _edgeVertIndices.resize(2 * _edgeCount);
832 }
833 inline void
resizeEdgeFaces(int totalEdgeFaceCount)834 Level::resizeEdgeFaces(int totalEdgeFaceCount) {
835 
836     _edgeFaceIndices.resize(totalEdgeFaceCount);
837     _edgeFaceLocalIndices.resize(totalEdgeFaceCount);
838 }
839 
840 inline void
resizeVertices(int vertCount)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(&_vertTags[0], 0, _vertCount * sizeof(VTag));
850 }
851 inline void
resizeVertexFaces(int totalVertFaceCount)852 Level::resizeVertexFaces(int totalVertFaceCount) {
853 
854     _vertFaceIndices.resize(totalVertFaceCount);
855     _vertFaceLocalIndices.resize(totalVertFaceCount);
856 }
857 inline void
resizeVertexEdges(int totalVertEdgeCount)858 Level::resizeVertexEdges(int totalVertEdgeCount) {
859 
860     _vertEdgeIndices.resize(totalVertEdgeCount);
861     _vertEdgeLocalIndices.resize(totalVertEdgeCount);
862 }
863 
864 inline IndexArray
shareFaceVertCountsAndOffsets()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 */
880