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