| OpenSubdiv

Loading...
Searching...
No Matches
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 bool testVertexNonManifoldCrease(Index vIndex) const;
476 void populateLocalIndices();
477
478 IndexArray shareFaceVertCountsAndOffsets() const;
479
480 private:
481 // Refinement classes (including all subclasses) build a Level:
482 friend class Refinement;
483 friend class TriRefinement;
484 friend class QuadRefinement;
485
486 //
487 // A Level is independent of subdivision scheme or options. While it may have been
488 // affected by them in its construction, they are not associated with it -- a Level
489 // is pure topology and any subdivision parameters are external.
490 //
491
492 // Simple members for inventory, etc.
493 int _faceCount;
494 int _edgeCount;
495 int _vertCount;
496
497 // The "depth" member is clearly useful in both the topological splitting and the
498 // stencil queries, but arguably it ties the Level to a hierarchy which counters
499 // the idea of it being independent.
500 int _depth;
501
502 // Maxima to help clients manage sizing of data buffers. Given "max valence",
503 // the "max edge faces" is strictly redundant as it will always be less, but
504 // since it will typically be so much less (i.e. 2) it is kept for now.
505 int _maxEdgeFaces;
506 int _maxValence;
507
508 //
509 // Topology vectors:
510 // Note that of all of these, only data for the face-edge relation is not
511 // stored in the osd::FarTables in any form. The FarTable vectors combine
512 // the edge-vert and edge-face relations. The eventual goal is that this
513 // data be part of the osd::Far classes and be a superset of the FarTable
514 // vectors, i.e. no data duplication or conversion. The fact that FarTable
515 // already stores 5 of the 6 possible relations should make the topology
516 // storage as a whole a non-issue.
517 //
518 // The vert-face-child and vert-edge-child indices are also arguably not
519 // a topology relation but more one for parent/child relations. But it is
520 // a topological relationship, and if named differently would not likely
521 // raise this. It has been named with "child" in the name as it does play
522 // a more significant role during subdivision in mapping between parent
523 // and child components, and so has been named to reflect that more clearly.
524 //
525
526 // Per-face:
527 std::vector<Index> _faceVertCountsAndOffsets; // 2 per face, redundant after level 0
528 std::vector<Index> _faceVertIndices; // 3 or 4 per face, variable at level 0
529 std::vector<Index> _faceEdgeIndices; // matches face-vert indices
530 std::vector<FTag> _faceTags; // 1 per face: includes "hole" tag
531
532 // Per-edge:
533 std::vector<Index> _edgeVertIndices; // 2 per edge
534 std::vector<Index> _edgeFaceCountsAndOffsets; // 2 per edge
535 std::vector<Index> _edgeFaceIndices; // varies with faces per edge
536 std::vector<LocalIndex> _edgeFaceLocalIndices; // varies with faces per edge
537
538 std::vector<float> _edgeSharpness; // 1 per edge
539 std::vector<ETag> _edgeTags; // 1 per edge: manifold, boundary, etc.
540
541 // Per-vertex:
542 std::vector<Index> _vertFaceCountsAndOffsets; // 2 per vertex
543 std::vector<Index> _vertFaceIndices; // varies with valence
544 std::vector<LocalIndex> _vertFaceLocalIndices; // varies with valence, 8-bit for now
545
546 std::vector<Index> _vertEdgeCountsAndOffsets; // 2 per vertex
547 std::vector<Index> _vertEdgeIndices; // varies with valence
548 std::vector<LocalIndex> _vertEdgeLocalIndices; // varies with valence, 8-bit for now
549
550 std::vector<float> _vertSharpness; // 1 per vertex
551 std::vector<VTag> _vertTags; // 1 per vertex: manifold, Sdc::Rule, etc.
552
553 // Face-varying channels:
554 std::vector<FVarLevel*> _fvarChannels;
555};
556
557//
558// Access/modify the vertices incident a given face:
559//
560 inline ConstIndexArray
561Level::getFaceVertices(Index faceIndex) const {
562 return ConstIndexArray(&_faceVertIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
563 _faceVertCountsAndOffsets[faceIndex*2]);
564}
565 inline IndexArray
566Level::getFaceVertices(Index faceIndex) {
567 return IndexArray(&_faceVertIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
568 _faceVertCountsAndOffsets[faceIndex*2]);
569}
570
571 inline void
572Level::resizeFaceVertices(Index faceIndex, int count) {
573
574 int* countOffsetPair = &_faceVertCountsAndOffsets[faceIndex*2];
575
576 countOffsetPair[0] = count;
577 countOffsetPair[1] = (faceIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
578
579 _maxValence = std::max(_maxValence, count);
580}
581
582 inline ConstIndexArray
583Level::getFaceVertices() const {
584 return ConstIndexArray(&_faceVertIndices[0], (int)_faceVertIndices.size());
585}
586
587//
588// Access/modify the edges incident a given face:
589//
590 inline ConstIndexArray
591Level::getFaceEdges(Index faceIndex) const {
592 return ConstIndexArray(&_faceEdgeIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
593 _faceVertCountsAndOffsets[faceIndex*2]);
594}
595 inline IndexArray
596Level::getFaceEdges(Index faceIndex) {
597 return IndexArray(&_faceEdgeIndices[_faceVertCountsAndOffsets[faceIndex*2+1]],
598 _faceVertCountsAndOffsets[faceIndex*2]);
599}
600
601//
602// Access/modify the faces incident a given vertex:
603//
604 inline ConstIndexArray
605Level::getVertexFaces(Index vertIndex) const {
606 return ConstIndexArray( (&_vertFaceIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
607 _vertFaceCountsAndOffsets[vertIndex*2]);
608}
609 inline IndexArray
610Level::getVertexFaces(Index vertIndex) {
611 return IndexArray( (&_vertFaceIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
612 _vertFaceCountsAndOffsets[vertIndex*2]);
613}
614
615 inline ConstLocalIndexArray
616Level::getVertexFaceLocalIndices(Index vertIndex) const {
617 return ConstLocalIndexArray( (&_vertFaceLocalIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
618 _vertFaceCountsAndOffsets[vertIndex*2]);
619}
620 inline LocalIndexArray
621Level::getVertexFaceLocalIndices(Index vertIndex) {
622 return LocalIndexArray( (&_vertFaceLocalIndices[0]) + _vertFaceCountsAndOffsets[vertIndex*2+1],
623 _vertFaceCountsAndOffsets[vertIndex*2]);
624}
625
626 inline void
627Level::resizeVertexFaces(Index vertIndex, int count) {
628 int* countOffsetPair = &_vertFaceCountsAndOffsets[vertIndex*2];
629
630 countOffsetPair[0] = count;
631 countOffsetPair[1] = (vertIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
632}
633 inline void
634Level::trimVertexFaces(Index vertIndex, int count) {
635 _vertFaceCountsAndOffsets[vertIndex*2] = count;
636}
637
638//
639// Access/modify the edges incident a given vertex:
640//
641 inline ConstIndexArray
642Level::getVertexEdges(Index vertIndex) const {
643 return ConstIndexArray( (&_vertEdgeIndices[0]) +_vertEdgeCountsAndOffsets[vertIndex*2+1],
644 _vertEdgeCountsAndOffsets[vertIndex*2]);
645}
646 inline IndexArray
647Level::getVertexEdges(Index vertIndex) {
648 return IndexArray( (&_vertEdgeIndices[0]) +_vertEdgeCountsAndOffsets[vertIndex*2+1],
649 _vertEdgeCountsAndOffsets[vertIndex*2]);
650}
651
652 inline ConstLocalIndexArray
653Level::getVertexEdgeLocalIndices(Index vertIndex) const {
654 return ConstLocalIndexArray( (&_vertEdgeLocalIndices[0]) + _vertEdgeCountsAndOffsets[vertIndex*2+1],
655 _vertEdgeCountsAndOffsets[vertIndex*2]);
656}
657 inline LocalIndexArray
658Level::getVertexEdgeLocalIndices(Index vertIndex) {
659 return LocalIndexArray( (&_vertEdgeLocalIndices[0]) + _vertEdgeCountsAndOffsets[vertIndex*2+1],
660 _vertEdgeCountsAndOffsets[vertIndex*2]);
661}
662
663 inline void
664Level::resizeVertexEdges(Index vertIndex, int count) {
665 int* countOffsetPair = &_vertEdgeCountsAndOffsets[vertIndex*2];
666
667 countOffsetPair[0] = count;
668 countOffsetPair[1] = (vertIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
669
670 _maxValence = std::max(_maxValence, count);
671}
672 inline void
673Level::trimVertexEdges(Index vertIndex, int count) {
674 _vertEdgeCountsAndOffsets[vertIndex*2] = count;
675}
676
677 inline void
678Level::setMaxValence(int valence) {
679 _maxValence = valence;
680}
681
682//
683// Access/modify the vertices incident a given edge:
684//
685 inline ConstIndexArray
686Level::getEdgeVertices(Index edgeIndex) const {
687 return ConstIndexArray(&_edgeVertIndices[edgeIndex*2], 2);
688}
689 inline IndexArray
690Level::getEdgeVertices(Index edgeIndex) {
691 return IndexArray(&_edgeVertIndices[edgeIndex*2], 2);
692}
693
694//
695// Access/modify the faces incident a given edge:
696//
697 inline ConstIndexArray
698Level::getEdgeFaces(Index edgeIndex) const {
699 return ConstIndexArray(&_edgeFaceIndices[0] +
700 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
701 _edgeFaceCountsAndOffsets[edgeIndex*2]);
702}
703 inline IndexArray
704Level::getEdgeFaces(Index edgeIndex) {
705 return IndexArray(&_edgeFaceIndices[0] +
706 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
707 _edgeFaceCountsAndOffsets[edgeIndex*2]);
708}
709
710 inline ConstLocalIndexArray
711Level::getEdgeFaceLocalIndices(Index edgeIndex) const {
712 return ConstLocalIndexArray(&_edgeFaceLocalIndices[0] +
713 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
714 _edgeFaceCountsAndOffsets[edgeIndex*2]);
715}
716 inline LocalIndexArray
717Level::getEdgeFaceLocalIndices(Index edgeIndex) {
718 return LocalIndexArray(&_edgeFaceLocalIndices[0] +
719 _edgeFaceCountsAndOffsets[edgeIndex*2+1],
720 _edgeFaceCountsAndOffsets[edgeIndex*2]);
721}
722
723 inline void
724Level::resizeEdgeFaces(Index edgeIndex, int count) {
725 int* countOffsetPair = &_edgeFaceCountsAndOffsets[edgeIndex*2];
726
727 countOffsetPair[0] = count;
728 countOffsetPair[1] = (edgeIndex == 0) ? 0 : (countOffsetPair[-2] + countOffsetPair[-1]);
729
730 _maxEdgeFaces = std::max(_maxEdgeFaces, count);
731}
732 inline void
733Level::trimEdgeFaces(Index edgeIndex, int count) {
734 _edgeFaceCountsAndOffsets[edgeIndex*2] = count;
735}
736
737//
738// Access/modify sharpness values:
739//
740 inline float
741Level::getEdgeSharpness(Index edgeIndex) const {
742 return _edgeSharpness[edgeIndex];
743}
744 inline float&
745Level::getEdgeSharpness(Index edgeIndex) {
746 return _edgeSharpness[edgeIndex];
747}
748
749 inline float
750Level::getVertexSharpness(Index vertIndex) const {
751 return _vertSharpness[vertIndex];
752}
753 inline float&
754Level::getVertexSharpness(Index vertIndex) {
755 return _vertSharpness[vertIndex];
756}
757
758 inline Sdc::Crease::Rule
759Level::getVertexRule(Index vertIndex) const {
760 return (Sdc::Crease::Rule) _vertTags[vertIndex]._rule;
761}
762
763//
764// Access/modify hole tag:
765//
766 inline void
767Level::setFaceHole(Index faceIndex, bool b) {
768 _faceTags[faceIndex]._hole = b;
769}
770 inline bool
771Level::isFaceHole(Index faceIndex) const {
772 return _faceTags[faceIndex]._hole;
773}
774
775//
776// Access/modify non-manifold tags:
777//
778 inline void
779Level::setEdgeNonManifold(Index edgeIndex, bool b) {
780 _edgeTags[edgeIndex]._nonManifold = b;
781}
782 inline bool
783Level::isEdgeNonManifold(Index edgeIndex) const {
784 return _edgeTags[edgeIndex]._nonManifold;
785}
786
787 inline void
788Level::setVertexNonManifold(Index vertIndex, bool b) {
789 _vertTags[vertIndex]._nonManifold = b;
790}
791 inline bool
792Level::isVertexNonManifold(Index vertIndex) const {
793 return _vertTags[vertIndex]._nonManifold;
794}
795
796//
797// Sizing methods to allocate space:
798//
799 inline void
800Level::resizeFaces(int faceCount) {
801 _faceCount = faceCount;
802 _faceVertCountsAndOffsets.resize(2 * faceCount);
803
804 _faceTags.resize(faceCount);
805 std::memset((void*) &_faceTags[0], 0, _faceCount * sizeof(FTag));
806}
807 inline void
808Level::resizeFaceVertices(int totalFaceVertCount) {
809 _faceVertIndices.resize(totalFaceVertCount);
810}
811 inline void
812Level::resizeFaceEdges(int totalFaceEdgeCount) {
813 _faceEdgeIndices.resize(totalFaceEdgeCount);
814}
815
816 inline void
817Level::resizeEdges(int edgeCount) {
818
819 _edgeCount = edgeCount;
820 _edgeFaceCountsAndOffsets.resize(2 * edgeCount);
821
822 _edgeSharpness.resize(edgeCount);
823 _edgeTags.resize(edgeCount);
824
825 if (edgeCount>0) {
826 std::memset((void*) &_edgeTags[0], 0, _edgeCount * sizeof(ETag));
827 }
828}
829 inline void
830Level::resizeEdgeVertices() {
831
832 _edgeVertIndices.resize(2 * _edgeCount);
833}
834 inline void
835Level::resizeEdgeFaces(int totalEdgeFaceCount) {
836
837 _edgeFaceIndices.resize(totalEdgeFaceCount);
838 _edgeFaceLocalIndices.resize(totalEdgeFaceCount);
839}
840
841 inline void
842Level::resizeVertices(int vertCount) {
843
844 _vertCount = vertCount;
845 _vertFaceCountsAndOffsets.resize(2 * vertCount);
846 _vertEdgeCountsAndOffsets.resize(2 * vertCount);
847
848 _vertSharpness.resize(vertCount);
849 _vertTags.resize(vertCount);
850 std::memset((void*) &_vertTags[0], 0, _vertCount * sizeof(VTag));
851}
852 inline void
853Level::resizeVertexFaces(int totalVertFaceCount) {
854
855 _vertFaceIndices.resize(totalVertFaceCount);
856 _vertFaceLocalIndices.resize(totalVertFaceCount);
857}
858 inline void
859Level::resizeVertexEdges(int totalVertEdgeCount) {
860
861 _vertEdgeIndices.resize(totalVertEdgeCount);
862 _vertEdgeLocalIndices.resize(totalVertEdgeCount);
863}
864
865 inline IndexArray
866Level::shareFaceVertCountsAndOffsets() const {
867 // XXXX manuelk we have to force const casting here (classes don't 'share'
868 // members usually...)
869 return IndexArray(const_cast<Index *>(&_faceVertCountsAndOffsets[0]),
870 (int)_faceVertCountsAndOffsets.size());
871}
872
873} // end namespace internal
874} // end namespace Vtr
875
876} // end namespace OPENSUBDIV_VERSION
877 using namespace OPENSUBDIV_VERSION;
878} // end namespace OpenSubdiv
879
880#endif /* OPENSUBDIV3_VTR_LEVEL_H */
options.h
crease.h
OpenSubdiv
Definition limits.h:32
OpenSubdiv::OPENSUBDIV_VERSION
Definition limits.h:33
OpenSubdiv::OPENSUBDIV_VERSION::Vtr
Definition topologyRefiner.h:40
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::ConstLocalIndexArray
ConstArray< LocalIndex > ConstLocalIndexArray
Definition types.h:83
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::LocalIndexArray
Array< LocalIndex > LocalIndexArray
Definition types.h:82
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::Index
int Index
Definition types.h:54
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::ConstIndexArray
ConstArray< Index > ConstIndexArray
Definition types.h:80
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::LocalIndex
unsigned short LocalIndex
Definition types.h:66
OpenSubdiv::OPENSUBDIV_VERSION::Vtr::IndexArray
Array< Index > IndexArray
Definition types.h:79
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Crease::Rule
Rule
Definition crease.h:82
types.h
types.h