24#ifndef OPENSUBDIV3_SDC_CATMARK_SCHEME_H
25#define OPENSUBDIV3_SDC_CATMARK_SCHEME_H
27#include "../version.h"
29#include "../sdc/scheme.h"
35namespace OPENSUBDIV_VERSION {
69template <
typename EDGE,
typename MASK>
73 typedef typename MASK::Weight Weight;
75 int faceCount = edge.GetNumFaces();
77 mask.SetNumVertexWeights(2);
78 mask.SetNumEdgeWeights(0);
79 mask.SetNumFaceWeights(faceCount);
80 mask.SetFaceWeightsForFaceCenters(
true);
86 bool face0IsTri =
false;
87 bool face1IsTri =
false;
89 if (useTriangleOption) {
97 edge.GetNumVerticesPerFace(vertsPerFace);
99 face0IsTri = (vertsPerFace[0] == 3);
100 face1IsTri = (vertsPerFace[1] == 3);
101 useTriangleOption = face0IsTri || face1IsTri;
103 useTriangleOption =
false;
107 if (! useTriangleOption) {
108 mask.VertexWeight(0) = 0.25f;
109 mask.VertexWeight(1) = 0.25f;
111 if (faceCount == 2) {
112 mask.FaceWeight(0) = 0.25f;
113 mask.FaceWeight(1) = 0.25f;
115 Weight fWeight = 0.5f / (Weight)faceCount;
116 for (
int i = 0; i < faceCount; ++i) {
117 mask.FaceWeight(i) = fWeight;
124 const Weight CATMARK_SMOOTH_TRI_EDGE_WEIGHT = (Weight) 0.470;
126 Weight f0Weight = face0IsTri ? CATMARK_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
127 Weight f1Weight = face1IsTri ? CATMARK_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
129 Weight fWeight = 0.5f * (f0Weight + f1Weight);
130 Weight vWeight = 0.5f * (1.0f - 2.0f * fWeight);
132 mask.VertexWeight(0) = vWeight;
133 mask.VertexWeight(1) = vWeight;
135 mask.FaceWeight(0) = fWeight;
136 mask.FaceWeight(1) = fWeight;
146template <
typename VERTEX,
typename MASK>
149 int const creaseEnds[2])
const {
150 typedef typename MASK::Weight Weight;
152 int valence = vertex.GetNumEdges();
154 mask.SetNumVertexWeights(1);
155 mask.SetNumEdgeWeights(valence);
156 mask.SetNumFaceWeights(0);
157 mask.SetFaceWeightsForFaceCenters(
false);
159 Weight vWeight = 0.75f;
160 Weight eWeight = 0.125f;
162 mask.VertexWeight(0) = vWeight;
163 for (
int i = 0; i < valence; ++i) {
164 mask.EdgeWeight(i) = 0.0f;
166 mask.EdgeWeight(creaseEnds[0]) = eWeight;
167 mask.EdgeWeight(creaseEnds[1]) = eWeight;
171template <
typename VERTEX,
typename MASK>
175 typedef typename MASK::Weight Weight;
182 assert(vertex.GetNumFaces() == vertex.GetNumEdges());
184 int valence = vertex.GetNumFaces();
186 mask.SetNumVertexWeights(1);
187 mask.SetNumEdgeWeights(valence);
188 mask.SetNumFaceWeights(valence);
189 mask.SetFaceWeightsForFaceCenters(
true);
191 Weight vWeight = (Weight)(valence - 2) / (Weight)valence;
192 Weight fWeight = 1.0f / (Weight)(valence * valence);
193 Weight eWeight = fWeight;
195 mask.VertexWeight(0) = vWeight;
196 for (
int i = 0; i < valence; ++i) {
197 mask.EdgeWeight(i) = eWeight;
198 mask.FaceWeight(i) = fWeight;
206template <
typename VERTEX,
typename MASK>
210 posMask.SetNumVertexWeights(1);
211 posMask.SetNumEdgeWeights(0);
212 posMask.SetNumFaceWeights(0);
213 posMask.SetFaceWeightsForFaceCenters(
false);
215 posMask.VertexWeight(0) = 1.0f;
219template <
typename VERTEX,
typename MASK>
222 int const creaseEnds[2])
const {
224 typedef typename MASK::Weight Weight;
226 int valence = vertex.GetNumEdges();
228 posMask.SetNumVertexWeights(1);
229 posMask.SetNumEdgeWeights(valence);
230 posMask.SetNumFaceWeights(0);
231 posMask.SetFaceWeightsForFaceCenters(
false);
233 Weight vWeight = (Weight)(2.0 / 3.0);
234 Weight eWeight = (Weight)(1.0 / 6.0);
236 posMask.VertexWeight(0) = vWeight;
237 for (
int i = 0; i < valence; ++i) {
238 posMask.EdgeWeight(i) = 0.0f;
240 posMask.EdgeWeight(creaseEnds[0]) = eWeight;
241 posMask.EdgeWeight(creaseEnds[1]) = eWeight;
245template <
typename VERTEX,
typename MASK>
249 typedef typename MASK::Weight Weight;
251 int valence = vertex.GetNumFaces();
253 assignCornerLimitMask(vertex, posMask);
257 posMask.SetNumVertexWeights(1);
258 posMask.SetNumEdgeWeights(valence);
259 posMask.SetNumFaceWeights(valence);
260 posMask.SetFaceWeightsForFaceCenters(
false);
264 Weight fWeight = (Weight)(1.0 / 36.0);
265 Weight eWeight = (Weight)(1.0 / 9.0);
266 Weight vWeight = (Weight)(4.0 / 9.0);
268 posMask.VertexWeight(0) = vWeight;
270 posMask.EdgeWeight(0) = eWeight;
271 posMask.EdgeWeight(1) = eWeight;
272 posMask.EdgeWeight(2) = eWeight;
273 posMask.EdgeWeight(3) = eWeight;
275 posMask.FaceWeight(0) = fWeight;
276 posMask.FaceWeight(1) = fWeight;
277 posMask.FaceWeight(2) = fWeight;
278 posMask.FaceWeight(3) = fWeight;
280 Weight Valence = (Weight) valence;
282 Weight fWeight = 1.0f / (Valence * (Valence + 5.0f));
283 Weight eWeight = 4.0f * fWeight;
284 Weight vWeight = 1.0f - Valence * (eWeight + fWeight);
286 posMask.VertexWeight(0) = vWeight;
287 for (
int i = 0; i < valence; ++i) {
288 posMask.EdgeWeight(i) = eWeight;
289 posMask.FaceWeight(i) = fWeight;
299template <
typename VERTEX,
typename MASK>
302 MASK& tan1Mask, MASK& tan2Mask)
const {
304 int valence = vertex.GetNumEdges();
306 tan1Mask.SetNumVertexWeights(1);
307 tan1Mask.SetNumEdgeWeights(valence);
308 tan1Mask.SetNumFaceWeights(0);
309 tan1Mask.SetFaceWeightsForFaceCenters(
false);
311 tan2Mask.SetNumVertexWeights(1);
312 tan2Mask.SetNumEdgeWeights(valence);
313 tan2Mask.SetNumFaceWeights(0);
314 tan2Mask.SetFaceWeightsForFaceCenters(
false);
317 tan1Mask.VertexWeight(0) = -1.0f;
318 tan1Mask.EdgeWeight(0) = 1.0f;
319 tan1Mask.EdgeWeight(1) = 0.0f;
321 tan2Mask.VertexWeight(0) = -1.0f;
322 tan2Mask.EdgeWeight(0) = 0.0f;
323 tan2Mask.EdgeWeight(1) = 1.0f;
325 for (
int i = 2; i < valence; ++i) {
326 tan1Mask.EdgeWeight(i) = 0.0f;
327 tan2Mask.EdgeWeight(i) = 0.0f;
332template <
typename VERTEX,
typename MASK>
335 MASK& tan1Mask, MASK& tan2Mask,
int const creaseEnds[2])
const {
337 typedef typename MASK::Weight Weight;
346 int numEdges = vertex.GetNumEdges();
347 int numFaces = vertex.GetNumFaces();
349 tan1Mask.SetNumVertexWeights(1);
350 tan1Mask.SetNumEdgeWeights(numEdges);
351 tan1Mask.SetNumFaceWeights(numFaces);
352 tan1Mask.SetFaceWeightsForFaceCenters(
false);
354 tan1Mask.VertexWeight(0) = 0.0f;
355 for (
int i = 0; i < numEdges; ++i) {
356 tan1Mask.EdgeWeight(i) = 0.0f;
358 for (
int i = 0; i < numFaces; ++i) {
359 tan1Mask.FaceWeight(i) = 0.0f;
362 tan1Mask.EdgeWeight(creaseEnds[0]) = 0.5f;
363 tan1Mask.EdgeWeight(creaseEnds[1]) = -0.5f;
374 tan2Mask.SetNumVertexWeights(1);
375 tan2Mask.SetNumEdgeWeights(numEdges);
376 tan2Mask.SetNumFaceWeights(numFaces);
377 tan2Mask.SetFaceWeightsForFaceCenters(
false);
380 for (
int i = 0; i < creaseEnds[0]; ++i) {
381 tan2Mask.EdgeWeight(i) = 0.0f;
382 tan2Mask.FaceWeight(i) = 0.0f;
386 int interiorEdgeCount = creaseEnds[1] - creaseEnds[0] - 1;
387 if (interiorEdgeCount == 1) {
390 tan2Mask.VertexWeight(0) = (Weight)(-4.0 / 6.0);
392 tan2Mask.EdgeWeight(creaseEnds[0]) = (Weight)(-1.0 / 6.0);
393 tan2Mask.EdgeWeight(creaseEnds[0] + 1) = (Weight)( 4.0 / 6.0);
394 tan2Mask.EdgeWeight(creaseEnds[1]) = (Weight)(-1.0 / 6.0);
396 tan2Mask.FaceWeight(creaseEnds[0]) = (Weight)(1.0 / 6.0);
397 tan2Mask.FaceWeight(creaseEnds[0] + 1) = (Weight)(1.0 / 6.0);
398 }
else if (interiorEdgeCount > 1) {
401 double k = (double) (interiorEdgeCount + 1);
402 double theta = M_PI / k;
404 double cosTheta = std::cos(theta);
405 double sinTheta = std::sin(theta);
408 double commonDenom = 1.0f / (k * (3.0f + cosTheta));
409 double R = (cosTheta + 1.0f) / sinTheta;
411 double vertexWeight = 4.0f * R * (cosTheta - 1.0f);
412 double creaseWeight = -R * (1.0f + 2.0f * cosTheta);
414 tan2Mask.VertexWeight(0) = (Weight) (vertexWeight * commonDenom);
416 tan2Mask.EdgeWeight(creaseEnds[0]) = (Weight) (creaseWeight * commonDenom);
417 tan2Mask.EdgeWeight(creaseEnds[1]) = (Weight) (creaseWeight * commonDenom);
419 tan2Mask.FaceWeight(creaseEnds[0]) = (Weight) (sinTheta * commonDenom);
421 double sinThetaI = 0.0f;
422 double sinThetaIplus1 = sinTheta;
423 for (
int i = 1; i < k; ++i) {
424 sinThetaI = sinThetaIplus1;
425 sinThetaIplus1 = std::sin((i+1)*theta);
427 tan2Mask.EdgeWeight(creaseEnds[0] + i) = (Weight) ((4.0f * sinThetaI) * commonDenom);
428 tan2Mask.FaceWeight(creaseEnds[0] + i) = (Weight) ((sinThetaI + sinThetaIplus1) * commonDenom);
433 tan2Mask.VertexWeight(0) = -6.0f;
435 tan2Mask.EdgeWeight(creaseEnds[0]) = 3.0f;
436 tan2Mask.EdgeWeight(creaseEnds[1]) = 3.0f;
438 tan2Mask.FaceWeight(creaseEnds[0]) = 0.0f;
442 for (
int i = creaseEnds[1]; i < numFaces; ++i) {
443 tan2Mask.FaceWeight(i) = 0.0f;
445 for (
int i = creaseEnds[1] + 1; i < numEdges; ++i) {
446 tan2Mask.EdgeWeight(i) = 0.0f;
451template <
typename VERTEX,
typename MASK>
454 MASK& tan1Mask, MASK& tan2Mask)
const {
456 typedef typename MASK::Weight Weight;
458 int valence = vertex.GetNumFaces();
460 assignCornerLimitTangentMasks(vertex, tan1Mask, tan2Mask);
465 tan1Mask.SetNumVertexWeights(1);
466 tan1Mask.SetNumEdgeWeights(valence);
467 tan1Mask.SetNumFaceWeights(valence);
468 tan1Mask.SetFaceWeightsForFaceCenters(
false);
470 tan1Mask.VertexWeight(0) = 0.0f;
473 tan1Mask.EdgeWeight(0) = 4.0f;
474 tan1Mask.EdgeWeight(1) = 0.0f;
475 tan1Mask.EdgeWeight(2) = -4.0f;
476 tan1Mask.EdgeWeight(3) = 0.0f;
478 tan1Mask.FaceWeight(0) = 1.0f;
479 tan1Mask.FaceWeight(1) = -1.0f;
480 tan1Mask.FaceWeight(2) = -1.0f;
481 tan1Mask.FaceWeight(3) = 1.0f;
483 double theta = 2.0f * M_PI / (double)valence;
485 double cosTheta = std::cos(theta);
486 double cosHalfTheta = std::cos(theta * 0.5f);
488 double lambda = (5.0 / 16.0) + (1.0 / 16.0) *
489 (cosTheta + cosHalfTheta * std::sqrt(2.0f * (9.0f + cosTheta)));
491 double edgeWeightScale = 4.0f;
492 double faceWeightScale = 1.0f / (4.0f * lambda - 1.0f);
494 for (
int i = 0; i < valence; ++i) {
495 double cosThetaI = std::cos( i * theta);
496 double cosThetaIplus1 = std::cos((i+1)* theta);
498 tan1Mask.EdgeWeight(i) = (Weight) (edgeWeightScale * cosThetaI);
499 tan1Mask.FaceWeight(i) = (Weight) (faceWeightScale * (cosThetaI + cosThetaIplus1));
504 tan2Mask.SetNumVertexWeights(1);
505 tan2Mask.SetNumEdgeWeights(valence);
506 tan2Mask.SetNumFaceWeights(valence);
507 tan2Mask.SetFaceWeightsForFaceCenters(
false);
509 tan2Mask.VertexWeight(0) = 0.0f;
511 tan2Mask.EdgeWeight(0) = 0.0f;
512 tan2Mask.EdgeWeight(1) = 4.0f;
513 tan2Mask.EdgeWeight(2) = 0.0f;
514 tan2Mask.EdgeWeight(3) = -4.0f;
516 tan2Mask.FaceWeight(0) = 1.0f;
517 tan2Mask.FaceWeight(1) = 1.0f;
518 tan2Mask.FaceWeight(2) = -1.0f;
519 tan2Mask.FaceWeight(3) = -1.0f;
521 tan2Mask.EdgeWeight(0) = tan1Mask.EdgeWeight(valence-1);
522 tan2Mask.FaceWeight(0) = tan1Mask.FaceWeight(valence-1);
523 for (
int i = 1; i < valence; ++i) {
524 tan2Mask.EdgeWeight(i) = tan1Mask.EdgeWeight(i-1);
525 tan2Mask.FaceWeight(i) = tan1Mask.FaceWeight(i-1);
533using namespace OPENSUBDIV_VERSION;
Split
Enumerated type for all face splitting schemes.
@ SPLIT_TO_QUADS
Used by Catmark and Bilinear.
@ TRI_SUB_SMOOTH
"smooth triangle" weights (Catmark scheme only)
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const
static Split GetTopologicalSplitType()
void assignCreaseMaskForVertex(VERTEX const &edge, MASK &mask, int const creaseEnds[2]) const
void assignCreaseLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2, int const creaseEnds[2]) const
static int GetRegularFaceSize()
void assignSmoothLimitMask(VERTEX const &vertex, MASK &pos) const
static int GetLocalNeighborhoodSize()
void assignCreaseLimitMask(VERTEX const &vertex, MASK &pos, int const creaseEnds[2]) const
void assignSmoothMaskForVertex(VERTEX const &edge, MASK &mask) const
static int GetRegularVertexValence()
void assignSmoothLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
void assignCornerLimitMask(VERTEX const &vertex, MASK &pos) const
void assignCornerLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const