All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
catmarkScheme.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 SDC_CATMARK_SCHEME_H
25 #define SDC_CATMARK_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 
36 namespace Sdc {
37 
38 //
39 // Specializations for Scheme<TYPE_CATMARK>:
40 //
41 
42 //
43 // Masks for edge-vertices: the hard Crease mask does not need to be specialized
44 // (simply the midpoint), so all that is left is the Smooth case:
45 //
46 // The Smooth mask is complicated by the need to support the "triangle subdivision"
47 // option, which applies different weighting in the presence of triangles. It is
48 // up for debate as to whether this is useful or not -- we may be able to deprecate
49 // this option.
50 //
51 template <>
52 template <typename EDGE, typename MASK>
53 inline void
54 Scheme<TYPE_CATMARK>::assignSmoothMaskForEdge(EDGE const& edge, MASK& mask) const {
55 
56  typedef typename MASK::Weight Weight;
57 
58  int faceCount = edge.GetNumFaces();
59 
60  mask.SetNumVertexWeights(2);
61  mask.SetNumEdgeWeights(0);
62  mask.SetNumFaceWeights(faceCount);
63 
64  //
65  // Determine if we need to inspect incident faces and apply alternate weighting for
66  // triangles -- and if so, determine which of the two are triangles.
67  //
68  // (Is this really used? Would be nice if we could deprecate this option...)
69  //
70  bool face0IsTri = false;
71  bool face1IsTri = false;
72  bool useTriangleOption = (_options.GetTriangleSubdivision() != Options::TRI_SUB_NORMAL);
73  if (useTriangleOption) {
74  if (faceCount == 2) {
75  //
76  // Need to inspect/gather valence of incident faces here...
77  //
78  useTriangleOption = face0IsTri || face1IsTri;
79  } else {
80  useTriangleOption = false;
81  }
82  }
83 
84  if (!useTriangleOption) {
85  mask.VertexWeight(0) = 0.25f;
86  mask.VertexWeight(1) = 0.25f;
87 
88  if (faceCount == 2) {
89  mask.FaceWeight(0) = 0.25f;
90  mask.FaceWeight(1) = 0.25f;
91  } else {
92  Weight fWeight = 0.5f / (Weight)faceCount;
93  for (int i = 0; i < faceCount; ++i) {
94  mask.FaceWeight(i) = fWeight;
95  }
96  }
97  } else {
98  //
99  // This mimics the implementation in Hbr in terms of order of operations. If
100  // the triangle-subdivision option can be deprecated we can remove this block:
101  //
102  const Weight CATMARK_SMOOTH_TRI_EDGE_WEIGHT = 0.470f;
103 
104  Weight f0Weight = face0IsTri ? CATMARK_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
105  Weight f1Weight = face1IsTri ? CATMARK_SMOOTH_TRI_EDGE_WEIGHT : 0.25f;
106 
107  Weight fWeight = 0.5f * (f0Weight + f1Weight);
108  Weight vWeight = 0.5f * (1.0f - 2.0f * fWeight);
109 
110  mask.VertexWeight(0) = vWeight;
111  mask.VertexWeight(1) = vWeight;
112 
113  mask.FaceWeight(0) = fWeight;
114  mask.FaceWeight(1) = fWeight;
115  }
116 }
117 
118 
119 //
120 // Masks for vertex-vertices: the hard Corner mask does not need to be specialized
121 // (simply the vertex itself), leaving the Crease and Smooth cases (Dart is smooth):
122 //
123 template <>
124 template <typename VERTEX, typename MASK>
125 inline void
126 Scheme<TYPE_CATMARK>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& mask, float const edgeSharpness[]) const {
127 
128  typedef typename MASK::Weight Weight;
129 
130  int valence = vertex.GetNumEdges();
131 
132  mask.SetNumVertexWeights(1);
133  mask.SetNumEdgeWeights(valence);
134  mask.SetNumFaceWeights(0);
135 
136  Weight vWeight = 0.75f;
137  Weight eWeight = 0.125f;
138 
139  mask.VertexWeight(0) = vWeight;
140 
141  //
142  // NOTE -- at some point the sharpness vector was optional, and topology would be used
143  // to identify a boundary crease. We are currently no longer passing a null sharpness
144  // vector and may not support it in future, in which case this test can be removed:
145  //
146  if (edgeSharpness != 0) {
147  // Use the sharpness values to identify the crease edges:
148  for (int i = 0; i < valence; ++i) {
149  mask.EdgeWeight(i) = (edgeSharpness[i] > 0.0f) ? eWeight : 0.0f;
150  }
151  } else {
152  // Use the boundary edges (first and last) as the crease edges:
153  mask.EdgeWeight(0) = eWeight;
154  for (int i = 1; i < (valence - 1); ++i) {
155  mask.EdgeWeight(i) = 0.0f;
156  }
157  mask.EdgeWeight(valence-1) = eWeight;
158  }
159 }
160 
161 template <>
162 template <typename VERTEX, typename MASK>
163 inline void
164 Scheme<TYPE_CATMARK>::assignSmoothMaskForVertex(VERTEX const& vertex, MASK& mask) const {
165 
166  typedef typename MASK::Weight Weight;
167 
168  //
169  // Remember that when the edge- and face-counts differ, we need to adjust this...
170  //
171  // Keep what's below for eCount == fCount and for the other cases -- which should
172  // only occur for non-manifold vertices -- use the following formula that we've
173  // adapted in MM:
174  //
175  // v' = (F + 2*E + (n-3)*v) / n
176  //
177  // where F is the average of the face points (fi) and E is the average of the edge
178  // midpoints (ei). The F term gives is the 1/(n*n) of below and we just need to
179  // factor the E and v terms to account for the edge endpoints rather than midpoints.
180  //
181  int valence = vertex.GetNumFaces();
182 
183  mask.SetNumVertexWeights(1);
184  mask.SetNumEdgeWeights(valence);
185  mask.SetNumFaceWeights(valence);
186 
187  Weight vWeight = (Weight)(valence - 2) / (Weight)valence;
188  Weight fWeight = 1.0f / (Weight)(valence * valence);
189  Weight eWeight = fWeight;
190 
191  mask.VertexWeight(0) = vWeight;
192  for (int i = 0; i < valence; ++i) {
193  mask.EdgeWeight(i) = eWeight;
194  mask.FaceWeight(i) = fWeight;
195  }
196 }
197 
198 } // end namespace sdc
199 
200 } // end namespace OPENSUBDIV_VERSION
201 using namespace OPENSUBDIV_VERSION;
202 } // end namespace OpenSubdiv
203 
204 #endif /* SDC_CATMARK_SCHEME_H */
205 
void assignSmoothMaskForVertex(VERTEX const &edge, MASK &mask) const
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const
void assignCreaseMaskForVertex(VERTEX const &edge, MASK &mask, float const sharpness[]) const