loopScheme.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_LOOP_SCHEME_H
25 #define OPENSUBDIV3_SDC_LOOP_SCHEME_H
26
27 #include "../version.h"
28
29 #include "../sdc/scheme.h"
30
31 #include <cassert>
32
33 namespace OpenSubdiv {
34 namespace OPENSUBDIV_VERSION {
35 namespace Sdc {
36
37
38 //
39 // Specializations for Sdc::Scheme<SCHEME_LOOP>:
40 //
41 //
42
43 //
44 // Loop traits:
45 //
46 template <>
47 inline Split Scheme<SCHEME_LOOP>::GetTopologicalSplitType() { return SPLIT_TO_TRIS; }
48
49 template <>
50 inline int Scheme<SCHEME_LOOP>::GetRegularFaceSize() { return 3; }
51
52 template <>
53 inline int Scheme<SCHEME_LOOP>::GetRegularVertexValence() { return 6; }
54
55 template <>
56 inline int Scheme<SCHEME_LOOP>::GetLocalNeighborhoodSize() { return 1; }
57
58
59 //
60 // Protected methods to assign the two types of masks for an edge-vertex --
61 // Crease and Smooth.
62 //
63 // The Crease case does not really need to be speciailized, though it may be
64 // preferable to define all explicitly here.
65 //
66 template <>
67 template <typename EDGE, typename MASK>
68 inline void
69 Scheme<SCHEME_LOOP>::assignCreaseMaskForEdge(EDGE const&, MASK& mask) const
70 {
71 mask.SetNumVertexWeights(2);
72 mask.SetNumEdgeWeights(0);
73 mask.SetNumFaceWeights(0);
74 mask.SetFaceWeightsForFaceCenters(false);
75
76 mask.VertexWeight(0) = 0.5f;
77 mask.VertexWeight(1) = 0.5f;
78 }
79
80 template <>
81 template <typename EDGE, typename MASK>
82 inline void
83 Scheme<SCHEME_LOOP>::assignSmoothMaskForEdge(EDGE const& edge, MASK& mask) const
84 {
85 int faceCount = edge.GetNumFaces();
86
87 mask.SetNumVertexWeights(2);
88 mask.SetNumEdgeWeights(0);
89 mask.SetNumFaceWeights(faceCount);
90 mask.SetFaceWeightsForFaceCenters(false);
91
92 //
93 // This is where we run into the issue of "face weights" -- we want to weight the
94 // face-centers for Catmark, but face-centers are not generated for Loop. So do
95 // we make assumptions on how the mask is used, assign some property to the mask
96 // to indicate how they were assigned, or take input from the mask itself?
97 //
98 // Regardless, we have two choices:
99 // - face-weights are for the vertices opposite the edge (as in Hbr):
100 // vertex weights = 0.375f;
101 // face weights = 0.125f;
102 //
103 // - face-weights are for the face centers:
104 // vertex weights = 0.125f;
105 // face weights = 0.375f;
106 //
107 // Coincidentally the coefficients are the same but reversed.
108 //
109 typedef typename MASK::Weight Weight;
110
111 Weight vWeight = mask.AreFaceWeightsForFaceCenters() ? 0.125f : 0.375f;
112 Weight fWeight = mask.AreFaceWeightsForFaceCenters() ? 0.375f : 0.125f;
113
114 mask.VertexWeight(0) = vWeight;
115 mask.VertexWeight(1) = vWeight;
116
117 if (faceCount == 2) {
118 mask.FaceWeight(0) = fWeight;
119 mask.FaceWeight(1) = fWeight;
120 } else {
121 // The non-manifold case is not clearly defined -- we adjust the above
122 // face-weight to preserve the ratio of edge-center and face-centers:
123 fWeight *= 2.0f / (Weight) faceCount;
124 for (int i = 0; i < faceCount; ++i) {
125 mask.FaceWeight(i) = fWeight;
126 }
127 }
128 }
129
130
131 //
132 // Protected methods to assign the three types of masks for a vertex-vertex --
133 // Corner, Crease and Smooth (Dart is the same as Smooth).
134 //
135 // Corner and Crease do not really need to be speciailized, though it may be
136 // preferable to define all explicitly here.
137 //
138 template <>
139 template <typename VERTEX, typename MASK>
140 inline void
141 Scheme<SCHEME_LOOP>::assignCornerMaskForVertex(VERTEX const&, MASK& mask) const
142 {
143 mask.SetNumVertexWeights(1);
144 mask.SetNumEdgeWeights(0);
145 mask.SetNumFaceWeights(0);
146 mask.SetFaceWeightsForFaceCenters(false);
147
148 mask.VertexWeight(0) = 1.0f;
149 }
150
151 template <>
152 template <typename VERTEX, typename MASK>
153 inline void
154 Scheme<SCHEME_LOOP>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& mask,
155 int const creaseEnds[2]) const {
156 typedef typename MASK::Weight Weight;
157
158 int valence = vertex.GetNumEdges();
159
160 mask.SetNumVertexWeights(1);
161 mask.SetNumEdgeWeights(valence);
162 mask.SetNumFaceWeights(0);
163 mask.SetFaceWeightsForFaceCenters(false);
164
165 Weight vWeight = 0.75f;
166 Weight eWeight = 0.125f;
167
168 mask.VertexWeight(0) = vWeight;
169 for (int i = 0; i < valence; ++i) {
170 mask.EdgeWeight(i) = 0.0f;
171 }
172 mask.EdgeWeight(creaseEnds[0]) = eWeight;
173 mask.EdgeWeight(creaseEnds[1]) = eWeight;
174 }
175
176 template <>
177 template <typename VERTEX, typename MASK>
178 inline void
179 Scheme<SCHEME_LOOP>::assignSmoothMaskForVertex(VERTEX const& vertex, MASK& mask) const
180 {
181 typedef typename MASK::Weight Weight;
182
183 int valence = vertex.GetNumFaces();
184
185 mask.SetNumVertexWeights(1);
186 mask.SetNumEdgeWeights(valence);
187 mask.SetNumFaceWeights(0);
188 mask.SetFaceWeightsForFaceCenters(false);
189
190 // Specialize for the regular case: 1/16 per edge-vert, 5/8 for the vert itself:
191 Weight eWeight = (Weight) 0.0625f;
192 Weight vWeight = (Weight) 0.625f;
193
194 if (valence != 6) {
195 // From HbrLoopSubdivision<T>::Subdivide(mesh, vertex):
196 // - could use some lookup tables here for common irregular valence (5, 7, 8)
197 // or all of these cosf() calls will be adding up...
198
199 Weight invValence = 1.0f / (Weight) valence;
200 Weight beta = 0.25f * cosf((Weight)M_PI * 2.0f * invValence) + 0.375f;
201
202 eWeight = (0.625f - (beta * beta)) * invValence;;
203 vWeight = 1.0f - (eWeight * (Weight)valence);
204 }
205
206 mask.VertexWeight(0) = vWeight;
207 for (int i = 0; i < valence; ++i) {
208 mask.EdgeWeight(i) = eWeight;
209 }
210 }
211
212
213 //
214 // Limit masks for position:
215 //
216 template <>
217 template <typename VERTEX, typename MASK>
218 inline void
219 Scheme<SCHEME_LOOP>::assignCornerLimitMask(VERTEX const& /* vertex */, MASK& posMask) const {
220
221 posMask.SetNumVertexWeights(1);
222 posMask.SetNumEdgeWeights(0);
223 posMask.SetNumFaceWeights(0);
224 posMask.SetFaceWeightsForFaceCenters(false);
225
226 posMask.VertexWeight(0) = 1.0f;
227 }
228
229 template <>
230 template <typename VERTEX, typename MASK>
231 inline void
232 Scheme<SCHEME_LOOP>::assignCreaseLimitMask(VERTEX const& vertex, MASK& posMask,
233 int const creaseEnds[2]) const {
234
235 typedef typename MASK::Weight Weight;
236
237 int valence = vertex.GetNumEdges();
238
239 posMask.SetNumVertexWeights(1);
240 posMask.SetNumEdgeWeights(valence);
241 posMask.SetNumFaceWeights(0);
242 posMask.SetFaceWeightsForFaceCenters(false);
243
244 //
245 // The refinement mask for a crease vertex is (1/8, 3/4, 1/8) and for a crease
246 // edge is (1/2, 1/2) -- producing a uniform B-spline curve along the crease
247 // (boundary) whether the vertex or its crease is regular or not. The limit
248 // mask is therefore (1/6, 2/3, 1/6) for ALL cases.
249 //
250 // An alternative limit mask (1/5, 3/5, 1/5) is often published for use either
251 // for irregular crease vertices or for all crease/boundary vertices, but this
252 // is based on an alternate refinement mask for the edge -- (3/8, 5/8) versus
253 // the usual (1/2, 1/2) -- and will not produce the B-spline curve desired.
254 //
255 Weight vWeight = 4.0f / 6.0f;
256 Weight eWeight = 1.0f / 6.0f;
257
258 posMask.VertexWeight(0) = vWeight;
259 for (int i = 0; i < valence; ++i) {
260 posMask.EdgeWeight(i) = 0.0f;
261 }
262 posMask.EdgeWeight(creaseEnds[0]) = eWeight;
263 posMask.EdgeWeight(creaseEnds[1]) = eWeight;
264 }
265
266 template <>
267 template <typename VERTEX, typename MASK>
268 inline void
269 Scheme<SCHEME_LOOP>::assignSmoothLimitMask(VERTEX const& vertex, MASK& posMask) const {
270
271 typedef typename MASK::Weight Weight;
272
273 int valence = vertex.GetNumFaces();
274 assert(valence != 2);
275
276 posMask.SetNumVertexWeights(1);
277 posMask.SetNumEdgeWeights(valence);
278 posMask.SetNumFaceWeights(0);
279 posMask.SetFaceWeightsForFaceCenters(false);
280
281 // Specialize for the regular case: 1/12 per edge-vert, 1/2 for the vert itself:
282 if (valence == 6) {
283 Weight eWeight = 1.0f / 12.0f;
284 Weight vWeight = 0.5f;
285
286 posMask.VertexWeight(0) = vWeight;
287
288 posMask.EdgeWeight(0) = eWeight;
289 posMask.EdgeWeight(1) = eWeight;
290 posMask.EdgeWeight(2) = eWeight;
291 posMask.EdgeWeight(3) = eWeight;
292 posMask.EdgeWeight(4) = eWeight;
293 posMask.EdgeWeight(5) = eWeight;
294
295 } else {
296 Weight invValence = 1.0f / valence;
297
298 Weight beta = 0.25f * cosf((Weight)M_PI * 2.0f * invValence) + 0.375f;
299 beta = (0.625f - (beta * beta)) * invValence;;
300
301 Weight eWeight = 1.0f / (valence + 3.0f / (8.0f * beta));
302 Weight vWeight = (Weight)(1.0f - (eWeight * valence));
303
304 posMask.VertexWeight(0) = vWeight;
305 for (int i = 0; i < valence; ++i) {
306 posMask.EdgeWeight(i) = eWeight;
307 }
308 }
309 }
310
311 /*
312 // Limit masks for tangents:
313 //
314 // A note on tangent magnitudes:
315 //
316 // Several formulae exist for limit tangents at a vertex to accomodate the
317 // different topological configurations around the vertex. While these produce
318 // the desired direction, there is inconsistency in the resulting magnitudes.
319 // Ideally a regular mesh of uniformly shaped triangles with similar edge lengths
320 // should produce tangents of similar magnitudes throughout -- including corners
321 // and boundaries. So some of the common formulae for these are adjusted with
322 // scale factors.
323 //
324 // For uses where magnitude does not matter, this scaling should be irrelevant.
325 // But just as with patches, where the magnitudes of partial derivates are
326 // consistent between similar patches, the magnitudes of limit tangents should
327 // also be similar.
328 //
329 // The reference tangents, in terms of magnitudes, are those produced by the
330 // limit tangent mask for smooth interior vertices, for which well established
331 // sin/cos formulae apply -- these remain unscaled. Formulae for the other
332 // crease/boundary, corner tangents and irregular cases are scaled to be more
333 // consistent with these.
334 //
335 // The crease/boundary tangents for the regular case can be viewed as derived
336 // from the smooth interior masks with two "phantom" points extrapolated across
337 // the regular boundary:
338 //
339 // v3 v2
340 // X - - - - - X
341 // / \ / \
342 // / \ / \
343 // v4 X - - - - - X - - - - - X v1
344 // . . 0 . .
345 // . . . .
346 // . . . .
347 // (v5) (v6)
348 //
349 // where v5 = v0 + (v4 - v3) and v6 = v0 + v1 - v2.
350 //
351 // When the standard limit tangent mask is applied, the cosines of increments
352 // of pi/3 gives us coefficients that are mutliples of 1/2, leading to the first
353 // tangent T1 = 3/2 * (v1 - v4), rather than the widely used T1 = v1 - v4. So
354 // this scale factor of 3/2 is applied to insure tangents along the boundaries
355 // are of similar magnitude as tangents in the immediate interior (which may be
356 // parallel).
357 //
358 // Tangents at corners are essentially a form of boundary tangent, and so its
359 // simple difference formula is scaled to be consistent with adjoining boundary
360 // tangents -- not just with the 3/2 factor from above, but with an additional
361 // 2.0 to compensate for the fact that the difference of only side of the vertex
362 // is considered here. The resulting scale factor of 3.0 for the regular corner
363 // is what similarly arises by extrapolating an interior region around the
364 // vertex and using the interior mask for the first tangent.
365 //
366 // The cross-tangent formula for the regular crease/boundary is similarly found
367 // from the above construction of the boundary, but the commonly used weights of
368 // +/- 1 and 2 result from omitting the common factor of sqrt(3)/2 (arising from
369 // the sines of increments of pi/3). With that scale factor close to one, it has
370 // less impact than the irregular cases, which are analogous to corner tangents
371 // in that differences on only one side of the vertex are considered. While a
372 // scaling of 3.0 is similarly understandable for the valence 2 and 3 cases, it is
373 // less obvious in the irregular formula for valence > 4, but similarly effective.
374 //
375 // The end result of these adjustments should be a set of limit tangents that are
376 // of similar magnitude over a regular mesh including boundaries and corners.
377 */
378 template <>
379 template <typename VERTEX, typename MASK>
380 inline void
381 Scheme<SCHEME_LOOP>::assignCornerLimitTangentMasks(VERTEX const& vertex,
382 MASK& tan1Mask, MASK& tan2Mask) const {
383
384 int valence = vertex.GetNumEdges();
385
386 tan1Mask.SetNumVertexWeights(1);
387 tan1Mask.SetNumEdgeWeights(valence);
388 tan1Mask.SetNumFaceWeights(0);
389 tan1Mask.SetFaceWeightsForFaceCenters(false);
390
391 tan2Mask.SetNumVertexWeights(1);
392 tan2Mask.SetNumEdgeWeights(valence);
393 tan2Mask.SetNumFaceWeights(0);
394 tan2Mask.SetFaceWeightsForFaceCenters(false);
395
396 // See note above regarding scale factor of 3.0:
397 tan1Mask.VertexWeight(0) = -3.0f;
398 tan1Mask.EdgeWeight(0) = 3.0f;
399 tan1Mask.EdgeWeight(1) = 0.0f;
400
401 tan2Mask.VertexWeight(0) = -3.0f;
402 tan2Mask.EdgeWeight(0) = 0.0f;
403 tan2Mask.EdgeWeight(1) = 3.0f;
404
405 // Should be at least 2 edges -- be sure to clear weights for any more:
406 for (int i = 2; i < valence; ++i) {
407 tan1Mask.EdgeWeight(i) = 0.0f;
408 tan2Mask.EdgeWeight(i) = 0.0f;
409 }
410 }
411
412 template <>
413 template <typename VERTEX, typename MASK>
414 inline void
415 Scheme<SCHEME_LOOP>::assignCreaseLimitTangentMasks(VERTEX const& vertex,
416 MASK& tan1Mask, MASK& tan2Mask, int const creaseEnds[2]) const {
417
418 typedef typename MASK::Weight Weight;
419
420 //
421 // First, the tangent along the crease:
422 // The first crease edge is considered the "leading" edge of the span
423 // of surface for which we are evaluating tangents and the second edge the
424 // "trailing edge". By convention, the tangent along the crease is oriented
425 // in the direction of the leading edge.
426 //
427 int valence = vertex.GetNumEdges();
428
429 tan1Mask.SetNumVertexWeights(1);
430 tan1Mask.SetNumEdgeWeights(valence);
431 tan1Mask.SetNumFaceWeights(0);
432 tan1Mask.SetFaceWeightsForFaceCenters(false);
433
434 tan1Mask.VertexWeight(0) = 0.0f;
435 for (int i = 0; i < valence; ++i) {
436 tan1Mask.EdgeWeight(i) = 0.0f;
437 }
438
439 // See the note above regarding scale factor of 1.5:
440 tan1Mask.EdgeWeight(creaseEnds[0]) = 1.5f;
441 tan1Mask.EdgeWeight(creaseEnds[1]) = -1.5f;
442
443 //
444 // Second, the tangent across the interior faces:
445 // Note this is ambigous for an interior vertex. We currently return
446 // the tangent for the surface in the counter-clockwise span between the
447 // leading and trailing edges that form the crease. Given the expected
448 // computation of a surface normal as Tan1 X Tan2, this tangent should be
449 // oriented "inward" from the crease/boundary -- across the surface rather
450 // than outward and away from it.
451 //
452 // There is inconsistency in the orientation of this tangent in commonly
453 // published results: the general formula provided for arbitrary valence
454 // has the tangent pointing across the crease and "outward" from the surface,
455 // while the special cases for regular valence and lower have the tangent
456 // pointing across the surface and "inward" from the crease. So if we are
457 // to consistently orient the first tangent along the crease, regardless of
458 // the interior topology, we have to correct this. With the first tangent
459 // following the direction of the leading crease edge, we want the second
460 // tangent pointing inward/across the surface -- so we flip the result of
461 // the general formula.
462 //
463 tan2Mask.SetNumVertexWeights(1);
464 tan2Mask.SetNumEdgeWeights(valence);
465 tan2Mask.SetNumFaceWeights(0);
466 tan2Mask.SetFaceWeightsForFaceCenters(false);
467
468 for (int i = 0; i < creaseEnds[0]; ++i) {
469 tan2Mask.EdgeWeight(i) = 0.0f;
470 }
471 int interiorEdgeCount = creaseEnds[1] - creaseEnds[0] - 1;
472 if (interiorEdgeCount == 2) {
473 // See note above regarding scale factor of (sin(60 degs) == sqrt(3)/2:
474
475 static Weight const Root3 = (Weight) 1.73205080756887729352f;
476 static Weight const Root3by2 = (Weight) (Root3 * 0.5);
477
478 tan2Mask.VertexWeight(0) = -Root3;
479
480 tan2Mask.EdgeWeight(creaseEnds[0]) = -Root3by2;
481 tan2Mask.EdgeWeight(creaseEnds[1]) = -Root3by2;
482
483 tan2Mask.EdgeWeight(creaseEnds[0] + 1) = Root3;
484 tan2Mask.EdgeWeight(creaseEnds[0] + 2) = Root3;
485 } else if (interiorEdgeCount > 2) {
486 // See notes above regarding scale factor of -3.0 (-1 for orientation,
487 // 2.0 for considering the region as a half-disk, and 1.5 in keeping
488 // with the crease tangent):
489
490 double theta = M_PI / (interiorEdgeCount + 1);
491
492 Weight cWeight = -3.0f * (Weight) std::sin(theta);
493 Weight eWeightCoeff = -3.0f * (2.0f * (Weight) std::cos(theta) - 2.0f);
494
495 tan2Mask.VertexWeight(0) = 0.0f;
496
497 tan2Mask.EdgeWeight(creaseEnds[0]) = cWeight;
498 tan2Mask.EdgeWeight(creaseEnds[1]) = cWeight;
499
500 for (int i = 1; i <= interiorEdgeCount; ++i) {
501 tan2Mask.EdgeWeight(creaseEnds[0] + i) = eWeightCoeff * (Weight) std::sin(i * theta);
502 }
503 } else if (interiorEdgeCount == 1) {
504 // See notes above regarding scale factor of 3.0:
505
506 tan2Mask.VertexWeight(0) = -3.0f;
507
508 tan2Mask.EdgeWeight(creaseEnds[0]) = 0.0f;
509 tan2Mask.EdgeWeight(creaseEnds[1]) = 0.0f;
510
511 tan2Mask.EdgeWeight(creaseEnds[0] + 1) = 3.0f;
512 } else {
513 // See notes above regarding scale factor of 3.0:
514
515 tan2Mask.VertexWeight(0) = -6.0f;
516
517 tan2Mask.EdgeWeight(creaseEnds[0]) = 3.0f;
518 tan2Mask.EdgeWeight(creaseEnds[1]) = 3.0f;
519 }
520 for (int i = creaseEnds[1] + 1; i < valence; ++i) {
521 tan2Mask.EdgeWeight(i) = 0.0f;
522 }
523 }
524
525 template <>
526 template <typename VERTEX, typename MASK>
527 inline void
528 Scheme<SCHEME_LOOP>::assignSmoothLimitTangentMasks(VERTEX const& vertex,
529 MASK& tan1Mask, MASK& tan2Mask) const {
530
531 typedef typename MASK::Weight Weight;
532
533 int valence = vertex.GetNumFaces();
534 assert(valence != 2);
535
536 tan1Mask.SetNumVertexWeights(1);
537 tan1Mask.SetNumEdgeWeights(valence);
538 tan1Mask.SetNumFaceWeights(0);
539 tan1Mask.SetFaceWeightsForFaceCenters(false);
540
541 tan2Mask.SetNumVertexWeights(1);
542 tan2Mask.SetNumEdgeWeights(valence);
543 tan2Mask.SetNumFaceWeights(0);
544 tan2Mask.SetFaceWeightsForFaceCenters(false);
545
546 tan1Mask.VertexWeight(0) = 0.0f;
547 tan2Mask.VertexWeight(0) = 0.0f;
548
549 if (valence == 6) {
550 static Weight const Root3by2 = (Weight)(0.5f * 1.73205080756887729352f);
551
552 tan1Mask.EdgeWeight(0) = 1.0f;
553 tan1Mask.EdgeWeight(1) = 0.5f;
554 tan1Mask.EdgeWeight(2) = -0.5f;
555 tan1Mask.EdgeWeight(3) = -1.0f;
556 tan1Mask.EdgeWeight(4) = -0.5f;
557 tan1Mask.EdgeWeight(5) = 0.5f;
558
559 tan2Mask.EdgeWeight(0) = 0.0f;
560 tan2Mask.EdgeWeight(1) = Root3by2;
561 tan2Mask.EdgeWeight(2) = Root3by2;
562 tan2Mask.EdgeWeight(3) = 0.0f;
563 tan2Mask.EdgeWeight(4) = -Root3by2;
564 tan2Mask.EdgeWeight(5) = -Root3by2;
565 } else {
566 Weight alpha = (Weight) (2.0f * M_PI / valence);
567 for (int i = 0; i < valence; ++i) {
568 double alphaI = alpha * i;
569 tan1Mask.EdgeWeight(i) = (Weight) std::cos(alphaI);
570 tan2Mask.EdgeWeight(i) = (Weight) std::sin(alphaI);
571 }
572 }
573 }
574
575 } // end namespace Sdc
576 } // end namespace OPENSUBDIV_VERSION
577 using namespace OPENSUBDIV_VERSION;
578 } // end namespace OpenSubdiv
579
580 #endif /* OPENSUBDIV3_SDC_LOOP_SCHEME_H */
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::GetRegularVertexValence
static int GetRegularVertexValence()
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignCreaseLimitMask
void assignCreaseLimitMask(VERTEX const &vertex, MASK &pos, int const creaseEnds[2]) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignCreaseMaskForEdge
void assignCreaseMaskForEdge(EDGE const &edge, MASK &mask) const
Definition: scheme.h:317
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignCreaseLimitTangentMasks
void assignCreaseLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2, int const creaseEnds[2]) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignCreaseMaskForVertex
void assignCreaseMaskForVertex(VERTEX const &edge, MASK &mask, int const creaseEnds[2]) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::GetTopologicalSplitType
static Split GetTopologicalSplitType()
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::SPLIT_TO_TRIS
Used by Loop.
Definition: types.h:49
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::GetRegularFaceSize
static int GetRegularFaceSize()
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignSmoothLimitTangentMasks
void assignSmoothLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Split
Split
Enumerated type for all face splitting scheme.
Definition: types.h:47
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignSmoothMaskForVertex
void assignSmoothMaskForVertex(VERTEX const &edge, MASK &mask) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::GetLocalNeighborhoodSize
static int GetLocalNeighborhoodSize()
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignSmoothLimitMask
void assignSmoothLimitMask(VERTEX const &vertex, MASK &pos) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignCornerMaskForVertex
void assignCornerMaskForVertex(VERTEX const &edge, MASK &mask) const
Definition: scheme.h:331
OpenSubdiv
Definition: error.h:30
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignCornerLimitMask
void assignCornerLimitMask(VERTEX const &vertex, MASK &pos) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignCornerLimitTangentMasks
void assignCornerLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
OpenSubdiv::OPENSUBDIV_VERSION::Sdc::Scheme::assignSmoothMaskForEdge
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const