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