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 #include "../sdc/crease.h"
25 #include "../sdc/catmarkScheme.h"
26 #include "../sdc/bilinearScheme.h"
27 #include "../vtr/types.h"
28 #include "../vtr/level.h"
29 #include "../vtr/refinement.h"
30 #include "../vtr/fvarLevel.h"
31 #include "../vtr/fvarRefinement.h"
32 #include "../vtr/stackBuffer.h"
33 
34 #include <cassert>
35 #include <cstdio>
36 #include <utility>
37 
38 
39 namespace OpenSubdiv {
40 namespace OPENSUBDIV_VERSION {
41 
42 namespace Vtr {
43 namespace internal {
44 
45 //
46 //  Simple constructor, destructor and basic initializers:
47 //
Refinement(Level const & parentArg,Level & childArg,Sdc::Options const & options)48 Refinement::Refinement(Level const & parentArg, Level & childArg, Sdc::Options const& options) :
49     _parent(&parentArg),
50     _child(&childArg),
51     _options(options),
52     _regFaceSize(-1),
53     _uniform(false),
54     _faceVertsFirst(false),
55     _childFaceFromFaceCount(0),
56     _childEdgeFromFaceCount(0),
57     _childEdgeFromEdgeCount(0),
58     _childVertFromFaceCount(0),
59     _childVertFromEdgeCount(0),
60     _childVertFromVertCount(0),
61     _firstChildFaceFromFace(0),
62     _firstChildEdgeFromFace(0),
63     _firstChildEdgeFromEdge(0),
64     _firstChildVertFromFace(0),
65     _firstChildVertFromEdge(0),
66     _firstChildVertFromVert(0) {
67 
68     assert((childArg.getDepth() == 0) && (childArg.getNumVertices() == 0));
69     childArg._depth = 1 + parentArg.getDepth();
70 }
71 
~Refinement()72 Refinement::~Refinement() {
73 
74     for (int i = 0; i < (int)_fvarChannels.size(); ++i) {
75         delete _fvarChannels[i];
76     }
77 }
78 
79 void
initializeChildComponentCounts()80 Refinement::initializeChildComponentCounts() {
81 
82     //
83     //  Assign the child's component counts/inventory based on the child components identified:
84     //
85     _child->_faceCount = _childFaceFromFaceCount;
86     _child->_edgeCount = _childEdgeFromFaceCount + _childEdgeFromEdgeCount;
87     _child->_vertCount = _childVertFromFaceCount + _childVertFromEdgeCount + _childVertFromVertCount;
88 }
89 
90 void
initializeSparseSelectionTags()91 Refinement::initializeSparseSelectionTags() {
92 
93     _parentFaceTag.resize(_parent->getNumFaces());
94     _parentEdgeTag.resize(_parent->getNumEdges());
95     _parentVertexTag.resize(_parent->getNumVertices());
96 }
97 
98 
99 //
100 //  The main refinement method -- provides a high-level overview of refinement:
101 //
102 //  The refinement process is as follows:
103 //      - determine a mapping from parent components to their potential child components
104 //          - for sparse refinement this mapping will be partial
105 //      - determine the reverse mapping from chosen child components back to their parents
106 //          - previously this was optional -- not strictly necessary and comes at added cost
107 //          - does simplify iteration of child components when refinement is sparse
108 //      - propagate/initialize component Tags from parents to their children
109 //          - knowing these Tags for a child component simplifies dealing with it later
110 //      - subdivide the topology, i.e. populate all topology relations for the child Level
111 //          - any subset of the 6 relations in a Level can be created
112 //          - using the minimum required in the last Level is very advantageous
113 //      - subdivide the sharpness values in the child Level
114 //      - subdivide face-varying channels in the child Level
115 //
116 void
refine(Options refineOptions)117 Refinement::refine(Options refineOptions) {
118 
119     //  This will become redundant when/if assigned on construction:
120     assert(_parent && _child);
121 
122     _uniform        = !refineOptions._sparse;
123     _faceVertsFirst =  refineOptions._faceVertsFirst;
124 
125     //  We may soon have an option here to suppress refinement of FVar channels...
126     bool refineOptions_ignoreFVarChannels = false;
127 
128     bool optionallyRefineFVar = (_parent->getNumFVarChannels() > 0) && !refineOptions_ignoreFVarChannels;
129 
130     //
131     //  Initialize the parent-to-child and reverse child-to-parent mappings and propagate
132     //  component tags to the new child components:
133     //
134     populateParentToChildMapping();
135 
136     initializeChildComponentCounts();
137 
138     populateChildToParentMapping();
139 
140     propagateComponentTags();
141 
142     //
143     //  Subdivide the topology -- populating only those of the 6 relations specified
144     //  (though we do require the vertex-face relation for refining FVar channels):
145     //
146     Relations relationsToPopulate;
147     if (refineOptions._minimalTopology) {
148         relationsToPopulate.setAll(false);
149         relationsToPopulate._faceVertices = true;
150     } else {
151         relationsToPopulate.setAll(true);
152     }
153     if (optionallyRefineFVar) {
154         relationsToPopulate._vertexFaces = true;
155     }
156 
157     subdivideTopology(relationsToPopulate);
158 
159     //
160     //  Subdivide the sharpness values and face-varying channels:
161     //    - note there is some dependency of the vertex tag/Rule for semi-sharp vertices
162     //
163     subdivideSharpnessValues();
164 
165     if (optionallyRefineFVar) {
166         subdivideFVarChannels();
167     }
168 
169     //  Various debugging support:
170     //
171     //printf("Vertex refinement to level %d completed...\n", _child->getDepth());
172     //_child->print();
173     //printf("  validating refinement to level %d...\n", _child->getDepth());
174     //_child->validateTopology();
175     //assert(_child->validateTopology());
176 }
177 
178 
179 //
180 //  Methods to construct the parent-to-child mapping
181 //
182 void
populateParentToChildMapping()183 Refinement::populateParentToChildMapping() {
184 
185     allocateParentChildIndices();
186 
187     //
188     //  If sparse refinement, mark indices of any components in addition to those selected
189     //  so that we have the full neighborhood for selected components:
190     //
191     if (!_uniform) {
192         //  Make sure the selection was non-empty -- currently unsupported...
193         if (_parentVertexTag.size() == 0) {
194             assert("Unsupported empty sparse refinement detected in Refinement" == 0);
195         }
196         markSparseChildComponentIndices();
197     }
198 
199     populateParentChildIndices();
200 }
201 
202 namespace {
isSparseIndexMarked(Index index)203     inline bool isSparseIndexMarked(Index index)   { return index != 0; }
204 
205     inline int
sequenceSparseIndexVector(IndexVector & indexVector,int baseValue=0)206     sequenceSparseIndexVector(IndexVector& indexVector, int baseValue = 0) {
207         int validCount = 0;
208         for (int i = 0; i < (int) indexVector.size(); ++i) {
209             indexVector[i] = isSparseIndexMarked(indexVector[i])
210                            ? (baseValue + validCount++) : INDEX_INVALID;
211         }
212         return validCount;
213     }
214 
215     inline int
sequenceFullIndexVector(IndexVector & indexVector,int baseValue=0)216     sequenceFullIndexVector(IndexVector& indexVector, int baseValue = 0) {
217         int indexCount = (int) indexVector.size();
218         for (int i = 0; i < indexCount; ++i) {
219             indexVector[i] = baseValue++;
220         }
221         return indexCount;
222     }
223 }
224 
225 void
populateParentChildIndices()226 Refinement::populateParentChildIndices() {
227 
228     //
229     //  Two vertex orderings are currently supported -- ordering vertices refined
230     //  from vertices first, or those refined from faces first.  It's possible this
231     //  may be extended to more possibilities.  Once the ordering is defined here,
232     //  other than analogous initialization in FVarRefinement, the treatment of
233     //  vertices in blocks based on origin should make the rest of the code
234     //  invariant to ordering changes.
235     //
236     //  These two blocks now differ only in the utility function that assigns the
237     //  sequential values to the index vectors -- so parameterization/simplification
238     //  is now possible...
239     //
240     if (_uniform) {
241         //  child faces:
242         _firstChildFaceFromFace = 0;
243         _childFaceFromFaceCount = sequenceFullIndexVector(_faceChildFaceIndices, _firstChildFaceFromFace);
244 
245         //  child edges:
246         _firstChildEdgeFromFace = 0;
247         _childEdgeFromFaceCount = sequenceFullIndexVector(_faceChildEdgeIndices, _firstChildEdgeFromFace);
248 
249         _firstChildEdgeFromEdge = _childEdgeFromFaceCount;
250         _childEdgeFromEdgeCount = sequenceFullIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge);
251 
252         //  child vertices:
253         if (_faceVertsFirst) {
254             _firstChildVertFromFace = 0;
255             _childVertFromFaceCount = sequenceFullIndexVector(_faceChildVertIndex, _firstChildVertFromFace);
256 
257             _firstChildVertFromEdge = _firstChildVertFromFace + _childVertFromFaceCount;
258             _childVertFromEdgeCount = sequenceFullIndexVector(_edgeChildVertIndex, _firstChildVertFromEdge);
259 
260             _firstChildVertFromVert = _firstChildVertFromEdge + _childVertFromEdgeCount;
261             _childVertFromVertCount = sequenceFullIndexVector(_vertChildVertIndex, _firstChildVertFromVert);
262         } else {
263             _firstChildVertFromVert = 0;
264             _childVertFromVertCount = sequenceFullIndexVector(_vertChildVertIndex, _firstChildVertFromVert);
265 
266             _firstChildVertFromFace = _firstChildVertFromVert + _childVertFromVertCount;
267             _childVertFromFaceCount = sequenceFullIndexVector(_faceChildVertIndex, _firstChildVertFromFace);
268 
269             _firstChildVertFromEdge = _firstChildVertFromFace + _childVertFromFaceCount;
270             _childVertFromEdgeCount = sequenceFullIndexVector(_edgeChildVertIndex, _firstChildVertFromEdge);
271         }
272     } else {
273         //  child faces:
274         _firstChildFaceFromFace = 0;
275         _childFaceFromFaceCount = sequenceSparseIndexVector(_faceChildFaceIndices, _firstChildFaceFromFace);
276 
277         //  child edges:
278         _firstChildEdgeFromFace = 0;
279         _childEdgeFromFaceCount = sequenceSparseIndexVector(_faceChildEdgeIndices, _firstChildEdgeFromFace);
280 
281         _firstChildEdgeFromEdge = _childEdgeFromFaceCount;
282         _childEdgeFromEdgeCount = sequenceSparseIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge);
283 
284         //  child vertices:
285         if (_faceVertsFirst) {
286             _firstChildVertFromFace = 0;
287             _childVertFromFaceCount = sequenceSparseIndexVector(_faceChildVertIndex, _firstChildVertFromFace);
288 
289             _firstChildVertFromEdge = _firstChildVertFromFace + _childVertFromFaceCount;
290             _childVertFromEdgeCount = sequenceSparseIndexVector(_edgeChildVertIndex, _firstChildVertFromEdge);
291 
292             _firstChildVertFromVert = _firstChildVertFromEdge + _childVertFromEdgeCount;
293             _childVertFromVertCount = sequenceSparseIndexVector(_vertChildVertIndex, _firstChildVertFromVert);
294         } else {
295             _firstChildVertFromVert = 0;
296             _childVertFromVertCount = sequenceSparseIndexVector(_vertChildVertIndex, _firstChildVertFromVert);
297 
298             _firstChildVertFromFace = _firstChildVertFromVert + _childVertFromVertCount;
299             _childVertFromFaceCount = sequenceSparseIndexVector(_faceChildVertIndex, _firstChildVertFromFace);
300 
301             _firstChildVertFromEdge = _firstChildVertFromFace + _childVertFromFaceCount;
302             _childVertFromEdgeCount = sequenceSparseIndexVector(_edgeChildVertIndex, _firstChildVertFromEdge);
303         }
304     }
305 }
306 
307 void
printParentToChildMapping() const308 Refinement::printParentToChildMapping() const {
309 
310     printf("Parent-to-child component mapping:\n");
311     for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
312         printf("  Face %d:\n", pFace);
313         printf("    Child vert:  %d\n", _faceChildVertIndex[pFace]);
314 
315         printf("    Child faces: ");
316         ConstIndexArray childFaces = getFaceChildFaces(pFace);
317         for (int i = 0; i < childFaces.size(); ++i) {
318             printf(" %d", childFaces[i]);
319         }
320         printf("\n");
321 
322         printf("    Child edges: ");
323         ConstIndexArray childEdges = getFaceChildEdges(pFace);
324         for (int i = 0; i < childEdges.size(); ++i) {
325             printf(" %d", childEdges[i]);
326         }
327         printf("\n");
328     }
329     for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
330         printf("  Edge %d:\n", pEdge);
331         printf("    Child vert:  %d\n", _edgeChildVertIndex[pEdge]);
332 
333         ConstIndexArray childEdges = getEdgeChildEdges(pEdge);
334         printf("    Child edges: %d %d\n", childEdges[0], childEdges[1]);
335     }
336     for (Index pVert = 0; pVert < _parent->getNumVertices(); ++pVert) {
337         printf("  Vert %d:\n", pVert);
338         printf("    Child vert:  %d\n", _vertChildVertIndex[pVert]);
339     }
340 }
341 
342 
343 //
344 //  Methods to construct the child-to-parent mapping:
345 //
346 void
populateChildToParentMapping()347 Refinement::populateChildToParentMapping() {
348 
349     ChildTag initialChildTags[2][4];
350     for (int i = 0; i < 2; ++i) {
351         for (int j = 0; j < 4; ++j) {
352             ChildTag & tag = initialChildTags[i][j];
353 
354             tag._incomplete    = (unsigned char)i;
355             tag._parentType    = 0;
356             tag._indexInParent = (unsigned char)j;
357         }
358     }
359 
360     populateFaceParentVectors(initialChildTags);
361     populateEdgeParentVectors(initialChildTags);
362     populateVertexParentVectors(initialChildTags);
363 }
364 
365 void
populateFaceParentVectors(ChildTag const initialChildTags[2][4])366 Refinement::populateFaceParentVectors(ChildTag const initialChildTags[2][4]) {
367 
368     _childFaceTag.resize(_child->getNumFaces());
369     _childFaceParentIndex.resize(_child->getNumFaces());
370 
371     populateFaceParentFromParentFaces(initialChildTags);
372 }
373 void
populateFaceParentFromParentFaces(ChildTag const initialChildTags[2][4])374 Refinement::populateFaceParentFromParentFaces(ChildTag const initialChildTags[2][4]) {
375 
376     if (_uniform) {
377         Index cFace = getFirstChildFaceFromFaces();
378         for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
379             ConstIndexArray cFaces = getFaceChildFaces(pFace);
380             if (cFaces.size() == 4) {
381                 _childFaceTag[cFace + 0] = initialChildTags[0][0];
382                 _childFaceTag[cFace + 1] = initialChildTags[0][1];
383                 _childFaceTag[cFace + 2] = initialChildTags[0][2];
384                 _childFaceTag[cFace + 3] = initialChildTags[0][3];
385 
386                 _childFaceParentIndex[cFace + 0] = pFace;
387                 _childFaceParentIndex[cFace + 1] = pFace;
388                 _childFaceParentIndex[cFace + 2] = pFace;
389                 _childFaceParentIndex[cFace + 3] = pFace;
390 
391                 cFace += 4;
392             } else {
393                 bool childTooLarge = (cFaces.size() > 4);
394                 for (int i = 0; i < cFaces.size(); ++i, ++cFace) {
395                     _childFaceTag[cFace] = initialChildTags[0][childTooLarge ? 0 : i];
396                     _childFaceParentIndex[cFace] = pFace;
397                 }
398             }
399         }
400     } else {
401         //  Child faces of faces:
402         for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
403             bool incomplete = !_parentFaceTag[pFace]._selected;
404 
405             IndexArray cFaces = getFaceChildFaces(pFace);
406             if (!incomplete && (cFaces.size() == 4)) {
407                 _childFaceTag[cFaces[0]] = initialChildTags[0][0];
408                 _childFaceTag[cFaces[1]] = initialChildTags[0][1];
409                 _childFaceTag[cFaces[2]] = initialChildTags[0][2];
410                 _childFaceTag[cFaces[3]] = initialChildTags[0][3];
411 
412                 _childFaceParentIndex[cFaces[0]] = pFace;
413                 _childFaceParentIndex[cFaces[1]] = pFace;
414                 _childFaceParentIndex[cFaces[2]] = pFace;
415                 _childFaceParentIndex[cFaces[3]] = pFace;
416             } else {
417                 bool childTooLarge = (cFaces.size() > 4);
418                 for (int i = 0; i < cFaces.size(); ++i) {
419                     if (IndexIsValid(cFaces[i])) {
420                         _childFaceTag[cFaces[i]] = initialChildTags[incomplete][childTooLarge ? 0 : i];
421                         _childFaceParentIndex[cFaces[i]] = pFace;
422                     }
423                 }
424             }
425         }
426     }
427 }
428 
429 void
populateEdgeParentVectors(ChildTag const initialChildTags[2][4])430 Refinement::populateEdgeParentVectors(ChildTag const initialChildTags[2][4]) {
431 
432     _childEdgeTag.resize(_child->getNumEdges());
433     _childEdgeParentIndex.resize(_child->getNumEdges());
434 
435     populateEdgeParentFromParentFaces(initialChildTags);
436     populateEdgeParentFromParentEdges(initialChildTags);
437 }
438 void
populateEdgeParentFromParentFaces(ChildTag const initialChildTags[2][4])439 Refinement::populateEdgeParentFromParentFaces(ChildTag const initialChildTags[2][4]) {
440 
441     if (_uniform) {
442         Index cEdge = getFirstChildEdgeFromFaces();
443         for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
444             ConstIndexArray cEdges = getFaceChildEdges(pFace);
445             if (cEdges.size() == 4) {
446                 _childEdgeTag[cEdge + 0] = initialChildTags[0][0];
447                 _childEdgeTag[cEdge + 1] = initialChildTags[0][1];
448                 _childEdgeTag[cEdge + 2] = initialChildTags[0][2];
449                 _childEdgeTag[cEdge + 3] = initialChildTags[0][3];
450 
451                 _childEdgeParentIndex[cEdge + 0] = pFace;
452                 _childEdgeParentIndex[cEdge + 1] = pFace;
453                 _childEdgeParentIndex[cEdge + 2] = pFace;
454                 _childEdgeParentIndex[cEdge + 3] = pFace;
455 
456                 cEdge += 4;
457             } else {
458                 bool childTooLarge = (cEdges.size() > 4);
459                 for (int i = 0; i < cEdges.size(); ++i, ++cEdge) {
460                     _childEdgeTag[cEdge] = initialChildTags[0][childTooLarge ? 0 : i];
461                     _childEdgeParentIndex[cEdge] = pFace;
462                 }
463             }
464         }
465     } else {
466         for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
467             bool incomplete = !_parentFaceTag[pFace]._selected;
468 
469             IndexArray cEdges = getFaceChildEdges(pFace);
470             if (!incomplete && (cEdges.size() == 4)) {
471                 _childEdgeTag[cEdges[0]] = initialChildTags[0][0];
472                 _childEdgeTag[cEdges[1]] = initialChildTags[0][1];
473                 _childEdgeTag[cEdges[2]] = initialChildTags[0][2];
474                 _childEdgeTag[cEdges[3]] = initialChildTags[0][3];
475 
476                 _childEdgeParentIndex[cEdges[0]] = pFace;
477                 _childEdgeParentIndex[cEdges[1]] = pFace;
478                 _childEdgeParentIndex[cEdges[2]] = pFace;
479                 _childEdgeParentIndex[cEdges[3]] = pFace;
480             } else {
481                 bool childTooLarge = (cEdges.size() > 4);
482                 for (int i = 0; i < cEdges.size(); ++i) {
483                     if (IndexIsValid(cEdges[i])) {
484                         _childEdgeTag[cEdges[i]] = initialChildTags[incomplete][childTooLarge ? 0 : i];
485                         _childEdgeParentIndex[cEdges[i]] = pFace;
486                     }
487                 }
488             }
489         }
490     }
491 }
492 void
populateEdgeParentFromParentEdges(ChildTag const initialChildTags[2][4])493 Refinement::populateEdgeParentFromParentEdges(ChildTag const initialChildTags[2][4]) {
494 
495     if (_uniform) {
496         Index cEdge = getFirstChildEdgeFromEdges();
497         for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge, cEdge += 2) {
498             _childEdgeTag[cEdge + 0] = initialChildTags[0][0];
499             _childEdgeTag[cEdge + 1] = initialChildTags[0][1];
500 
501             _childEdgeParentIndex[cEdge + 0] = pEdge;
502             _childEdgeParentIndex[cEdge + 1] = pEdge;
503         }
504     } else {
505         for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
506             bool incomplete = !_parentEdgeTag[pEdge]._selected;
507 
508             IndexArray cEdges = getEdgeChildEdges(pEdge);
509             if (!incomplete) {
510                 _childEdgeTag[cEdges[0]] = initialChildTags[0][0];
511                 _childEdgeTag[cEdges[1]] = initialChildTags[0][1];
512 
513                 _childEdgeParentIndex[cEdges[0]] = pEdge;
514                 _childEdgeParentIndex[cEdges[1]] = pEdge;
515             } else {
516                 for (int i = 0; i < 2; ++i) {
517                     if (IndexIsValid(cEdges[i])) {
518                         _childEdgeTag[cEdges[i]] = initialChildTags[incomplete][i];
519                         _childEdgeParentIndex[cEdges[i]] = pEdge;
520                     }
521                 }
522             }
523         }
524     }
525 }
526 
527 void
populateVertexParentVectors(ChildTag const initialChildTags[2][4])528 Refinement::populateVertexParentVectors(ChildTag const initialChildTags[2][4]) {
529 
530     if (_uniform) {
531         _childVertexTag.resize(_child->getNumVertices(), initialChildTags[0][0]);
532     } else {
533         _childVertexTag.resize(_child->getNumVertices(), initialChildTags[1][0]);
534     }
535     _childVertexParentIndex.resize(_child->getNumVertices());
536 
537     populateVertexParentFromParentFaces(initialChildTags);
538     populateVertexParentFromParentEdges(initialChildTags);
539     populateVertexParentFromParentVertices(initialChildTags);
540 }
541 void
populateVertexParentFromParentFaces(ChildTag const initialChildTags[2][4])542 Refinement::populateVertexParentFromParentFaces(ChildTag const initialChildTags[2][4]) {
543 
544     if (getNumChildVerticesFromFaces() == 0) return;
545 
546     if (_uniform) {
547         Index cVert = getFirstChildVertexFromFaces();
548         for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace, ++cVert) {
549             //  Child tag was initialized as the complete and only child when allocated
550 
551             _childVertexParentIndex[cVert] = pFace;
552         }
553     } else {
554         ChildTag const & completeChildTag = initialChildTags[0][0];
555 
556         for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
557             Index cVert = _faceChildVertIndex[pFace];
558             if (IndexIsValid(cVert)) {
559                 //  Child tag was initialized as incomplete -- reset if complete:
560                 if (_parentFaceTag[pFace]._selected) {
561                     _childVertexTag[cVert] = completeChildTag;
562                 }
563                 _childVertexParentIndex[cVert] = pFace;
564             }
565         }
566     }
567 }
568 void
populateVertexParentFromParentEdges(ChildTag const initialChildTags[2][4])569 Refinement::populateVertexParentFromParentEdges(ChildTag const initialChildTags[2][4]) {
570 
571     if (_uniform) {
572         Index cVert = getFirstChildVertexFromEdges();
573         for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge, ++cVert) {
574             //  Child tag was initialized as the complete and only child when allocated
575 
576             _childVertexParentIndex[cVert] = pEdge;
577         }
578     } else {
579         ChildTag const & completeChildTag = initialChildTags[0][0];
580 
581         for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
582             Index cVert = _edgeChildVertIndex[pEdge];
583             if (IndexIsValid(cVert)) {
584                 //  Child tag was initialized as incomplete -- reset if complete:
585                 if (_parentEdgeTag[pEdge]._selected) {
586                     _childVertexTag[cVert] = completeChildTag;
587                 }
588                 _childVertexParentIndex[cVert] = pEdge;
589             }
590         }
591     }
592 }
593 void
populateVertexParentFromParentVertices(ChildTag const initialChildTags[2][4])594 Refinement::populateVertexParentFromParentVertices(ChildTag const initialChildTags[2][4]) {
595 
596     if (_uniform) {
597         Index cVert = getFirstChildVertexFromVertices();
598         for (Index pVert = 0; pVert < _parent->getNumVertices(); ++pVert, ++cVert) {
599             //  Child tag was initialized as the complete and only child when allocated
600 
601             _childVertexParentIndex[cVert] = pVert;
602         }
603     } else {
604         ChildTag const & completeChildTag = initialChildTags[0][0];
605 
606         for (Index pVert = 0; pVert < _parent->getNumVertices(); ++pVert) {
607             Index cVert = _vertChildVertIndex[pVert];
608             if (IndexIsValid(cVert)) {
609                 //  Child tag was initialized as incomplete but these should be complete:
610                 if (_parentVertexTag[pVert]._selected) {
611                     _childVertexTag[cVert] = completeChildTag;
612                 }
613                 _childVertexParentIndex[cVert] = pVert;
614             }
615         }
616     }
617 }
618 
619 
620 //
621 //  Methods to propagate/initialize child component tags from their parent component:
622 //
623 void
propagateComponentTags()624 Refinement::propagateComponentTags() {
625 
626     populateFaceTagVectors();
627     populateEdgeTagVectors();
628     populateVertexTagVectors();
629 }
630 
631 void
populateFaceTagVectors()632 Refinement::populateFaceTagVectors() {
633 
634     _child->_faceTags.resize(_child->getNumFaces());
635 
636     populateFaceTagsFromParentFaces();
637 }
638 void
populateFaceTagsFromParentFaces()639 Refinement::populateFaceTagsFromParentFaces() {
640 
641     //
642     //  Tags for faces originating from faces are inherited from the parent face:
643     //
644     Index cFace    = getFirstChildFaceFromFaces();
645     Index cFaceEnd = cFace + getNumChildFacesFromFaces();
646     for ( ; cFace < cFaceEnd; ++cFace) {
647         _child->_faceTags[cFace] = _parent->_faceTags[_childFaceParentIndex[cFace]];
648     }
649 }
650 
651 void
populateEdgeTagVectors()652 Refinement::populateEdgeTagVectors() {
653 
654     _child->_edgeTags.resize(_child->getNumEdges());
655 
656     populateEdgeTagsFromParentFaces();
657     populateEdgeTagsFromParentEdges();
658 }
659 void
populateEdgeTagsFromParentFaces()660 Refinement::populateEdgeTagsFromParentFaces() {
661 
662     //
663     //  Tags for edges originating from faces are all constant:
664     //
665     Level::ETag eTag;
666     eTag.clear();
667 
668     Index cEdge    = getFirstChildEdgeFromFaces();
669     Index cEdgeEnd = cEdge + getNumChildEdgesFromFaces();
670     for ( ; cEdge < cEdgeEnd; ++cEdge) {
671         _child->_edgeTags[cEdge] = eTag;
672     }
673 }
674 void
populateEdgeTagsFromParentEdges()675 Refinement::populateEdgeTagsFromParentEdges() {
676 
677     //
678     //  Tags for edges originating from edges are inherited from the parent edge:
679     //
680     Index cEdge    = getFirstChildEdgeFromEdges();
681     Index cEdgeEnd = cEdge + getNumChildEdgesFromEdges();
682     for ( ; cEdge < cEdgeEnd; ++cEdge) {
683         _child->_edgeTags[cEdge] = _parent->_edgeTags[_childEdgeParentIndex[cEdge]];
684     }
685 }
686 
687 void
populateVertexTagVectors()688 Refinement::populateVertexTagVectors() {
689 
690     _child->_vertTags.resize(_child->getNumVertices());
691 
692     populateVertexTagsFromParentFaces();
693     populateVertexTagsFromParentEdges();
694     populateVertexTagsFromParentVertices();
695 
696     if (!_uniform) {
697         for (Index cVert = 0; cVert < _child->getNumVertices(); ++cVert) {
698             if (_childVertexTag[cVert]._incomplete) {
699                 _child->_vertTags[cVert]._incomplete = true;
700             }
701         }
702     }
703 }
704 void
populateVertexTagsFromParentFaces()705 Refinement::populateVertexTagsFromParentFaces() {
706 
707     //
708     //  Similarly, tags for vertices originating from faces are all constant -- with the
709     //  unfortunate exception of refining level 0, where the faces may be N-sided and so
710     //  introduce new vertices that need to be tagged as extra-ordinary:
711     //
712     if (getNumChildVerticesFromFaces() == 0) return;
713 
714     Level::VTag vTag;
715     vTag.clear();
716     vTag._rule = Sdc::Crease::RULE_SMOOTH;
717 
718     Index cVert    = getFirstChildVertexFromFaces();
719     Index cVertEnd = cVert + getNumChildVerticesFromFaces();
720 
721     if (_parent->_depth > 0) {
722         for ( ; cVert < cVertEnd; ++cVert) {
723             _child->_vertTags[cVert] = vTag;
724         }
725     } else {
726         for ( ; cVert < cVertEnd; ++cVert) {
727             _child->_vertTags[cVert] = vTag;
728 
729             if (_parent->getNumFaceVertices(_childVertexParentIndex[cVert]) != _regFaceSize) {
730                 _child->_vertTags[cVert]._xordinary = true;
731             }
732         }
733     }
734 }
735 void
populateVertexTagsFromParentEdges()736 Refinement::populateVertexTagsFromParentEdges() {
737 
738     //
739     //  Tags for vertices originating from edges are initialized according to the tags
740     //  of the parent edge:
741     //
742     Level::VTag vTag;
743     vTag.clear();
744 
745     for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
746         Index cVert = _edgeChildVertIndex[pEdge];
747         if (!IndexIsValid(cVert)) continue;
748 
749         //  From the cleared local VTag, we just need to assign properties dependent
750         //  on the parent edge:
751         Level::ETag const& pEdgeTag = _parent->_edgeTags[pEdge];
752 
753         vTag._nonManifold    = pEdgeTag._nonManifold;
754         vTag._boundary       = pEdgeTag._boundary;
755         vTag._semiSharpEdges = pEdgeTag._semiSharp;
756         vTag._infSharpEdges  = pEdgeTag._infSharp;
757         vTag._infSharpCrease = pEdgeTag._infSharp;
758         vTag._infIrregular   = pEdgeTag._infSharp && pEdgeTag._nonManifold;
759 
760         vTag._rule = (Level::VTag::VTagSize)((pEdgeTag._semiSharp || pEdgeTag._infSharp)
761                        ? Sdc::Crease::RULE_CREASE : Sdc::Crease::RULE_SMOOTH);
762 
763         _child->_vertTags[cVert] = vTag;
764     }
765 }
766 void
populateVertexTagsFromParentVertices()767 Refinement::populateVertexTagsFromParentVertices() {
768 
769     //
770     //  Tags for vertices originating from vertices are inherited from the parent vertex:
771     //
772     Index cVert    = getFirstChildVertexFromVertices();
773     Index cVertEnd = cVert + getNumChildVerticesFromVertices();
774     for ( ; cVert < cVertEnd; ++cVert) {
775         _child->_vertTags[cVert] = _parent->_vertTags[_childVertexParentIndex[cVert]];
776         _child->_vertTags[cVert]._incidIrregFace = 0;
777     }
778 }
779 
780 
781 
782 //
783 //  Methods to subdivide the topology:
784 //
785 //  The main method to subdivide topology is fairly simple -- given a set of relations
786 //  to populate it simply tests and populates each relation separately.  The method for
787 //  each relation is responsible for appropriate allocation and initialization of all
788 //  data involved, and these are virtual -- provided by a quad- or tri-split subclass.
789 //
790 void
subdivideTopology(Relations const & applyTo)791 Refinement::subdivideTopology(Relations const& applyTo) {
792 
793     if (applyTo._faceVertices) {
794         populateFaceVertexRelation();
795     }
796     if (applyTo._faceEdges) {
797         populateFaceEdgeRelation();
798     }
799     if (applyTo._edgeVertices) {
800         populateEdgeVertexRelation();
801     }
802     if (applyTo._edgeFaces) {
803         populateEdgeFaceRelation();
804     }
805     if (applyTo._vertexFaces) {
806         populateVertexFaceRelation();
807     }
808     if (applyTo._vertexEdges) {
809         populateVertexEdgeRelation();
810     }
811 
812     //
813     //  Additional members of the child Level not specific to any relation...
814     //      - note in the case of max-valence, the child's max-valence may be less
815     //  than the parent if that maximal parent vertex was not included in the sparse
816     //  refinement (possible when sparse refinement is more general).
817     //      - it may also be more if the base level was fairly trivial, i.e. less
818     //  than the regular valence, or contains non-manifold edges with many faces.
819     //      - NOTE that when/if we support N-gons for tri-splitting, that the valence
820     //  of edge-vertices introduced on the N-gon may be 7 rather than 6, while N may
821     //  be less than both.
822     //
823     //  In general, we need a better way to deal with max-valence.  The fact that
824     //  each topology relation is independent/optional complicates the issue of
825     //  where to keep track of it...
826     //
827     if (_splitType == Sdc::SPLIT_TO_QUADS) {
828         _child->_maxValence = std::max(_parent->_maxValence, 4);
829         _child->_maxValence = std::max(_child->_maxValence, 2 + _parent->_maxEdgeFaces);
830     } else {
831         _child->_maxValence = std::max(_parent->_maxValence, 6);
832         _child->_maxValence = std::max(_child->_maxValence, 2 + _parent->_maxEdgeFaces * 2);
833     }
834 }
835 
836 
837 //
838 //  Methods to subdivide sharpness values:
839 //
840 void
subdivideSharpnessValues()841 Refinement::subdivideSharpnessValues() {
842 
843     //
844     //  Subdividing edge and vertex sharpness values are independent, but in order
845     //  to maintain proper classification/tagging of components as semi-sharp, both
846     //  must be computed and the neighborhood inspected to properly update the
847     //  status.
848     //
849     //  It is possible to clear the semi-sharp status when propagating the tags and
850     //  to reset it (potentially multiple times) when updating the sharpness values.
851     //  The vertex subdivision Rule is also affected by this, which complicates the
852     //  process.  So for now we apply a post-process to explicitly handle all
853     //  semi-sharp vertices.
854     //
855 
856     //  These methods will update sharpness tags local to the edges and vertices:
857     subdivideEdgeSharpness();
858     subdivideVertexSharpness();
859 
860     //  This method uses local sharpness tags (set above) to update vertex tags that
861     //  reflect the neighborhood of the vertex (e.g. its rule):
862     reclassifySemisharpVertices();
863 }
864 
865 void
subdivideEdgeSharpness()866 Refinement::subdivideEdgeSharpness() {
867 
868     Sdc::Crease creasing(_options);
869 
870     _child->_edgeSharpness.clear();
871     _child->_edgeSharpness.resize(_child->getNumEdges(), Sdc::Crease::SHARPNESS_SMOOTH);
872 
873     //
874     //  Edge sharpness is passed to child-edges using the parent edge and the
875     //  parent vertex for which the child corresponds.  Child-edges are created
876     //  from both parent faces and parent edges, but those child-edges created
877     //  from a parent face should be within the face's interior and so smooth
878     //  (and so previously initialized).
879     //
880     //  The presence/validity of each parent edges child vert indicates one or
881     //  more child edges.
882     //
883     //  NOTE -- It is also useful at this time to classify the child vert of
884     //  this edge based on the creasing information here, particularly when a
885     //  non-trivial creasing method like Chaikin is used.  This is not being
886     //  done now but is worth considering...
887     //
888     internal::StackBuffer<float,16> pVertEdgeSharpness;
889     if (!creasing.IsUniform()) {
890         pVertEdgeSharpness.Reserve(_parent->getMaxValence());
891     }
892 
893     Index cEdge    = getFirstChildEdgeFromEdges();
894     Index cEdgeEnd = cEdge + getNumChildEdgesFromEdges();
895     for ( ; cEdge < cEdgeEnd; ++cEdge) {
896         float&       cSharpness = _child->_edgeSharpness[cEdge];
897         Level::ETag& cEdgeTag   = _child->_edgeTags[cEdge];
898 
899         if (cEdgeTag._infSharp) {
900             cSharpness = Sdc::Crease::SHARPNESS_INFINITE;
901         } else if (cEdgeTag._semiSharp) {
902             Index pEdge      = _childEdgeParentIndex[cEdge];
903             float pSharpness = _parent->_edgeSharpness[pEdge];
904 
905             if (creasing.IsUniform()) {
906                 cSharpness = creasing.SubdivideUniformSharpness(pSharpness);
907             } else {
908                 ConstIndexArray pEdgeVerts = _parent->getEdgeVertices(pEdge);
909                 Index           pVert      = pEdgeVerts[_childEdgeTag[cEdge]._indexInParent];
910                 ConstIndexArray pVertEdges = _parent->getVertexEdges(pVert);
911 
912                 for (int i = 0; i < pVertEdges.size(); ++i) {
913                     pVertEdgeSharpness[i] = _parent->_edgeSharpness[pVertEdges[i]];
914                 }
915                 cSharpness = creasing.SubdivideEdgeSharpnessAtVertex(pSharpness, pVertEdges.size(),
916                                                                          pVertEdgeSharpness);
917             }
918             if (! Sdc::Crease::IsSharp(cSharpness)) {
919                 cEdgeTag._semiSharp = false;
920             }
921         }
922     }
923 }
924 
925 void
subdivideVertexSharpness()926 Refinement::subdivideVertexSharpness() {
927 
928     Sdc::Crease creasing(_options);
929 
930     _child->_vertSharpness.clear();
931     _child->_vertSharpness.resize(_child->getNumVertices(), Sdc::Crease::SHARPNESS_SMOOTH);
932 
933     //
934     //  All child-verts originating from faces or edges are initialized as smooth
935     //  above.  Only those originating from vertices require "subdivided" values:
936     //
937     //  Only deal with the subrange of vertices originating from vertices:
938     Index cVertBegin = getFirstChildVertexFromVertices();
939     Index cVertEnd   = cVertBegin + getNumChildVerticesFromVertices();
940 
941     for (Index cVert = cVertBegin; cVert < cVertEnd; ++cVert) {
942         float&       cSharpness = _child->_vertSharpness[cVert];
943         Level::VTag& cVertTag   = _child->_vertTags[cVert];
944 
945         if (cVertTag._infSharp) {
946             cSharpness = Sdc::Crease::SHARPNESS_INFINITE;
947         } else if (cVertTag._semiSharp) {
948             Index pVert      = _childVertexParentIndex[cVert];
949             float pSharpness = _parent->_vertSharpness[pVert];
950 
951             cSharpness = creasing.SubdivideVertexSharpness(pSharpness);
952             if (! Sdc::Crease::IsSharp(cSharpness)) {
953                 cVertTag._semiSharp = false;
954             }
955         }
956     }
957 }
958 
959 void
reclassifySemisharpVertices()960 Refinement::reclassifySemisharpVertices() {
961 
962     typedef Level::VTag::VTagSize VTagSize;
963 
964     Sdc::Crease creasing(_options);
965 
966     //
967     //  Inspect all vertices derived from edges -- for those whose parent edges were semisharp,
968     //  reset the semisharp tag and the associated Rule according to the sharpness pair for the
969     //  subdivided edges (note this may be better handled when the edge sharpness is computed):
970     //
971     Index vertFromEdgeBegin = getFirstChildVertexFromEdges();
972     Index vertFromEdgeEnd   = vertFromEdgeBegin + getNumChildVerticesFromEdges();
973 
974     for (Index cVert = vertFromEdgeBegin; cVert < vertFromEdgeEnd; ++cVert) {
975         Level::VTag& cVertTag = _child->_vertTags[cVert];
976         if (!cVertTag._semiSharpEdges) continue;
977 
978         Index pEdge = _childVertexParentIndex[cVert];
979 
980         ConstIndexArray cEdges = getEdgeChildEdges(pEdge);
981 
982         if (_childVertexTag[cVert]._incomplete) {
983             //  One child edge likely missing -- assume Crease if remaining edge semi-sharp:
984             cVertTag._semiSharpEdges = (IndexIsValid(cEdges[0]) && _child->_edgeTags[cEdges[0]]._semiSharp) ||
985                                        (IndexIsValid(cEdges[1]) && _child->_edgeTags[cEdges[1]]._semiSharp);
986             cVertTag._rule = (VTagSize)(cVertTag._semiSharpEdges ? Sdc::Crease::RULE_CREASE : Sdc::Crease::RULE_SMOOTH);
987         } else {
988             int sharpEdgeCount = _child->_edgeTags[cEdges[0]]._semiSharp + _child->_edgeTags[cEdges[1]]._semiSharp;
989 
990             cVertTag._semiSharpEdges = (sharpEdgeCount > 0);
991             cVertTag._rule = (VTagSize)(creasing.DetermineVertexVertexRule(0.0, sharpEdgeCount));
992         }
993     }
994 
995     //
996     //  Inspect all vertices derived from vertices -- for those whose parent vertices were
997     //  semisharp (inherited in the child vert's tag), inspect and reset the semisharp tag
998     //  and the associated Rule (based on neighboring child edges around the child vertex).
999     //
1000     //  We should never find such a vertex "incomplete" in a sparse refinement as a parent
1001     //  vertex is either selected or not, but never neighboring.  So the only complication
1002     //  here is whether the local topology of child edges exists -- it may have been pruned
1003     //  from the last level to reduce memory.  If so, we use the parent to identify the
1004     //  child edges.
1005     //
1006     //  In both cases, we count the number of sharp and semisharp child edges incident the
1007     //  child vertex and adjust the "semisharp" and "rule" tags accordingly.
1008     //
1009     Index vertFromVertBegin = getFirstChildVertexFromVertices();
1010     Index vertFromVertEnd   = vertFromVertBegin + getNumChildVerticesFromVertices();
1011 
1012     for (Index cVert = vertFromVertBegin; cVert < vertFromVertEnd; ++cVert) {
1013         Index pVert = _childVertexParentIndex[cVert];
1014         Level::VTag const& pVertTag = _parent->_vertTags[pVert];
1015 
1016         //  Skip if parent not semi-sharp:
1017         if (!pVertTag._semiSharp && !pVertTag._semiSharpEdges) continue;
1018 
1019         //
1020         //  We need to inspect the child neighborhood's sharpness when either semi-sharp
1021         //  edges were present around the parent vertex, or the parent vertex sharpness
1022         //  decayed:
1023         //
1024         Level::VTag& cVertTag = _child->_vertTags[cVert];
1025 
1026         bool sharpVertexDecayed = pVertTag._semiSharp && !cVertTag._semiSharp;
1027 
1028         if (pVertTag._semiSharpEdges || sharpVertexDecayed) {
1029             int infSharpEdgeCount = 0;
1030             int semiSharpEdgeCount = 0;
1031 
1032             bool cVertEdgesPresent = (_child->getNumVertexEdgesTotal() > 0);
1033             if (cVertEdgesPresent) {
1034                 ConstIndexArray cEdges = _child->getVertexEdges(cVert);
1035 
1036                 for (int i = 0; i < cEdges.size(); ++i) {
1037                     Level::ETag cEdgeTag = _child->_edgeTags[cEdges[i]];
1038 
1039                     infSharpEdgeCount  += cEdgeTag._infSharp;
1040                     semiSharpEdgeCount += cEdgeTag._semiSharp;
1041                 }
1042             } else {
1043                 ConstIndexArray      pEdges      = _parent->getVertexEdges(pVert);
1044                 ConstLocalIndexArray pVertInEdge = _parent->getVertexEdgeLocalIndices(pVert);
1045 
1046                 for (int i = 0; i < pEdges.size(); ++i) {
1047                     ConstIndexArray cEdgePair = getEdgeChildEdges(pEdges[i]);
1048 
1049                     Index       cEdge    = cEdgePair[pVertInEdge[i]];
1050                     Level::ETag cEdgeTag = _child->_edgeTags[cEdge];
1051 
1052                     infSharpEdgeCount  += cEdgeTag._infSharp;
1053                     semiSharpEdgeCount += cEdgeTag._semiSharp;
1054                 }
1055             }
1056             cVertTag._semiSharpEdges = (semiSharpEdgeCount > 0);
1057 
1058             if (!cVertTag._semiSharp && !cVertTag._infSharp) {
1059                 cVertTag._rule = (VTagSize)(creasing.DetermineVertexVertexRule(0.0,
1060                                         infSharpEdgeCount + semiSharpEdgeCount));
1061             }
1062         }
1063     }
1064 }
1065 
1066 //
1067 //  Methods to subdivide face-varying channels:
1068 //
1069 void
subdivideFVarChannels()1070 Refinement::subdivideFVarChannels() {
1071 
1072     assert(_child->_fvarChannels.size() == 0);
1073     assert(this->_fvarChannels.size() == 0);
1074 
1075     int channelCount = _parent->getNumFVarChannels();
1076 
1077     for (int channel = 0; channel < channelCount; ++channel) {
1078         FVarLevel* parentFVar = _parent->_fvarChannels[channel];
1079 
1080         FVarLevel*      childFVar  = new FVarLevel(*_child);
1081         FVarRefinement* refineFVar = new FVarRefinement(*this, *parentFVar, *childFVar);
1082 
1083         refineFVar->applyRefinement();
1084 
1085         _child->_fvarChannels.push_back(childFVar);
1086         this->_fvarChannels.push_back(refineFVar);
1087     }
1088 }
1089 
1090 //
1091 //  Marking of sparse child components -- including those selected and those neighboring...
1092 //
1093 //      For schemes requiring neighboring support, this is the equivalent of the "guarantee
1094 //  neighbors" in Hbr -- it ensures that all components required to define the limit of
1095 //  those "selected" are also generated in the refinement.
1096 //
1097 //  The difference with Hbr is that we do this in a single pass for all components once
1098 //  "selection" of components of interest has been completed.
1099 //
1100 //  Considering two approaches:
1101 //      1) By Vertex neighborhoods:
1102 //          - for each base vertex
1103 //              - for each incident face
1104 //                  - test and mark components for its child face
1105 //  or
1106 //      2) By Edge and Face contents:
1107 //          - for each base edge
1108 //              - test and mark local components
1109 //          - for each base face
1110 //              - test and mark local components
1111 //
1112 //  Given a typical quad mesh with N verts, N faces and 2*N edges, determine which is more
1113 //  efficient...
1114 //
1115 //  Going with (2) initially for simplicity -- certain aspects of (1) are awkward, i.e. the
1116 //  identification of child-edges to be marked (trivial in (2).  We are also guaranteed with
1117 //  (2) that we only visit each component once, i.e. each edge and each face.
1118 //
1119 //  Revising the above assessment... (2) has gotten WAY more complicated once the ability to
1120 //  select child faces is provided.  Given that feature is important to Manuel for support
1121 //  of the FarStencilTables we have to assume it will be needed.  So we'll try (1) out as it
1122 //  will be simpler to get it correct -- we can work on improving performance later.
1123 //
1124 //  Complexity added by child component selection:
1125 //      - the child vertex of the component can now be selected as part of a child face or
1126 //  edge, and so the parent face or edge is not fully selected.  So we've had to add another
1127 //  bit to the marking masks to indicate when a parent component is "fully selected".
1128 //      - selecting a child face creates the situation where child edges of parent edges do
1129 //  not have any selected vertex at their ends -- both can be neighboring.  This complicated
1130 //  the marking of neighboring child edges, which was otherwise trivial -- if any end vertex
1131 //  of a child edge (of a parent edge) was selected, the child edge was at least neighboring.
1132 //
1133 //  Final note on the marking technique:
1134 //      There are currently two values to the marking of child components, which are no
1135 //  longer that useful.  It is now sufficient, and not likely to be necessary, to distinguish
1136 //  between what was selected or added to support it.  Ultimately that will be determined by
1137 //  inspecting the selected flag on the parent component once the child-to-parent map is in
1138 //  place.
1139 //
1140 namespace {
1141     Index const IndexSparseMaskNeighboring = (1 << 0);
1142     Index const IndexSparseMaskSelected    = (1 << 1);
1143 
markSparseIndexNeighbor(Index & index)1144     inline void markSparseIndexNeighbor(Index& index) { index = IndexSparseMaskNeighboring; }
markSparseIndexSelected(Index & index)1145     inline void markSparseIndexSelected(Index& index) { index = IndexSparseMaskSelected; }
1146 }
1147 
1148 void
markSparseChildComponentIndices()1149 Refinement::markSparseChildComponentIndices() {
1150 
1151     //
1152     //  There is an explicit ordering here as the work done for vertices is a subset
1153     //  of what is required for edges, which in turn is a subset of what is required
1154     //  for faces.  This ordering and their related implementations tries to avoid
1155     //  doing redundant work and accomplishing everything necessary in a single
1156     //  iteration through each component type.
1157     //
1158     markSparseVertexChildren();
1159     markSparseEdgeChildren();
1160     markSparseFaceChildren();
1161 }
1162 
1163 
1164 void
markSparseVertexChildren()1165 Refinement::markSparseVertexChildren() {
1166 
1167     assert(_parentVertexTag.size() > 0);
1168 
1169     //
1170     //  For each parent vertex:
1171     //      - mark the descending child vertex for each selected vertex
1172     //
1173     for (Index pVert = 0; pVert < parent().getNumVertices(); ++pVert) {
1174         if (_parentVertexTag[pVert]._selected) {
1175             markSparseIndexSelected(_vertChildVertIndex[pVert]);
1176         }
1177     }
1178 }
1179 
1180 void
markSparseEdgeChildren()1181 Refinement::markSparseEdgeChildren() {
1182 
1183     assert(_parentEdgeTag.size() > 0);
1184 
1185     //
1186     //  For each parent edge:
1187     //      - mark the descending child edges and vertex for each selected edge
1188     //      - test each end vertex of unselected edges to see if selected:
1189     //          - mark both the child edge and the middle child vertex if so
1190     //      - set transitional bit for all edges based on selection of incident faces
1191     //
1192     //  Note that no edges have been marked "fully selected" -- only their vertices have
1193     //  been marked and marking of their child edges deferred to visiting each edge only
1194     //  once here.
1195     //
1196     for (Index pEdge = 0; pEdge < parent().getNumEdges(); ++pEdge) {
1197         IndexArray      eChildEdges = getEdgeChildEdges(pEdge);
1198         ConstIndexArray eVerts      = parent().getEdgeVertices(pEdge);
1199 
1200         SparseTag& pEdgeTag = _parentEdgeTag[pEdge];
1201 
1202         if (pEdgeTag._selected) {
1203             markSparseIndexSelected(eChildEdges[0]);
1204             markSparseIndexSelected(eChildEdges[1]);
1205             markSparseIndexSelected(_edgeChildVertIndex[pEdge]);
1206         } else {
1207             if (_parentVertexTag[eVerts[0]]._selected) {
1208                 markSparseIndexNeighbor(eChildEdges[0]);
1209                 markSparseIndexNeighbor(_edgeChildVertIndex[pEdge]);
1210             }
1211             if (_parentVertexTag[eVerts[1]]._selected) {
1212                 markSparseIndexNeighbor(eChildEdges[1]);
1213                 markSparseIndexNeighbor(_edgeChildVertIndex[pEdge]);
1214             }
1215         }
1216 
1217         //
1218         //  TAG the parent edges as "transitional" here if only one was selected (or in
1219         //  the more general non-manifold case, they are not all selected the same way).
1220         //  We use the transitional tags on the edges to TAG the parent face below.
1221         //
1222         //  Note -- this is best done now rather than as a post-process as we have more
1223         //  explicit information about the selected components.  Unless we also tag the
1224         //  parent faces as selected, we can't easily tell from the child-faces of the
1225         //  edge's incident faces which were generated by selection or neighboring...
1226         //
1227         ConstIndexArray eFaces = parent().getEdgeFaces(pEdge);
1228         if (eFaces.size() == 2) {
1229             pEdgeTag._transitional = (_parentFaceTag[eFaces[0]]._selected !=
1230                                       _parentFaceTag[eFaces[1]]._selected);
1231         } else if (eFaces.size() < 2) {
1232             pEdgeTag._transitional = false;
1233         } else {
1234             bool isFace0Selected = _parentFaceTag[eFaces[0]]._selected;
1235 
1236             pEdgeTag._transitional = false;
1237             for (int i = 1; i < eFaces.size(); ++i) {
1238                 if (_parentFaceTag[eFaces[i]]._selected != isFace0Selected) {
1239                     pEdgeTag._transitional = true;
1240                     break;
1241                 }
1242             }
1243         }
1244     }
1245 }
1246 
1247 } // end namespace internal
1248 } // end namespace Vtr
1249 
1250 } // end namespace OPENSUBDIV_VERSION
1251 } // end namespace OpenSubdiv
1252