All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
subdivision.h
Go to the documentation of this file.
1 //
2 // Copyright 2013 Pixar
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 
25 #ifndef HBRSUBDIVISION_H
26 #define HBRSUBDIVISION_H
27 
28 #include "../version.h"
29 
30 namespace OpenSubdiv {
31 namespace OPENSUBDIV_VERSION {
32 
33 template <class T> class HbrFace;
34 template <class T> class HbrVertex;
35 template <class T> class HbrHalfedge;
36 template <class T> class HbrMesh;
37 template <class T> class HbrSubdivision {
38 public:
41 
42  virtual ~HbrSubdivision<T>() {}
43 
44  virtual HbrSubdivision<T>* Clone() const = 0;
45 
46  // How to subdivide a face
47  virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face) = 0;
48 
49  // Subdivide a face only at a particular vertex (creating one child)
50  virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex) = 0;
51 
52  // Refine all faces around a particular vertex
53  virtual void RefineAtVertex(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
54 
55  // Given an edge, try to ensure the edge's opposite exists by
56  // forcing refinement up the hierarchy
57  virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) = 0;
58 
59  // Given an vertex, ensure all faces in the ring around it exist
60  // by forcing refinement up the hierarchy
61  virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex) = 0;
62 
63  // Returns true if the vertex, edge, or face has a limit point,
64  // curve, or surface associated with it
65  virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrFace<T>* /* face */) { return true; }
66  virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrHalfedge<T>* /* edge */) { return true; }
67  virtual bool HasLimit(HbrMesh<T>* /* mesh */, HbrVertex<T>* /* vertex */) { return true; }
68 
69  // How to turn faces, edges, and vertices into vertices
70  virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face) = 0;
71  virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge) = 0;
72  virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex) = 0;
73 
74  // Returns true if the vertex is extraordinary in the subdivision scheme
75  virtual bool VertexIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrVertex<T>* /* vertex */) { return false; }
76 
77  // Returns true if the face is extraordinary in the subdivision scheme
78  virtual bool FaceIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrFace<T>* /* face */) { return false; }
79 
80  // Crease subdivision rules. When subdividing a edge with a crease
81  // strength, we get two child subedges, and we need to determine
82  // what weights to assign these subedges. The "normal" rule
83  // is to simply assign the current edge's crease strength - 1
84  // to both of the child subedges. The "Chaikin" rule looks at the
85  // current edge and incident edges to the current edge's end
86  // vertices, and weighs them; for more information consult
87  // the Geri's Game paper.
91  };
94 
95  // Figures out how to assign a crease weight on an edge to its
96  // subedge. The subedge must be a child of the parent edge
97  // (either subedge->GetOrgVertex() or subedge->GetDestVertex()
98  // == edge->Subdivide()). The vertex supplied must NOT be
99  // a parent of the subedge; it is either the origin or
100  // destination vertex of edge.
101  void SubdivideCreaseWeight(HbrHalfedge<T>* edge, HbrVertex<T>* vertex, HbrHalfedge<T>* subedge);
102 
103  // Returns the expected number of children faces after subdivision
104  // for a face with the given number of vertices.
105  virtual int GetFaceChildrenCount(int nvertices) const = 0;
106 
107 protected:
109 
110  // Helper routine for subclasses: for a given vertex, sums
111  // contributions from surrounding vertices
112  void AddSurroundingVerticesWithWeight(HbrMesh<T>* mesh, HbrVertex<T>* vertex, float weight, T* data);
113 
114  // Helper routine for subclasses: for a given vertex with a crease
115  // mask, adds contributions from the two crease edges
116  void AddCreaseEdgesWithWeight(HbrMesh<T>* mesh, HbrVertex<T>* vertex, bool next, float weight, T* data);
117 
118 private:
119  // Helper class used by AddSurroundingVerticesWithWeight
120  class SmoothSubdivisionVertexOperator : public HbrVertexOperator<T> {
121  public:
122  SmoothSubdivisionVertexOperator(T* data, bool meshHasEdits, float weight)
123  : m_data(data),
124  m_meshHasEdits(meshHasEdits),
125  m_weight(weight)
126  {
127  }
128  virtual void operator() (HbrVertex<T> &vertex) {
129  // Must ensure vertex edits have been applied
130  if (m_meshHasEdits) {
131  vertex.GuaranteeNeighbors();
132  }
133  m_data->AddWithWeight(vertex.GetData(), m_weight);
134  }
135  private:
136  T* m_data;
137  const bool m_meshHasEdits;
138  const float m_weight;
139  };
140 
141  // Helper class used by AddCreaseEdgesWithWeight
142  class CreaseSubdivisionHalfedgeOperator : public HbrHalfedgeOperator<T> {
143  public:
144  CreaseSubdivisionHalfedgeOperator(HbrVertex<T> *vertex, T* data, bool meshHasEdits, bool next, float weight)
145  : m_vertex(vertex),
146  m_data(data),
147  m_meshHasEdits(meshHasEdits),
148  m_next(next),
149  m_weight(weight),
150  m_count(0)
151  {
152  }
153  virtual void operator() (HbrHalfedge<T> &edge) {
154  if (m_count < 2 && edge.IsSharp(m_next)) {
155  HbrVertex<T>* a = edge.GetDestVertex();
156  if (a == m_vertex) a = edge.GetOrgVertex();
157  // Must ensure vertex edits have been applied
158  if (m_meshHasEdits) {
159  a->GuaranteeNeighbors();
160  }
161  m_data->AddWithWeight(a->GetData(), m_weight);
162  m_count++;
163  }
164  }
165  private:
166  HbrVertex<T>* m_vertex;
167  T* m_data;
168  const bool m_meshHasEdits;
169  const bool m_next;
170  const float m_weight;
171  int m_count;
172  };
173 
174 private:
175  // Helper class used by RefineAtVertex.
176  class RefineFaceAtVertexOperator : public HbrFaceOperator<T> {
177  public:
178  RefineFaceAtVertexOperator(HbrSubdivision<T>* subdivision, HbrMesh<T>* mesh, HbrVertex<T> *vertex)
179  : m_subdivision(subdivision),
180  m_mesh(mesh),
181  m_vertex(vertex)
182  {
183  }
184  virtual void operator() (HbrFace<T> &face) {
185  m_subdivision->RefineFaceAtVertex(m_mesh, &face, m_vertex);
186  }
187  private:
188  HbrSubdivision<T>* const m_subdivision;
189  HbrMesh<T>* const m_mesh;
190  HbrVertex<T>* const m_vertex;
191  };
192 
193 };
194 
195 template <class T>
196 void
198  GuaranteeNeighbors(mesh, vertex);
199  RefineFaceAtVertexOperator op(this, mesh, vertex);
200  vertex->ApplyOperatorSurroundingFaces(op);
201 }
202 
203 template <class T>
204 void
206 
207  float sharpness = edge->GetSharpness();
208 
209  // In all methods, if the parent edge is infinitely sharp, the
210  // child edge is also infinitely sharp
211  if (sharpness >= HbrHalfedge<T>::k_InfinitelySharp) {
213  }
214 
215  // Chaikin's curve subdivision: use 3/4 of the parent sharpness,
216  // plus 1/4 of crease sharpnesses incident to vertex
217  else if (creaseSubdivision == HbrSubdivision<T>::k_CreaseChaikin) {
218 
219  float childsharp = 0.0f;
220 
221  int n = 0;
222 
223  // Add 1/4 of the sharpness of all crease edges incident to
224  // the vertex (other than this crease edge)
225  class ChaikinEdgeCreaseOperator : public HbrHalfedgeOperator<T> {
226  public:
227 
228  ChaikinEdgeCreaseOperator(
229  HbrHalfedge<T> const * edge, float & childsharp, int & count) :
230  m_edge(edge), m_childsharp(childsharp), m_count(count) { }
231 
232  virtual void operator() (HbrHalfedge<T> &edge) {
233 
234  // Skip original edge or it's opposite
235  if ((&edge==m_edge) || (&edge==m_edge->GetOpposite()))
236  return;
237  if (edge.GetSharpness() > HbrHalfedge<T>::k_Smooth) {
238  m_childsharp += edge.GetSharpness();
239  ++m_count;
240  }
241  }
242 
243  private:
244  HbrHalfedge<T> const * m_edge;
245  float & m_childsharp;
246  int & m_count;
247  };
248 
249  ChaikinEdgeCreaseOperator op(edge, childsharp, n);
250  vertex->GuaranteeNeighbors();
251  vertex->ApplyOperatorSurroundingEdges(op);
252 
253  if (n) {
254  childsharp = childsharp * 0.25f / float(n);
255  }
256 
257  // Add 3/4 of the sharpness of this crease edge
258  childsharp += sharpness * 0.75f;
259  childsharp -= 1.0f;
260  if (childsharp < (float) HbrHalfedge<T>::k_Smooth) {
261  childsharp = (float) HbrHalfedge<T>::k_Smooth;
262  }
263  subedge->SetSharpness(childsharp);
264 
265  } else {
266  sharpness -= 1.0f;
267  if (sharpness < (float) HbrHalfedge<T>::k_Smooth) {
268  sharpness = (float) HbrHalfedge<T>::k_Smooth;
269  }
270  subedge->SetSharpness(sharpness);
271  }
272 }
273 
274 template <class T>
275 void
277  SmoothSubdivisionVertexOperator op(data, mesh->HasVertexEdits(), weight);
279 }
280 
281 template <class T>
282 void
283 HbrSubdivision<T>::AddCreaseEdgesWithWeight(HbrMesh<T>* mesh, HbrVertex<T>* vertex, bool next, float weight, T* data) {
284  CreaseSubdivisionHalfedgeOperator op(vertex, data, mesh->HasVertexEdits(), next, weight);
285  vertex->ApplyOperatorSurroundingEdges(op);
286 }
287 
288 } // end namespace OPENSUBDIV_VERSION
289 using namespace OPENSUBDIV_VERSION;
290 
291 } // end namespace OpenSubdiv
292 
293 #endif /* HBRSUBDIVISION_H */
294 
virtual void GuaranteeNeighbor(HbrMesh< T > *mesh, HbrHalfedge< T > *edge)=0
virtual int GetFaceChildrenCount(int nvertices) const =0
void ApplyOperatorSurroundingVertices(HbrVertexOperator< T > &op) const
Definition: vertex.h:1394
virtual void Refine(HbrMesh< T > *mesh, HbrFace< T > *face)=0
void SubdivideCreaseWeight(HbrHalfedge< T > *edge, HbrVertex< T > *vertex, HbrHalfedge< T > *subedge)
Definition: subdivision.h:205
virtual void GuaranteeNeighbors(HbrMesh< T > *mesh, HbrVertex< T > *vertex)=0
void SetCreaseSubdivisionMethod(CreaseSubdivision method)
Definition: subdivision.h:93
virtual HbrFace< T > * RefineFaceAtVertex(HbrMesh< T > *mesh, HbrFace< T > *face, HbrVertex< T > *vertex)=0
virtual bool FaceIsExtraordinary(HbrMesh< T > const *, HbrFace< T > *)
Definition: subdivision.h:78
virtual bool HasLimit(HbrMesh< T > *, HbrVertex< T > *)
Definition: subdivision.h:67
virtual HbrSubdivision< T > * Clone() const =0
CreaseSubdivision GetCreaseSubdivisionMethod() const
Definition: subdivision.h:92
void AddCreaseEdgesWithWeight(HbrMesh< T > *mesh, HbrVertex< T > *vertex, bool next, float weight, T *data)
Definition: subdivision.h:283
HbrHalfedge< T > * GetOpposite() const
Definition: halfedge.h:74
virtual HbrVertex< T > * Subdivide(HbrMesh< T > *mesh, HbrFace< T > *face)=0
void ApplyOperatorSurroundingFaces(HbrFaceOperator< T > &op) const
Definition: vertex.h:1413
void ApplyOperatorSurroundingEdges(HbrHalfedgeOperator< T > &op) const
Definition: vertex.h:1351
virtual void RefineAtVertex(HbrMesh< T > *mesh, HbrVertex< T > *vertex)
Definition: subdivision.h:197
void AddSurroundingVerticesWithWeight(HbrMesh< T > *mesh, HbrVertex< T > *vertex, float weight, T *data)
Definition: subdivision.h:276
virtual bool HasLimit(HbrMesh< T > *, HbrFace< T > *)
Definition: subdivision.h:65
virtual bool VertexIsExtraordinary(HbrMesh< T > const *, HbrVertex< T > *)
Definition: subdivision.h:75
virtual bool HasLimit(HbrMesh< T > *, HbrHalfedge< T > *)
Definition: subdivision.h:66