24 #ifndef OPENSUBDIV3_SDC_LOOP_SCHEME_H
25 #define OPENSUBDIV3_SDC_LOOP_SCHEME_H
27 #include "../version.h"
29 #include "../sdc/scheme.h"
34 namespace OpenSubdiv {
35 namespace OPENSUBDIV_VERSION {
68 template <
typename EDGE,
typename MASK>
72 mask.SetNumVertexWeights(2);
73 mask.SetNumEdgeWeights(0);
74 mask.SetNumFaceWeights(0);
75 mask.SetFaceWeightsForFaceCenters(
false);
77 mask.VertexWeight(0) = 0.5f;
78 mask.VertexWeight(1) = 0.5f;
82 template <
typename EDGE,
typename MASK>
86 int faceCount = edge.GetNumFaces();
88 mask.SetNumVertexWeights(2);
89 mask.SetNumEdgeWeights(0);
90 mask.SetNumFaceWeights(faceCount);
91 mask.SetFaceWeightsForFaceCenters(
false);
110 typedef typename MASK::Weight Weight;
112 Weight vWeight = mask.AreFaceWeightsForFaceCenters() ? 0.125f : 0.375f;
113 Weight fWeight = mask.AreFaceWeightsForFaceCenters() ? 0.375f : 0.125f;
115 mask.VertexWeight(0) = vWeight;
116 mask.VertexWeight(1) = vWeight;
118 if (faceCount == 2) {
119 mask.FaceWeight(0) = fWeight;
120 mask.FaceWeight(1) = fWeight;
124 fWeight *= 2.0f / (Weight) faceCount;
125 for (
int i = 0; i < faceCount; ++i) {
126 mask.FaceWeight(i) = fWeight;
140 template <
typename VERTEX,
typename MASK>
144 mask.SetNumVertexWeights(1);
145 mask.SetNumEdgeWeights(0);
146 mask.SetNumFaceWeights(0);
147 mask.SetFaceWeightsForFaceCenters(
false);
149 mask.VertexWeight(0) = 1.0f;
153 template <
typename VERTEX,
typename MASK>
156 int const creaseEnds[2])
const {
157 typedef typename MASK::Weight Weight;
159 int valence = vertex.GetNumEdges();
161 mask.SetNumVertexWeights(1);
162 mask.SetNumEdgeWeights(valence);
163 mask.SetNumFaceWeights(0);
164 mask.SetFaceWeightsForFaceCenters(
false);
166 Weight vWeight = 0.75f;
167 Weight eWeight = 0.125f;
169 mask.VertexWeight(0) = vWeight;
170 for (
int i = 0; i < valence; ++i) {
171 mask.EdgeWeight(i) = 0.0f;
173 mask.EdgeWeight(creaseEnds[0]) = eWeight;
174 mask.EdgeWeight(creaseEnds[1]) = eWeight;
178 template <
typename VERTEX,
typename MASK>
182 typedef typename MASK::Weight Weight;
184 int valence = vertex.GetNumFaces();
186 mask.SetNumVertexWeights(1);
187 mask.SetNumEdgeWeights(valence);
188 mask.SetNumFaceWeights(0);
189 mask.SetFaceWeightsForFaceCenters(
false);
192 Weight eWeight = (Weight) 0.0625f;
193 Weight vWeight = (Weight) 0.625f;
200 double dValence = (double) valence;
201 double invValence = 1.0f / dValence;
202 double cosTheta = std::cos(M_PI * 2.0f * invValence);
204 double beta = 0.25f * cosTheta + 0.375f;
206 eWeight = (Weight) ((0.625f - (beta * beta)) * invValence);
207 vWeight = (Weight) (1.0f - (eWeight * dValence));
210 mask.VertexWeight(0) = vWeight;
211 for (
int i = 0; i < valence; ++i) {
212 mask.EdgeWeight(i) = eWeight;
221 template <
typename VERTEX,
typename MASK>
225 posMask.SetNumVertexWeights(1);
226 posMask.SetNumEdgeWeights(0);
227 posMask.SetNumFaceWeights(0);
228 posMask.SetFaceWeightsForFaceCenters(
false);
230 posMask.VertexWeight(0) = 1.0f;
234 template <
typename VERTEX,
typename MASK>
237 int const creaseEnds[2])
const {
239 typedef typename MASK::Weight Weight;
241 int valence = vertex.GetNumEdges();
243 posMask.SetNumVertexWeights(1);
244 posMask.SetNumEdgeWeights(valence);
245 posMask.SetNumFaceWeights(0);
246 posMask.SetFaceWeightsForFaceCenters(
false);
259 Weight vWeight = (Weight) (4.0 / 6.0);
260 Weight eWeight = (Weight) (1.0 / 6.0);
262 posMask.VertexWeight(0) = vWeight;
263 for (
int i = 0; i < valence; ++i) {
264 posMask.EdgeWeight(i) = 0.0f;
266 posMask.EdgeWeight(creaseEnds[0]) = eWeight;
267 posMask.EdgeWeight(creaseEnds[1]) = eWeight;
271 template <
typename VERTEX,
typename MASK>
275 typedef typename MASK::Weight Weight;
277 int valence = vertex.GetNumFaces();
279 posMask.SetNumVertexWeights(1);
280 posMask.SetNumEdgeWeights(valence);
281 posMask.SetNumFaceWeights(0);
282 posMask.SetFaceWeightsForFaceCenters(
false);
286 Weight eWeight = (Weight) (1.0 / 12.0);
287 Weight vWeight = 0.5f;
289 posMask.VertexWeight(0) = vWeight;
291 posMask.EdgeWeight(0) = eWeight;
292 posMask.EdgeWeight(1) = eWeight;
293 posMask.EdgeWeight(2) = eWeight;
294 posMask.EdgeWeight(3) = eWeight;
295 posMask.EdgeWeight(4) = eWeight;
296 posMask.EdgeWeight(5) = eWeight;
299 double dValence = (double) valence;
300 double invValence = 1.0f / dValence;
301 double cosTheta = std::cos(M_PI * 2.0f * invValence);
303 double beta = 0.25f * cosTheta + 0.375f;
304 double gamma = (0.625f - (beta * beta)) * invValence;
306 Weight eWeight = (Weight) (1.0f / (dValence + 3.0f / (8.0f * gamma)));
307 Weight vWeight = (Weight) (1.0f - (eWeight * dValence));
309 posMask.VertexWeight(0) = vWeight;
310 for (
int i = 0; i < valence; ++i) {
311 posMask.EdgeWeight(i) = eWeight;
384 template <
typename VERTEX,
typename MASK>
387 MASK& tan1Mask, MASK& tan2Mask)
const {
389 int valence = vertex.GetNumEdges();
391 tan1Mask.SetNumVertexWeights(1);
392 tan1Mask.SetNumEdgeWeights(valence);
393 tan1Mask.SetNumFaceWeights(0);
394 tan1Mask.SetFaceWeightsForFaceCenters(
false);
396 tan2Mask.SetNumVertexWeights(1);
397 tan2Mask.SetNumEdgeWeights(valence);
398 tan2Mask.SetNumFaceWeights(0);
399 tan2Mask.SetFaceWeightsForFaceCenters(
false);
402 tan1Mask.VertexWeight(0) = -3.0f;
403 tan1Mask.EdgeWeight(0) = 3.0f;
404 tan1Mask.EdgeWeight(1) = 0.0f;
406 tan2Mask.VertexWeight(0) = -3.0f;
407 tan2Mask.EdgeWeight(0) = 0.0f;
408 tan2Mask.EdgeWeight(1) = 3.0f;
411 for (
int i = 2; i < valence; ++i) {
412 tan1Mask.EdgeWeight(i) = 0.0f;
413 tan2Mask.EdgeWeight(i) = 0.0f;
418 template <
typename VERTEX,
typename MASK>
421 MASK& tan1Mask, MASK& tan2Mask,
int const creaseEnds[2])
const {
423 typedef typename MASK::Weight Weight;
432 int valence = vertex.GetNumEdges();
434 tan1Mask.SetNumVertexWeights(1);
435 tan1Mask.SetNumEdgeWeights(valence);
436 tan1Mask.SetNumFaceWeights(0);
437 tan1Mask.SetFaceWeightsForFaceCenters(
false);
439 tan1Mask.VertexWeight(0) = 0.0f;
440 for (
int i = 0; i < valence; ++i) {
441 tan1Mask.EdgeWeight(i) = 0.0f;
445 tan1Mask.EdgeWeight(creaseEnds[0]) = 1.5f;
446 tan1Mask.EdgeWeight(creaseEnds[1]) = -1.5f;
468 tan2Mask.SetNumVertexWeights(1);
469 tan2Mask.SetNumEdgeWeights(valence);
470 tan2Mask.SetNumFaceWeights(0);
471 tan2Mask.SetFaceWeightsForFaceCenters(
false);
473 for (
int i = 0; i < creaseEnds[0]; ++i) {
474 tan2Mask.EdgeWeight(i) = 0.0f;
476 int interiorEdgeCount = creaseEnds[1] - creaseEnds[0] - 1;
477 if (interiorEdgeCount == 2) {
480 static Weight
const Root3 = (Weight) 1.73205080756887729352;
481 static Weight
const Root3by2 = (Weight) (Root3 * 0.5);
483 tan2Mask.VertexWeight(0) = -Root3;
485 tan2Mask.EdgeWeight(creaseEnds[0]) = -Root3by2;
486 tan2Mask.EdgeWeight(creaseEnds[1]) = -Root3by2;
488 tan2Mask.EdgeWeight(creaseEnds[0] + 1) = Root3;
489 tan2Mask.EdgeWeight(creaseEnds[0] + 2) = Root3;
490 }
else if (interiorEdgeCount > 2) {
495 double theta = M_PI / (interiorEdgeCount + 1);
497 tan2Mask.VertexWeight(0) = 0.0f;
499 Weight cWeight = (Weight) (-3.0f * std::sin(theta));
500 tan2Mask.EdgeWeight(creaseEnds[0]) = cWeight;
501 tan2Mask.EdgeWeight(creaseEnds[1]) = cWeight;
503 double eCoeff = -3.0f * 2.0f * (std::cos(theta) - 1.0f);
504 for (
int i = 1; i <= interiorEdgeCount; ++i) {
505 tan2Mask.EdgeWeight(creaseEnds[0] + i) = (Weight) (eCoeff * std::sin(i * theta));
507 }
else if (interiorEdgeCount == 1) {
510 tan2Mask.VertexWeight(0) = -3.0f;
512 tan2Mask.EdgeWeight(creaseEnds[0]) = 0.0f;
513 tan2Mask.EdgeWeight(creaseEnds[1]) = 0.0f;
515 tan2Mask.EdgeWeight(creaseEnds[0] + 1) = 3.0f;
519 tan2Mask.VertexWeight(0) = -6.0f;
521 tan2Mask.EdgeWeight(creaseEnds[0]) = 3.0f;
522 tan2Mask.EdgeWeight(creaseEnds[1]) = 3.0f;
524 for (
int i = creaseEnds[1] + 1; i < valence; ++i) {
525 tan2Mask.EdgeWeight(i) = 0.0f;
530 template <
typename VERTEX,
typename MASK>
533 MASK& tan1Mask, MASK& tan2Mask)
const {
535 typedef typename MASK::Weight Weight;
537 int valence = vertex.GetNumFaces();
539 tan1Mask.SetNumVertexWeights(1);
540 tan1Mask.SetNumEdgeWeights(valence);
541 tan1Mask.SetNumFaceWeights(0);
542 tan1Mask.SetFaceWeightsForFaceCenters(
false);
544 tan2Mask.SetNumVertexWeights(1);
545 tan2Mask.SetNumEdgeWeights(valence);
546 tan2Mask.SetNumFaceWeights(0);
547 tan2Mask.SetFaceWeightsForFaceCenters(
false);
549 tan1Mask.VertexWeight(0) = 0.0f;
550 tan2Mask.VertexWeight(0) = 0.0f;
553 static Weight
const Root3by2 = (Weight)(0.5 * 1.73205080756887729352);
555 tan1Mask.EdgeWeight(0) = 1.0f;
556 tan1Mask.EdgeWeight(1) = 0.5f;
557 tan1Mask.EdgeWeight(2) = -0.5f;
558 tan1Mask.EdgeWeight(3) = -1.0f;
559 tan1Mask.EdgeWeight(4) = -0.5f;
560 tan1Mask.EdgeWeight(5) = 0.5f;
562 tan2Mask.EdgeWeight(0) = 0.0f;
563 tan2Mask.EdgeWeight(1) = Root3by2;
564 tan2Mask.EdgeWeight(2) = Root3by2;
565 tan2Mask.EdgeWeight(3) = 0.0f;
566 tan2Mask.EdgeWeight(4) = -Root3by2;
567 tan2Mask.EdgeWeight(5) = -Root3by2;
569 double alpha = 2.0f * M_PI / valence;
570 for (
int i = 0; i < valence; ++i) {
571 double alphaI = alpha * i;
572 tan1Mask.EdgeWeight(i) = (Weight) std::cos(alphaI);
573 tan2Mask.EdgeWeight(i) = (Weight) std::sin(alphaI);
580 using namespace OPENSUBDIV_VERSION;
void assignCreaseLimitMask(VERTEX const &vertex, MASK &pos, int const creaseEnds[2]) const
void assignCreaseMaskForVertex(VERTEX const &edge, MASK &mask, int const creaseEnds[2]) const
Split
Enumerated type for all face splitting schemes.
void assignSmoothLimitMask(VERTEX const &vertex, MASK &pos) const
static int GetRegularFaceSize()
void assignSmoothMaskForVertex(VERTEX const &edge, MASK &mask) const
static Split GetTopologicalSplitType()
static int GetRegularVertexValence()
void assignCornerLimitMask(VERTEX const &vertex, MASK &pos) const
void assignCornerLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
void assignSmoothLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
static int GetLocalNeighborhoodSize()
void assignCreaseMaskForEdge(EDGE const &edge, MASK &mask) const
void assignCornerMaskForVertex(VERTEX const &edge, MASK &mask) const
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const
void assignCreaseLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2, int const creaseEnds[2]) const