OpenSubdiv
Loading...
Searching...
No Matches
scheme.h
Go to the documentation of this file.
1//
2// Copyright 2014 DreamWorks Animation LLC.
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24#ifndef OPENSUBDIV3_SDC_SCHEME_H
25#define OPENSUBDIV3_SDC_SCHEME_H
26
27#include "../version.h"
28
29#include "../sdc/types.h"
30#include "../sdc/options.h"
31#include "../sdc/crease.h"
32
33#include <cassert>
34#include <cstdlib>
35#include <vector>
36
37namespace OpenSubdiv {
38namespace OPENSUBDIV_VERSION {
39
40namespace Sdc {
41
65template <SchemeType SCHEME_TYPE>
66class Scheme {
67
68public:
69
70 Scheme() : _options() { }
71
72 Scheme(Options const& options) : _options(options) { }
73
74 Options GetOptions() const { return _options; }
75 void SetOptions(const Options& newOptions) { _options = newOptions; }
76
80 template <typename FACE, typename MASK>
81 void ComputeFaceVertexMask(FACE const& faceNeighborhood, MASK& faceVertexMask) const;
82
98 template <typename EDGE, typename MASK>
99 void ComputeEdgeVertexMask(EDGE const& edgeNeighborhood, MASK& edgeVertexMask,
101 Crease::Rule childRule = Crease::RULE_UNKNOWN) const;
102
112 template <typename VERTEX, typename MASK>
113 void ComputeVertexVertexMask(VERTEX const& vertexNeighborhood, MASK& vertexVertexMask,
115 Crease::Rule childRule = Crease::RULE_UNKNOWN) const;
116
141 template <typename VERTEX, typename MASK>
142 void ComputeVertexLimitMask(VERTEX const& vertexNeighborhood, MASK& positionMask,
143 Crease::Rule vertexRule) const;
144
145 template <typename VERTEX, typename MASK>
146 void ComputeVertexLimitMask(VERTEX const& vertexNeighborhood, MASK& positionMask,
147 MASK& tangent1Mask, MASK& tangent2Mask,
148 Crease::Rule vertexRule) const;
149
150 //
151 // Static methods defining traits/properties of the scheme:
152 //
154 static int GetRegularFaceSize();
157
158protected:
159
160 //
161 // Supporting internal methods -- optionally implemented, depending on specialization:
162 //
163
164 // Subdivision/refinement masks -- two for edge-vertices and three for vertex-vertices:
165 //
166 template <typename EDGE, typename MASK>
167 void assignCreaseMaskForEdge(EDGE const& edge, MASK& mask) const;
168 template <typename EDGE, typename MASK>
169 void assignSmoothMaskForEdge(EDGE const& edge, MASK& mask) const;
170
171 template <typename VERTEX, typename MASK>
172 void assignCornerMaskForVertex(VERTEX const& edge, MASK& mask) const;
173 template <typename VERTEX, typename MASK>
174 void assignCreaseMaskForVertex(VERTEX const& edge, MASK& mask, int const creaseEnds[2]) const;
175 template <typename VERTEX, typename MASK>
176 void assignSmoothMaskForVertex(VERTEX const& edge, MASK& mask) const;
177
178 //
179 // Limit masks for position and tangents at vertices -- three cases for each:
180 //
181 template <typename VERTEX, typename MASK>
182 void assignCornerLimitMask(VERTEX const& vertex, MASK& pos) const;
183 template <typename VERTEX, typename MASK>
184 void assignCreaseLimitMask(VERTEX const& vertex, MASK& pos, int const creaseEnds[2]) const;
185 template <typename VERTEX, typename MASK>
186 void assignSmoothLimitMask(VERTEX const& vertex, MASK& pos) const;
187
188 template <typename VERTEX, typename MASK>
189 void assignCornerLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2) const;
190 template <typename VERTEX, typename MASK>
191 void assignCreaseLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2, int const creaseEnds[2]) const;
192 template <typename VERTEX, typename MASK>
193 void assignSmoothLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2) const;
194
195private:
196 Options _options;
197
198protected:
199
200 //
201 // Internal implementation support:
202 //
203 // We need a local "mask" class to be declared locally within the vertex-vertex mask query
204 // to hold one of the two possible masks required and to combine the local mask with the mask
205 // the caller provides. It has been parameterized by <WEIGHT> so that a version compatible
206 // with the caller's mask class is created.
207 //
208 template <typename WEIGHT>
209 class LocalMask {
210
211 public:
212 typedef WEIGHT Weight;
213
214 public:
215 LocalMask(Weight* v, Weight* e, Weight* f) : _vWeights(v), _eWeights(e), _fWeights(f) { }
217
218 public:
219
220 //
221 // Methods required for general mask assignments and queries:
222 //
223 int GetNumVertexWeights() const { return _vCount; }
224 int GetNumEdgeWeights() const { return _eCount; }
225 int GetNumFaceWeights() const { return _fCount; }
226
227 void SetNumVertexWeights(int count) { _vCount = count; }
228 void SetNumEdgeWeights( int count) { _eCount = count; }
229 void SetNumFaceWeights( int count) { _fCount = count; }
230
231 Weight const& VertexWeight(int index) const { return _vWeights[index]; }
232 Weight const& EdgeWeight( int index) const { return _eWeights[index]; }
233 Weight const& FaceWeight( int index) const { return _fWeights[index]; }
234
235 Weight& VertexWeight(int index) { return _vWeights[index]; }
236 Weight& EdgeWeight( int index) { return _eWeights[index]; }
237 Weight& FaceWeight( int index) { return _fWeights[index]; }
238
239 bool AreFaceWeightsForFaceCenters() const { return _fWeightsForCenters; }
240 void SetFaceWeightsForFaceCenters(bool on) { _fWeightsForCenters = on; }
241
242 public:
243
244 //
245 // Additional methods -- mainly the blending method for vertex-vertex masks:
246 //
247 template <typename USER_MASK>
248 inline void
249 CombineVertexVertexMasks(Weight thisCoeff, Weight dstCoeff, USER_MASK& dst) const {
250
251 //
252 // This implementation is convoluted by the potential sparsity of each mask. Since
253 // it is specific to a vertex-vertex mask, we are guaranteed to have exactly one
254 // vertex-weight for both masks, but the edge- and face-weights are optional. The
255 // child mask (the "source") should have a superset of the weights of the parent
256 // (the "destination") given its reduced sharpness, so we fortunately don't need to
257 // test all permutations.
258 //
259 dst.VertexWeight(0) = dstCoeff * dst.VertexWeight(0) + thisCoeff * this->VertexWeight(0);
260
261 int edgeWeightCount = this->GetNumEdgeWeights();
262 if (edgeWeightCount) {
263 if (dst.GetNumEdgeWeights() == 0) {
264 dst.SetNumEdgeWeights(edgeWeightCount);
265 for (int i = 0; i < edgeWeightCount; ++i) {
266 dst.EdgeWeight(i) = thisCoeff * this->EdgeWeight(i);
267 }
268 } else {
269 for (int i = 0; i < edgeWeightCount; ++i) {
270 dst.EdgeWeight(i) = dstCoeff * dst.EdgeWeight(i) + thisCoeff * this->EdgeWeight(i);
271 }
272 }
273 }
274
275 int faceWeightCount = this->GetNumFaceWeights();
276 if (faceWeightCount) {
277 //
278 // If combining face weights, be sure their interpretation (i.e. face-centers
279 // or opposite vertices) is properly set in the destination mask:
280 //
281 if (dst.GetNumFaceWeights() == 0) {
282 dst.SetNumFaceWeights(faceWeightCount);
283 dst.SetFaceWeightsForFaceCenters(this->AreFaceWeightsForFaceCenters());
284
285 for (int i = 0; i < faceWeightCount; ++i) {
286 dst.FaceWeight(i) = thisCoeff * this->FaceWeight(i);
287 }
288 } else {
289 assert(this->AreFaceWeightsForFaceCenters() == dst.AreFaceWeightsForFaceCenters());
290
291 for (int i = 0; i < faceWeightCount; ++i) {
292 dst.FaceWeight(i) = dstCoeff * dst.FaceWeight(i) + thisCoeff * this->FaceWeight(i);
293 }
294 }
295 }
296 }
297
298 private:
299 Weight* _vWeights;
300 Weight* _eWeights;
301 Weight* _fWeights;
302 int _vCount;
303 int _eCount;
304 int _fCount;
305 bool _fWeightsForCenters;
306 };
307};
308
309
310//
311// Crease and corner masks are common to most schemes -- the rest need to be provided
312// for each Scheme specialization.
313//
314template <SchemeType SCHEME>
315template <typename EDGE, typename MASK>
316inline void
317Scheme<SCHEME>::assignCreaseMaskForEdge(EDGE const&, MASK& mask) const {
318
319 mask.SetNumVertexWeights(2);
320 mask.SetNumEdgeWeights(0);
321 mask.SetNumFaceWeights(0);
322 mask.SetFaceWeightsForFaceCenters(false);
323
324 mask.VertexWeight(0) = 0.5f;
325 mask.VertexWeight(1) = 0.5f;
326}
327
328template <SchemeType SCHEME>
329template <typename VERTEX, typename MASK>
330inline void
331Scheme<SCHEME>::assignCornerMaskForVertex(VERTEX const&, MASK& mask) const {
332
333 mask.SetNumVertexWeights(1);
334 mask.SetNumEdgeWeights(0);
335 mask.SetNumFaceWeights(0);
336 mask.SetFaceWeightsForFaceCenters(false);
337
338 mask.VertexWeight(0) = 1.0f;
339}
340
341
342//
343// The computation of a face-vertex mask is trivial and consistent for all schemes:
344//
345template <SchemeType SCHEME>
346template <typename FACE, typename MASK>
347void
348Scheme<SCHEME>::ComputeFaceVertexMask(FACE const& face, MASK& mask) const {
349
350 int vertCount = face.GetNumVertices();
351
352 mask.SetNumVertexWeights(vertCount);
353 mask.SetNumEdgeWeights(0);
354 mask.SetNumFaceWeights(0);
355 mask.SetFaceWeightsForFaceCenters(false);
356
357 typename MASK::Weight vWeight = 1.0f / (typename MASK::Weight) vertCount;
358 for (int i = 0; i < vertCount; ++i) {
359 mask.VertexWeight(i) = vWeight;
360 }
361}
362
363
364//
365// The computation of an edge-vertex mask requires inspection of sharpness values to
366// determine if smooth or a crease, and also to detect and apply a transition from a
367// crease to smooth. Using the protected methods to assign the specific masks (only
368// two -- smooth or crease) this implementation should serve all non-linear schemes
369// (currently Catmark and Loop) and only needs to be specialized for Bilinear to
370// trivialize it to the crease case.
371//
372// The implementation here is slightly complicated by combining two scenarios into a
373// single implementation -- either the caller knows the parent and child rules and
374// provides them, or they don't and the Rules have to be determined from sharpness
375// values. Both cases include quick return once the parent is determined to be
376// smooth or the child a crease, leaving the transitional case remaining.
377//
378// The overall process is as follows:
379//
380// - quickly detect the most common specified or detected Smooth case and return
381// - quickly detect a full Crease by child Rule assignment and return
382// - determine from sharpness if unspecified child is a crease -- return if so
383// - compute smooth mask for child and combine with crease from parent
384//
385// Usage of the parent Rule here allows some misuse in that only three of five possible
386// assignments are legitimate for the parent and four for the child (Dart being only
387// valid for the child and Corner for neither). Results are undefined in these cases.
388//
389template <SchemeType SCHEME>
390template <typename EDGE, typename MASK>
391void
393 MASK& mask,
394 Crease::Rule parentRule,
395 Crease::Rule childRule) const {
396
397 //
398 // If the parent was specified or determined to be Smooth, we can quickly return
399 // with a Smooth mask. Otherwise the parent is a crease -- if the child was
400 // also specified to be a crease, we can quickly return with a Crease mask.
401 //
402 if ((parentRule == Crease::RULE_SMOOTH) ||
403 ((parentRule == Crease::RULE_UNKNOWN) && (edge.GetSharpness() <= 0.0f))) {
404 assignSmoothMaskForEdge(edge, mask);
405 return;
406 }
407 if (childRule == Crease::RULE_CREASE) {
408 assignCreaseMaskForEdge(edge, mask);
409 return;
410 }
411
412 //
413 // We have a Crease on the parent and the child was either specified as Smooth
414 // or was not specified at all -- deal with the unspecified case first (again
415 // returning a Crease mask if the child is also determined to be a Crease) and
416 // continue if we have a transition to Smooth.
417 //
418 // Note when qualifying the child that if the parent sharpness > 1.0, regardless
419 // of the creasing method, whether the child sharpness values decay to zero is
420 // irrelevant -- the fractional weight for such a case (the value of the parent
421 // sharpness) is > 1.0, and when clamped to 1 effectively yields a full crease.
422 //
423 if (childRule == Crease::RULE_UNKNOWN) {
424 Crease crease(_options);
425
426 bool childIsCrease = false;
427 if (parentRule == Crease::RULE_CREASE) {
428 // Child unknown as default value but parent Rule specified as Crease
429 childIsCrease = true;
430 } else if (edge.GetSharpness() >= 1.0f) {
431 // Sharpness >= 1.0 always a crease -- see note above
432 childIsCrease = true;
433 } else if (crease.IsUniform()) {
434 // Sharpness < 1.0 is guaranteed to decay to 0.0 for Uniform child edges
435 childIsCrease = false;
436 } else {
437 // Sharpness <= 1.0 does not necessarily decay to 0.0 for both child edges...
438 float cEdgeSharpness[2];
439 edge.GetChildSharpnesses(crease, cEdgeSharpness);
440 childIsCrease = (cEdgeSharpness[0] > 0.0f) && (cEdgeSharpness[1] > 0.0f);
441 }
442 if (childIsCrease) {
443 assignCreaseMaskForEdge(edge, mask);
444 return;
445 }
446 }
447
448 //
449 // We are now left with the Crease-to-Smooth case -- compute the Smooth mask
450 // for the child and augment it with the transitional Crease of the parent.
451 //
452 // A general combination of separately assigned masks here (as done in the vertex-
453 // vertex case) is overkill -- trivially combine the 0.5f vertex coefficient for
454 // the Crease of the parent with the vertex weights and attenuate the face weights
455 // accordingly.
456 //
457 assignSmoothMaskForEdge(edge, mask);
458
459 typedef typename MASK::Weight Weight;
460
461 Weight pWeight = edge.GetSharpness();
462 Weight cWeight = 1.0f - pWeight;
463
464 mask.VertexWeight(0) = pWeight * 0.5f + cWeight * mask.VertexWeight(0);
465 mask.VertexWeight(1) = pWeight * 0.5f + cWeight * mask.VertexWeight(1);
466
467 int faceCount = mask.GetNumFaceWeights();
468 for (int i = 0; i < faceCount; ++i) {
469 mask.FaceWeight(i) *= cWeight;
470 }
471}
472
473//
474// The computation of a vertex-vertex mask requires inspection of creasing sharpness values
475// to determine what subdivision Rules apply to the parent and its child vertex, and also to
476// detect and apply a transition between two differing Rules. Using the protected methods to
477// assign specific masks, this implementation should serve all non-linear schemes (currently
478// Catmark and Loop) and only needs to be specialized for Bilinear to remove all unnecessary
479// complexity relating to creasing, Rules, etc.
480//
481// The implementation here is slightly complicated by combining two scenarios into one --
482// either the caller knows the parent and child rules and provides them, or they don't and
483// the Rules have to be determined from sharpness values. Even when the Rules are known and
484// provided though, there are cases where the parent and child sharpness values need to be
485// identified, so accounting for the unknown Rules too is not much of an added complication.
486//
487// The benefit of supporting specified Rules is that they can often be trivially
488// determined from context (e.g. a vertex derived from a face at a previous level will always
489// be smooth) rather than more generally, and at greater cost, inspecting neighboring and
490// they are often the same for parent and child.
491//
492// The overall process is as follows:
493//
494// - quickly detect the most common Smooth case when specified and return
495// - determine if sharpness for parent is required and gather if so
496// - if unspecified, determine the parent rule
497// - assign mask for the parent rule -- returning if Smooth/Dart
498// - return if child rule matches parent
499// - gather sharpness for child to determine or combine child rule
500// - if unspecified, determine the child rule, returning if it matches parent
501// - assign local mask for child rule
502// - combine local child mask with the parent mask
503//
504// Remember -- if the parent rule is specified but the child is not, this implies only one
505// of the two optional rules was specified and is meant to indicate there is no transition,
506// so the child rule should be assigned to be the same (wish the compiler would allow this
507// in default value assignment).
508//
509template <SchemeType SCHEME>
510template <typename VERTEX, typename MASK>
511void
513 MASK& mask,
514 Crease::Rule pRule,
515 Crease::Rule cRule) const {
516
517 // Quick assignment and return for the most common case:
518 if ((pRule == Crease::RULE_SMOOTH) || (pRule == Crease::RULE_DART)) {
519 assignSmoothMaskForVertex(vertex, mask);
520 return;
521 }
522 // If unspecified, assign the child rule to match the parent rule if specified:
523 if ((cRule == Crease::RULE_UNKNOWN) && (pRule != Crease::RULE_UNKNOWN)) {
524 cRule = pRule;
525 }
526 int valence = vertex.GetNumEdges();
527
528 //
529 // Determine if we need the parent edge sharpness values -- identify/gather if so
530 // and use it to compute the parent rule if unspecified:
531 //
532 float * pEdgeSharpnessBuffer = (float *)alloca(valence*sizeof(float)),
533 * pEdgeSharpness = 0,
534 pVertexSharpness = 0.0f;
535
536 bool requireParentSharpness = (pRule == Crease::RULE_UNKNOWN) ||
537 (pRule == Crease::RULE_CREASE) ||
538 (pRule != cRule);
539 if (requireParentSharpness) {
540 pVertexSharpness = vertex.GetSharpness();
541 pEdgeSharpness = vertex.GetSharpnessPerEdge(pEdgeSharpnessBuffer);
542
543 if (pRule == Crease::RULE_UNKNOWN) {
544 pRule = Crease(_options).DetermineVertexVertexRule(pVertexSharpness, valence, pEdgeSharpness);
545 }
546 }
547 if ((pRule == Crease::RULE_SMOOTH) || (pRule == Crease::RULE_DART)) {
548 assignSmoothMaskForVertex(vertex, mask);
549 return; // As done on entry, we can return immediately if parent is Smooth/Dart
550 } else if (pRule == Crease::RULE_CREASE) {
551 int creaseEnds[2];
552 Crease(_options).GetSharpEdgePairOfCrease(pEdgeSharpness, valence, creaseEnds);
553
554 assignCreaseMaskForVertex(vertex, mask, creaseEnds);
555 } else {
556 assignCornerMaskForVertex(vertex, mask);
557 }
558 if (cRule == pRule) return;
559
560 //
561 // Identify/gather child sharpness to combine masks for the two differing Rules:
562 //
563 Crease crease(_options);
564
565 float * cEdgeSharpnessBuffer = (float *)alloca(valence*sizeof(float)),
566 * cEdgeSharpness = vertex.GetChildSharpnessPerEdge(crease, cEdgeSharpnessBuffer),
567 cVertexSharpness = vertex.GetChildSharpness(crease);
568
569 if (cRule == Crease::RULE_UNKNOWN) {
570 cRule = crease.DetermineVertexVertexRule(cVertexSharpness, valence, cEdgeSharpness);
571 if (cRule == pRule) return;
572 }
573
574 //
575 // Initialize a local child mask, compute the fractional weight from parent and child
576 // sharpness values and combine the two masks:
577 //
578 typedef typename MASK::Weight Weight;
579
580 Weight * cMaskWeights = (Weight *)alloca((1 + 2 * valence)*sizeof(Weight));
581 LocalMask<Weight> cMask(cMaskWeights, cMaskWeights + 1, cMaskWeights + 1 + valence);
582
583 if ((cRule == Crease::RULE_SMOOTH) || (cRule == Crease::RULE_DART)) {
584 assignSmoothMaskForVertex(vertex, cMask);
585 } else if (cRule == Crease::RULE_CREASE) {
586 int creaseEnds[2];
587 Crease(_options).GetSharpEdgePairOfCrease(cEdgeSharpness, valence, creaseEnds);
588
589 assignCreaseMaskForVertex(vertex, cMask, creaseEnds);
590 } else {
591 assignCornerMaskForVertex(vertex, cMask);
592 }
593
594 Weight pWeight = crease.ComputeFractionalWeightAtVertex(pVertexSharpness, cVertexSharpness,
595 valence, pEdgeSharpness, cEdgeSharpness);
596 Weight cWeight = 1.0f - pWeight;
597
598 cMask.CombineVertexVertexMasks(cWeight, pWeight, mask);
599}
600
601//
602// The computation of limit masks for vertices:
603//
604template <SchemeType SCHEME>
605template <typename VERTEX, typename MASK>
606void
608 MASK& mask,
609 Crease::Rule rule) const {
610
611 if ((rule == Crease::RULE_SMOOTH) || (rule == Crease::RULE_DART)) {
612 assignSmoothLimitMask(vertex, mask);
613 } else if (rule == Crease::RULE_CREASE) {
614 float * edgeSharpness = (float *)alloca(vertex.GetNumEdges() * sizeof(float));
615 vertex.GetSharpnessPerEdge(edgeSharpness);
616
617 int creaseEnds[2];
618 Crease(_options).GetSharpEdgePairOfCrease(edgeSharpness, vertex.GetNumEdges(), creaseEnds);
619
620 assignCreaseLimitMask(vertex, mask, creaseEnds);
621 } else {
622 assignCornerLimitMask(vertex, mask);
623 }
624}
625
626template <SchemeType SCHEME>
627template <typename VERTEX, typename MASK>
628void
630 MASK& posMask,
631 MASK& tan1Mask,
632 MASK& tan2Mask,
633 Crease::Rule rule) const {
634
635 if ((rule == Crease::RULE_SMOOTH) || (rule == Crease::RULE_DART)) {
636 assignSmoothLimitMask(vertex, posMask);
637 assignSmoothLimitTangentMasks(vertex, tan1Mask, tan2Mask);
638 } else if (rule == Crease::RULE_CREASE) {
639 float * edgeSharpness = (float *)alloca(vertex.GetNumEdges() * sizeof(float));
640 vertex.GetSharpnessPerEdge(edgeSharpness);
641
642 int creaseEnds[2];
643 Crease(_options).GetSharpEdgePairOfCrease(edgeSharpness, vertex.GetNumEdges(), creaseEnds);
644
645 assignCreaseLimitMask(vertex, posMask, creaseEnds);
646 assignCreaseLimitTangentMasks(vertex, tan1Mask, tan2Mask, creaseEnds);
647 } else {
648 assignCornerLimitMask(vertex, posMask);
649 assignCornerLimitTangentMasks(vertex, tan1Mask, tan2Mask);
650 }
651}
652
653
654} // end namespace sdc
655
656} // end namespace OPENSUBDIV_VERSION
657using namespace OPENSUBDIV_VERSION;
658} // end namespace OpenSubdiv
659
660#endif /* OPENSUBDIV3_SDC_SCHEME_H */
Split
Enumerated type for all face splitting schemes.
Definition: types.h:47
Types, constants and utilities related to semi-sharp creasing – whose implementation is independent o...
Definition: crease.h:62
void GetSharpEdgePairOfCrease(float const *incidentEdgeSharpness, int incidentEdgeCount, int sharpEdgePair[2]) const
Definition: crease.h:228
Rule DetermineVertexVertexRule(float vertexSharpness, int incidentEdgeCount, float const *incidentEdgeSharpness) const
float ComputeFractionalWeightAtVertex(float vertexSharpness, float childVertexSharpness, int incidentEdgeCount, float const *incidentEdgeSharpness, float const *childEdgesSharpness) const
Transitional weighting: When the rules applicable to a parent vertex and its child differ,...
All supported options applying to subdivision scheme.
Definition: options.h:51
Scheme is a class template which provides all implementation for the subdivision schemes supported by...
Definition: scheme.h:66
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const
void assignCreaseMaskForVertex(VERTEX const &edge, MASK &mask, int const creaseEnds[2]) const
void ComputeVertexVertexMask(VERTEX const &vertexNeighborhood, MASK &vertexVertexMask, Crease::Rule parentRule=Crease::RULE_UNKNOWN, Crease::Rule childRule=Crease::RULE_UNKNOWN) const
Vertex-vertex masks If known, a single Rule or pair of Rules can be specified (indicating a crease tr...
Definition: scheme.h:512
void ComputeVertexLimitMask(VERTEX const &vertexNeighborhood, MASK &positionMask, Crease::Rule vertexRule) const
Limit masks for vertices – position and tangents These presume that a vertex is suitably isolated for...
Definition: scheme.h:607
void assignCreaseLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2, int const creaseEnds[2]) const
void assignCreaseMaskForEdge(EDGE const &edge, MASK &mask) const
Definition: scheme.h:317
void ComputeEdgeVertexMask(EDGE const &edgeNeighborhood, MASK &edgeVertexMask, Crease::Rule parentRule=Crease::RULE_UNKNOWN, Crease::Rule childRule=Crease::RULE_UNKNOWN) const
Edge-vertex masks If known, the Rule for the edge and/or the derived vertex can be specified to accel...
Definition: scheme.h:392
void assignSmoothLimitMask(VERTEX const &vertex, MASK &pos) const
void assignCornerMaskForVertex(VERTEX const &edge, MASK &mask) const
Definition: scheme.h:331
void assignCreaseLimitMask(VERTEX const &vertex, MASK &pos, int const creaseEnds[2]) const
void assignSmoothMaskForVertex(VERTEX const &edge, MASK &mask) const
void assignSmoothLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
void assignCornerLimitMask(VERTEX const &vertex, MASK &pos) const
Scheme(Options const &options)
Definition: scheme.h:72
void ComputeFaceVertexMask(FACE const &faceNeighborhood, MASK &faceVertexMask) const
Face-vertex masks - trivial for all current schemes.
Definition: scheme.h:348
void assignCornerLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
void SetOptions(const Options &newOptions)
Definition: scheme.h:75
Weight const & EdgeWeight(int index) const
Definition: scheme.h:232
void CombineVertexVertexMasks(Weight thisCoeff, Weight dstCoeff, USER_MASK &dst) const
Definition: scheme.h:249
Weight const & FaceWeight(int index) const
Definition: scheme.h:233
LocalMask(Weight *v, Weight *e, Weight *f)
Definition: scheme.h:215
Weight const & VertexWeight(int index) const
Definition: scheme.h:231