24 #ifndef OPENSUBDIV3_SDC_CATMARK_SCHEME_H 
   25 #define OPENSUBDIV3_SDC_CATMARK_SCHEME_H 
   27 #include "../version.h" 
   29 #include "../sdc/scheme.h" 
   34 namespace OpenSubdiv {
 
   35 namespace OPENSUBDIV_VERSION {
 
   69 template <
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;
 
  146 template <
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;
 
  171 template <
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;
 
  206 template <
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;
 
  219 template <
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;
 
  245 template <
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 fWeight = 1.0f / (Weight)(valence * (valence + 5.0f));
 
  281         Weight eWeight = 4.0f * fWeight;
 
  282         Weight vWeight = (Weight)(1.0f - valence * (eWeight + fWeight));
 
  284         posMask.VertexWeight(0) = vWeight;
 
  285         for (
int i = 0; i < valence; ++i) {
 
  286             posMask.EdgeWeight(i) = eWeight;
 
  287             posMask.FaceWeight(i) = fWeight;
 
  297 template <
typename VERTEX, 
typename MASK>
 
  300         MASK& tan1Mask, MASK& tan2Mask)
 const {
 
  302     int valence = vertex.GetNumEdges();
 
  304     tan1Mask.SetNumVertexWeights(1);
 
  305     tan1Mask.SetNumEdgeWeights(valence);
 
  306     tan1Mask.SetNumFaceWeights(0);
 
  307     tan1Mask.SetFaceWeightsForFaceCenters(
false);
 
  309     tan2Mask.SetNumVertexWeights(1);
 
  310     tan2Mask.SetNumEdgeWeights(valence);
 
  311     tan2Mask.SetNumFaceWeights(0);
 
  312     tan2Mask.SetFaceWeightsForFaceCenters(
false);
 
  315     tan1Mask.VertexWeight(0) = -1.0f;
 
  316     tan1Mask.EdgeWeight(0)   =  1.0f;
 
  317     tan1Mask.EdgeWeight(1)   =  0.0f;
 
  319     tan2Mask.VertexWeight(0) = -1.0f;
 
  320     tan2Mask.EdgeWeight(0)   =  0.0f;
 
  321     tan2Mask.EdgeWeight(1)   =  1.0f;
 
  323     for (
int i = 2; i < valence; ++i) {
 
  324         tan1Mask.EdgeWeight(i) = 0.0f;
 
  325         tan2Mask.EdgeWeight(i) = 0.0f;
 
  330 template <
typename VERTEX, 
typename MASK>
 
  333         MASK& tan1Mask, MASK& tan2Mask, 
int const creaseEnds[2])
 const {
 
  335     typedef typename MASK::Weight Weight;
 
  344     int numEdges = vertex.GetNumEdges();
 
  345     int numFaces = vertex.GetNumFaces();
 
  347     tan1Mask.SetNumVertexWeights(1);
 
  348     tan1Mask.SetNumEdgeWeights(numEdges);
 
  349     tan1Mask.SetNumFaceWeights(numFaces);
 
  350     tan1Mask.SetFaceWeightsForFaceCenters(
false);
 
  352     tan1Mask.VertexWeight(0) = 0.0f;
 
  353     for (
int i = 0; i < numEdges; ++i) {
 
  354         tan1Mask.EdgeWeight(i) = 0.0f;
 
  356     for (
int i = 0; i < numFaces; ++i) {
 
  357         tan1Mask.FaceWeight(i) = 0.0f;
 
  360     tan1Mask.EdgeWeight(creaseEnds[0]) =  0.5f;
 
  361     tan1Mask.EdgeWeight(creaseEnds[1]) = -0.5f;
 
  372     tan2Mask.SetNumVertexWeights(1);
 
  373     tan2Mask.SetNumEdgeWeights(numEdges);
 
  374     tan2Mask.SetNumFaceWeights(numFaces);
 
  375     tan2Mask.SetFaceWeightsForFaceCenters(
false);
 
  378     for (
int i = 0; i < creaseEnds[0]; ++i) {
 
  379         tan2Mask.EdgeWeight(i) = 0.0f;
 
  380         tan2Mask.FaceWeight(i) = 0.0f;
 
  384     int interiorEdgeCount = creaseEnds[1] - creaseEnds[0] - 1;
 
  385     if (interiorEdgeCount == 1) {
 
  388         tan2Mask.VertexWeight(0) = (Weight)(-4.0 / 6.0);
 
  390         tan2Mask.EdgeWeight(creaseEnds[0])     = (Weight)(-1.0 / 6.0);
 
  391         tan2Mask.EdgeWeight(creaseEnds[0] + 1) = (Weight)( 4.0 / 6.0);
 
  392         tan2Mask.EdgeWeight(creaseEnds[1])     = (Weight)(-1.0 / 6.0);
 
  394         tan2Mask.FaceWeight(creaseEnds[0])     = (Weight)(1.0 / 6.0);
 
  395         tan2Mask.FaceWeight(creaseEnds[0] + 1) = (Weight)(1.0 / 6.0);
 
  396     } 
else if (interiorEdgeCount > 1) {
 
  399         double k     = (double) (interiorEdgeCount + 1);
 
  400         double theta = M_PI / k;
 
  402         double cosTheta = std::cos(theta);
 
  403         double sinTheta = std::sin(theta);
 
  406         double commonDenom = 1.0f / (k * (3.0f + cosTheta));
 
  407         double R = (cosTheta + 1.0f) / sinTheta;
 
  409         double vertexWeight = 4.0f * R * (cosTheta - 1.0f);
 
  410         double creaseWeight = -R * (1.0f + 2.0f * cosTheta);
 
  412         tan2Mask.VertexWeight(0) = (Weight) (vertexWeight * commonDenom);
 
  414         tan2Mask.EdgeWeight(creaseEnds[0]) = (Weight) (creaseWeight * commonDenom);
 
  415         tan2Mask.EdgeWeight(creaseEnds[1]) = (Weight) (creaseWeight * commonDenom);
 
  417         tan2Mask.FaceWeight(creaseEnds[0]) = (Weight) (sinTheta * commonDenom);
 
  419         double sinThetaI      = 0.0f;
 
  420         double sinThetaIplus1 = sinTheta;
 
  421         for (
int i = 1; i < k; ++i) {
 
  422             sinThetaI      = sinThetaIplus1;
 
  423             sinThetaIplus1 = std::sin((i+1)*theta);
 
  425             tan2Mask.EdgeWeight(creaseEnds[0] + i) = (Weight) ((4.0f * sinThetaI) * commonDenom);
 
  426             tan2Mask.FaceWeight(creaseEnds[0] + i) = (Weight) ((sinThetaI + sinThetaIplus1) * commonDenom);
 
  431         tan2Mask.VertexWeight(0) = -6.0f;
 
  433         tan2Mask.EdgeWeight(creaseEnds[0]) = 3.0f;
 
  434         tan2Mask.EdgeWeight(creaseEnds[1]) = 3.0f;
 
  436         tan2Mask.FaceWeight(creaseEnds[0]) = 0.0f;
 
  440     for (
int i = creaseEnds[1]; i < numFaces; ++i) {
 
  441         tan2Mask.FaceWeight(i) = 0.0f;
 
  443     for (
int i = creaseEnds[1] + 1; i < numEdges; ++i) {
 
  444         tan2Mask.EdgeWeight(i) = 0.0f;
 
  449 template <
typename VERTEX, 
typename MASK>
 
  452         MASK& tan1Mask, MASK& tan2Mask)
 const {
 
  454     typedef typename MASK::Weight Weight;
 
  456     int valence = vertex.GetNumFaces();
 
  458         assignCornerLimitTangentMasks(vertex, tan1Mask, tan2Mask);
 
  463     tan1Mask.SetNumVertexWeights(1);
 
  464     tan1Mask.SetNumEdgeWeights(valence);
 
  465     tan1Mask.SetNumFaceWeights(valence);
 
  466     tan1Mask.SetFaceWeightsForFaceCenters(
false);
 
  468     tan1Mask.VertexWeight(0) = 0.0f;
 
  471         tan1Mask.EdgeWeight(0) =  4.0f;
 
  472         tan1Mask.EdgeWeight(1) =  0.0f;
 
  473         tan1Mask.EdgeWeight(2) = -4.0f;
 
  474         tan1Mask.EdgeWeight(3) =  0.0f;
 
  476         tan1Mask.FaceWeight(0) =  1.0f;
 
  477         tan1Mask.FaceWeight(1) = -1.0f;
 
  478         tan1Mask.FaceWeight(2) = -1.0f;
 
  479         tan1Mask.FaceWeight(3) =  1.0f;
 
  481         double theta = 2.0f * M_PI / (double)valence;
 
  483         double cosTheta     = std::cos(theta);
 
  484         double cosHalfTheta = std::cos(theta * 0.5f);
 
  486         double lambda = (5.0 / 16.0) + (1.0 / 16.0) *
 
  487                 (cosTheta + cosHalfTheta * std::sqrt(2.0f * (9.0f + cosTheta)));
 
  489         double edgeWeightScale = 4.0f;
 
  490         double faceWeightScale = 1.0f / (4.0f * lambda - 1.0f);
 
  492         for (
int i = 0; i < valence; ++i) {
 
  493             double cosThetaI      = std::cos(  i  * theta);
 
  494             double cosThetaIplus1 = std::cos((i+1)* theta);
 
  496             tan1Mask.EdgeWeight(i) = (Weight) (edgeWeightScale * cosThetaI);
 
  497             tan1Mask.FaceWeight(i) = (Weight) (faceWeightScale * (cosThetaI + cosThetaIplus1));
 
  502     tan2Mask.SetNumVertexWeights(1);
 
  503     tan2Mask.SetNumEdgeWeights(valence);
 
  504     tan2Mask.SetNumFaceWeights(valence);
 
  505     tan2Mask.SetFaceWeightsForFaceCenters(
false);
 
  507     tan2Mask.VertexWeight(0) = 0.0f;
 
  509         tan2Mask.EdgeWeight(0) =  0.0f;
 
  510         tan2Mask.EdgeWeight(1) =  4.0f;
 
  511         tan2Mask.EdgeWeight(2) =  0.0f;
 
  512         tan2Mask.EdgeWeight(3) = -4.0f;
 
  514         tan2Mask.FaceWeight(0) =  1.0f;
 
  515         tan2Mask.FaceWeight(1) =  1.0f;
 
  516         tan2Mask.FaceWeight(2) = -1.0f;
 
  517         tan2Mask.FaceWeight(3) = -1.0f;
 
  519         tan2Mask.EdgeWeight(0) = tan1Mask.EdgeWeight(valence-1);
 
  520         tan2Mask.FaceWeight(0) = tan1Mask.FaceWeight(valence-1);
 
  521         for (
int i = 1; i < valence; ++i) {
 
  522             tan2Mask.EdgeWeight(i) = tan1Mask.EdgeWeight(i-1);
 
  523             tan2Mask.FaceWeight(i) = tan1Mask.FaceWeight(i-1);
 
  531 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()
Used by Catmark and Bilinear. 
"smooth triangle" weights (Catmark scheme only) 
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const 
void assignCreaseLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2, int const creaseEnds[2]) const