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