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 
37 namespace OpenSubdiv {
38 namespace OPENSUBDIV_VERSION {
39 
40 namespace Sdc {
41 
65 template <SchemeType SCHEME_TYPE>
66 class Scheme {
67 
68 public:
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,
100  Crease::Rule parentRule = Crease::RULE_UNKNOWN,
101  Crease::Rule childRule = Crease::RULE_UNKNOWN) const;
102 
112  template <typename VERTEX, typename MASK>
113  void ComputeVertexVertexMask(VERTEX const& vertexNeighborhood, MASK& vertexVertexMask,
114  Crease::Rule parentRule = Crease::RULE_UNKNOWN,
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();
155  static int GetRegularVertexValence();
156  static int GetLocalNeighborhoodSize();
157 
158 protected:
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 
195 private:
196  Options _options;
197 
198 protected:
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 mask 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 callers 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 //
314 template <SchemeType SCHEME>
315 template <typename EDGE, typename MASK>
316 inline void
317 Scheme<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 
328 template <SchemeType SCHEME>
329 template <typename VERTEX, typename MASK>
330 inline void
331 Scheme<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 //
345 template <SchemeType SCHEME>
346 template <typename FACE, typename MASK>
347 void
348 Scheme<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 need to be specialized it 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 //
389 template <SchemeType SCHEME>
390 template <typename EDGE, typename MASK>
391 void
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 have 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 need 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 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 //
509 template <SchemeType SCHEME>
510 template <typename VERTEX, typename MASK>
511 void
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  // Intialize 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 //
604 template <SchemeType SCHEME>
605 template <typename VERTEX, typename MASK>
606 void
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 
626 template <SchemeType SCHEME>
627 template <typename VERTEX, typename MASK>
628 void
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
657 using namespace OPENSUBDIV_VERSION;
658 } // end namespace OpenSubdiv
659 
660 #endif /* OPENSUBDIV3_SDC_SCHEME_H */
Rule DetermineVertexVertexRule(float vertexSharpness, int incidentEdgeCount, float const *incidentEdgeSharpness) const
Weight const & FaceWeight(int index) const
Definition: scheme.h:233
Split
Enumerated type for all face splitting scheme.
Definition: types.h:47
void assignCornerLimitMask(VERTEX const &vertex, MASK &pos) const
void assignSmoothMaskForVertex(VERTEX const &edge, MASK &mask) const
void SetOptions(const Options &newOptions)
Definition: scheme.h:75
void assignCreaseMaskForEdge(EDGE const &edge, MASK &mask) const
Definition: scheme.h:317
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 assignCornerMaskForVertex(VERTEX const &edge, MASK &mask) const
Definition: scheme.h:331
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
Scheme is a class template which provides all implementation for the subdivision schemes supported by...
Definition: scheme.h:66
void assignCreaseMaskForVertex(VERTEX const &edge, MASK &mask, int const creaseEnds[2]) const
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const
Scheme(Options const &options)
Definition: scheme.h:72
All supported options applying to subdivision scheme.
Definition: options.h:51
void assignSmoothLimitMask(VERTEX const &vertex, MASK &pos) const
Weight const & EdgeWeight(int index) const
Definition: scheme.h:232
void assignCreaseLimitMask(VERTEX const &vertex, MASK &pos, int const creaseEnds[2]) 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...
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 fo...
Definition: scheme.h:607
void GetSharpEdgePairOfCrease(float const *incidentEdgeSharpness, int incidentEdgeCount, int sharpEdgePair[2]) const
Definition: crease.h:228
void ComputeFaceVertexMask(FACE const &faceNeighborhood, MASK &faceVertexMask) const
Face-vertex masks - trivial for all current schemes.
Definition: scheme.h:348
void assignCreaseLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2, int const creaseEnds[2]) const
Weight const & VertexWeight(int index) const
Definition: scheme.h:231
LocalMask(Weight *v, Weight *e, Weight *f)
Definition: scheme.h:215
void CombineVertexVertexMasks(Weight thisCoeff, Weight dstCoeff, USER_MASK &dst) const
Definition: scheme.h:249
Types, constants and utilities related to semi-sharp creasing – whose implementation is independent ...
Definition: crease.h:62
void assignCornerLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
void assignSmoothLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const