All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bilinear.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 HBRBILINEAR_H
26 #define HBRBILINEAR_H
27 
28 /*#define HBR_DEBUG */
29 #include "../hbr/subdivision.h"
30 
31 #include "../version.h"
32 
33 namespace OpenSubdiv {
34 namespace OPENSUBDIV_VERSION {
35 
36 template <class T>
38 public:
40  : HbrSubdivision<T>() {}
41 
42  virtual HbrSubdivision<T>* Clone() const {
43  return new HbrBilinearSubdivision<T>();
44  }
45 
46  virtual void Refine(HbrMesh<T>* mesh, HbrFace<T>* face);
47  virtual HbrFace<T>* RefineFaceAtVertex(HbrMesh<T>* mesh, HbrFace<T>* face, HbrVertex<T>* vertex);
48  virtual void GuaranteeNeighbor(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
49  virtual void GuaranteeNeighbors(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
50 
51  virtual bool HasLimit(HbrMesh<T>* mesh, HbrFace<T>* face);
52  virtual bool HasLimit(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
53  virtual bool HasLimit(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
54 
55  virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrFace<T>* face);
56  virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrHalfedge<T>* edge);
57  virtual HbrVertex<T>* Subdivide(HbrMesh<T>* mesh, HbrVertex<T>* vertex);
58 
59  virtual bool VertexIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrVertex<T>* vertex) { return vertex->GetValence() != 4; }
60  virtual bool FaceIsExtraordinary(HbrMesh<T> const * /* mesh */, HbrFace<T>* face) { return face->GetNumVertices() != 4; }
61 
62  virtual int GetFaceChildrenCount(int nvertices) const { return nvertices; }
63 
64 private:
65 
66  // Transfers facevarying data from a parent face to a child face
67  void transferFVarToChild(HbrMesh<T>* mesh, HbrFace<T>* face, HbrFace<T>* child, int index);
68 
69  // Transfers vertex and edge edits from a parent face to a child face
70  void transferEditsToChild(HbrFace<T>* face, HbrFace<T>* child, int index);
71 };
72 
73 template <class T>
74 void
76 
78  const int fvarcount = mesh->GetFVarCount();
79  int fvarindex = 0;
80  const int nv = face->GetNumVertices();
81  bool extraordinary = (nv != 4);
82  HbrVertex<T> *v = face->GetVertex(index), *childVertex;
83  HbrHalfedge<T>* edge;
84 
85  // We do the face subdivision rule first, because we may reuse the
86  // result (stored in fv2) for the other subdivisions.
87  float weight = 1.0f / nv;
88 
89  // For the face center vertex, the facevarying data can be cleared
90  // and averaged en masse, since the subdivision rules don't change
91  // for any of the data - we use the smooth rule for all of it.
92  // And since we know that the fvardata for this particular vertex
93  // is smooth and therefore shareable amongst all incident faces,
94  // we don't have to allocate extra storage for it. We also don't
95  // have to compute it if some other face got to it first (as
96  // indicated by the IsInitialized() flag).
97  HbrFVarData<T>& fv2 = child->GetFVarData(extraordinary ? 2 : (index+2)%4);
98  if (!fv2.IsInitialized()) {
99  const int totalfvarwidth = mesh->GetTotalFVarWidth();
100  fv2.ClearAll(totalfvarwidth);
101  for (int j = 0; j < nv; ++j) {
102  fv2.AddWithWeightAll(face->GetFVarData(j), totalfvarwidth, weight);
103  }
104  }
105  assert(fv2.IsInitialized());
106 
107  v->GuaranteeNeighbors();
108 
109  // Make sure that that each of the vertices of the child face have
110  // the appropriate facevarying storage as needed. If there are
111  // discontinuities in any facevarying datum, the vertex must
112  // allocate a new block of facevarying storage specific to the
113  // child face.
114  bool fv0IsSmooth, fv1IsSmooth, fv3IsSmooth;
115 
116  childVertex = child->GetVertex(extraordinary ? 0 : (index+0)%4);
117  fv0IsSmooth = v->IsFVarAllSmooth();
118  if (!fv0IsSmooth) {
119  childVertex->NewFVarData(child);
120  }
121  HbrFVarData<T>& fv0 = childVertex->GetFVarData(child);
122 
123  edge = face->GetEdge(index);
124  GuaranteeNeighbor(mesh, edge);
125  assert(edge->GetOrgVertex() == v);
126  childVertex = child->GetVertex(extraordinary ? 1 : (index+1)%4);
127  fv1IsSmooth = !edge->IsFVarInfiniteSharpAnywhere();
128  if (!fv1IsSmooth) {
129  childVertex->NewFVarData(child);
130  }
131  HbrFVarData<T>& fv1 = childVertex->GetFVarData(child);
132 
133  edge = edge->GetPrev();
134  GuaranteeNeighbor(mesh, edge);
135  assert(edge == face->GetEdge((index + nv - 1) % nv));
136  assert(edge->GetDestVertex() == v);
137  childVertex = child->GetVertex(extraordinary ? 3 : (index+3)%4);
138  fv3IsSmooth = !edge->IsFVarInfiniteSharpAnywhere();
139  if (!fv3IsSmooth) {
140  childVertex->NewFVarData(child);
141  }
142  HbrFVarData<T>& fv3 = childVertex->GetFVarData(child);
143  fvarindex = 0;
144  for (int fvaritem = 0; fvaritem < fvarcount; ++fvaritem) {
145  // Vertex subdivision rule. Analyze whether the vertex is on the
146  // boundary and whether it's an infinitely sharp corner. We
147  // determine the last by checking the propagate corners flag on
148  // the mesh; if it's off, we check the two edges of this face
149  // incident to that vertex and determining whether they are
150  // facevarying boundary edges - this is analogous to what goes on
151  // for the interpolateboundary tag (which when set to
152  // EDGEANDCORNER marks vertices with a valence of two as being
153  // sharp corners). If propagate corners is on, we check *all*
154  // faces to see if two edges side by side are facevarying boundary
155  // edges. The facevarying boundary check ignores geometric
156  // sharpness, otherwise we may swim at geometric creases which
157  // aren't actually discontinuous.
158  bool infcorner = false;
159  const int fvarwidth = mesh->GetFVarWidths()[fvaritem];
160  const unsigned char fvarmask = v->GetFVarMask(fvaritem);
161  if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryEdgeAndCorner) {
162  if (fvarmask >= HbrVertex<T>::k_Corner) {
163  infcorner = true;
164  } else if (mesh->GetFVarPropagateCorners()) {
165  if (v->IsFVarCorner(fvaritem)) {
166  infcorner = true;
167  }
168  } else {
169  if (face->GetEdge(index)->GetFVarSharpness(fvaritem, true) && face->GetEdge(index)->GetPrev()->GetFVarSharpness(fvaritem, true)) {
170  infcorner = true;
171  }
172  }
173  }
174 
175  // Infinitely sharp vertex rule. Applied if the vertex is:
176  // - undergoing no facevarying boundary interpolation;
177  // - at a geometric crease, in either boundary interpolation case; or
178  // - is an infinitely sharp facevarying vertex, in the EDGEANDCORNER case; or
179  // - has a mask equal or greater than one, in the "always
180  // sharp" interpolate boundary case
181  if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
182  (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryAlwaysSharp &&
183  fvarmask >= 1) ||
184  v->GetSharpness() > HbrVertex<T>::k_Smooth ||
185  infcorner) {
186  fv0.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 1.0f);
187  }
188  // Dart rule: unlike geometric creases, because there's two
189  // discontinuous values for the one incident edge, we use the
190  // boundary rule and not the smooth rule
191  else if (fvarmask == 1) {
192  assert(!v->OnBoundary());
193 
194  // Use 0.75 of the current vert
195  fv0.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.75f);
196 
197  // 0.125 of "two adjacent edge vertices", which in actuality
198  // are the facevarying values of the same vertex but on each
199  // side of the single incident facevarying sharp edge
200  HbrHalfedge<T>* start = v->GetIncidentEdge(), *nextedge;
201  edge = start;
202  while (edge) {
203  if (edge->GetFVarSharpness(fvaritem)) {
204  break;
205  }
206  nextedge = v->GetNextEdge(edge);
207  if (nextedge == start) {
208  assert(0); // we should have found it by now
209  break;
210  } else if (!nextedge) {
211  // should never get into this case - if the vertex is
212  // on a boundary, it can never be a facevarying dart
213  // vertex
214  assert(0);
215  edge = edge->GetPrev();
216  break;
217  } else {
218  edge = nextedge;
219  }
220  }
221  HbrVertex<T>* w = edge->GetDestVertex();
222  HbrFace<T>* bestface = edge->GetLeftFace();
223  int j;
224  for (j = 0; j < bestface->GetNumVertices(); ++j) {
225  if (bestface->GetVertex(j) == w) break;
226  }
227  assert(j != bestface->GetNumVertices());
228  fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
229  bestface = edge->GetRightFace();
230  for (j = 0; j < bestface->GetNumVertices(); ++j) {
231  if (bestface->GetVertex(j) == w) break;
232  }
233  assert(j != bestface->GetNumVertices());
234  fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
235  }
236  // Boundary vertex rule
237  else if (fvarmask != 0) {
238 
239  // Use 0.75 of the current vert
240  fv0.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.75f);
241 
242  // Compute 0.125 of two adjacent edge vertices. However the
243  // two adjacent edge vertices we use must be part of the
244  // facevarying "boundary". To find the first edge we cycle
245  // counterclockwise around the current vertex v and look for
246  // the first boundary edge
247 
248  HbrFace<T>* bestface = face;
249  HbrHalfedge<T>* bestedge = face->GetEdge(index)->GetPrev();
250  HbrHalfedge<T>* starte = bestedge->GetOpposite();
251  HbrVertex<T>* w = 0;
252  if (!starte) {
253  w = face->GetEdge(index)->GetPrev()->GetOrgVertex();
254  } else {
255  HbrHalfedge<T>* e = starte, *next;
256  assert(starte->GetOrgVertex() == v);
257  do {
258  if (e->GetFVarSharpness(fvaritem) || !e->GetLeftFace()) {
259  bestface = e->GetRightFace();
260  bestedge = e;
261  break;
262  }
263  next = v->GetNextEdge(e);
264  if (!next) {
265  bestface = e->GetLeftFace();
266  w = e->GetPrev()->GetOrgVertex();
267  break;
268  }
269  e = next;
270  } while (e && e != starte);
271  }
272  if (!w) w = bestedge->GetDestVertex();
273  int j;
274  for (j = 0; j < bestface->GetNumVertices(); ++j) {
275  if (bestface->GetVertex(j) == w) break;
276  }
277  assert(j != bestface->GetNumVertices());
278  fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
279 
280  // Look for the other edge by cycling clockwise around v
281  bestface = face;
282  bestedge = face->GetEdge(index);
283  starte = bestedge;
284  w = 0;
285  if (HbrHalfedge<T>* e = starte) {
286  assert(starte->GetOrgVertex() == v);
287  do {
288  if (e->GetFVarSharpness(fvaritem) || !e->GetRightFace()) {
289  bestface = e->GetLeftFace();
290  bestedge = e;
291  break;
292  }
293  assert(e->GetOpposite());
294  e = v->GetPreviousEdge(e);
295  } while (e && e != starte);
296  }
297  if (!w) w = bestedge->GetDestVertex();
298  for (j = 0; j < bestface->GetNumVertices(); ++j) {
299  if (bestface->GetVertex(j) == w) break;
300  }
301  assert(j != bestface->GetNumVertices());
302  fv0.AddWithWeight(bestface->GetFVarData(j), fvarindex, fvarwidth, 0.125f);
303 
304  }
305  // Smooth rule. Here, we can take a shortcut if we know that
306  // the vertex is smooth and some other vertex has completely
307  // computed the facevarying values
308  else if (!fv0IsSmooth || !fv0.IsInitialized()) {
309  int valence = v->GetValence();
310  float invvalencesquared = 1.0f / (valence * valence);
311 
312  // Use n-2/n of the current vertex value
313  fv0.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, invvalencesquared * valence * (valence - 2));
314 
315  // Add 1/n^2 of surrounding edge vertices and surrounding face
316  // averages. We loop over all surrounding faces..
317  HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
318  edge = start;
319  while (edge) {
320  HbrFace<T>* g = edge->GetLeftFace();
321  weight = invvalencesquared / g->GetNumVertices();
322  // .. and compute the average of each face. At the same
323  // time, we look for the edge on that face whose origin is
324  // the same as v, and add a contribution from its
325  // destination vertex value; this takes care of the
326  // surrounding edge vertex addition.
327  for (int j = 0; j < g->GetNumVertices(); ++j) {
328  fv0.AddWithWeight(g->GetFVarData(j), fvarindex, fvarwidth, weight);
329  if (g->GetEdge(j)->GetOrgVertex() == v) {
330  fv0.AddWithWeight(g->GetFVarData((j + 1) % g->GetNumVertices()), fvarindex, fvarwidth, invvalencesquared);
331  }
332  }
333  edge = v->GetNextEdge(edge);
334  if (edge == start) break;
335  }
336  }
337 
338  // Edge subdivision rule
339  edge = face->GetEdge(index);
340 
341  if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
342  edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
343 
344  // Sharp edge rule
345  fv1.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
346  fv1.AddWithWeight(face->GetFVarData((index + 1) % nv), fvarindex, fvarwidth, 0.5f);
347  } else if (!fv1IsSmooth || !fv1.IsInitialized()) {
348  // Smooth edge subdivision. Add 0.25 of adjacent vertices
349  fv1.SetWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.25f);
350  fv1.AddWithWeight(face->GetFVarData((index + 1) % nv), fvarindex, fvarwidth, 0.25f);
351  // Local subdivided face vertex
352  fv1.AddWithWeight(fv2, fvarindex, fvarwidth, 0.25f);
353  // Add 0.25 * average of neighboring face vertices
354  HbrFace<T>* oppFace = edge->GetRightFace();
355  weight = 0.25f / oppFace->GetNumVertices();
356  for (int j = 0; j < oppFace->GetNumVertices(); ++j) {
357  fv1.AddWithWeight(oppFace->GetFVarData(j), fvarindex, fvarwidth, weight);
358  }
359  }
360 
361 
362  // Edge subdivision rule
363  edge = edge->GetPrev();
364 
365  if (fvarinterp == HbrMesh<T>::k_InterpolateBoundaryNone ||
366  edge->GetFVarSharpness(fvaritem) || edge->IsBoundary()) {
367 
368  // Sharp edge rule
369  fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.5f);
370  fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.5f);
371  } else if (!fv3IsSmooth || !fv3.IsInitialized()) {
372  // Smooth edge subdivision. Add 0.25 of adjacent vertices
373  fv3.SetWithWeight(face->GetFVarData((index + nv - 1) % nv), fvarindex, fvarwidth, 0.25f);
374  fv3.AddWithWeight(face->GetFVarData(index), fvarindex, fvarwidth, 0.25f);
375  // Local subdivided face vertex
376  fv3.AddWithWeight(fv2, fvarindex, fvarwidth, 0.25f);
377  // Add 0.25 * average of neighboring face vertices
378  HbrFace<T>* oppFace = edge->GetRightFace();
379  weight = 0.25f / oppFace->GetNumVertices();
380  for (int j = 0; j < oppFace->GetNumVertices(); ++j) {
381  fv3.AddWithWeight(oppFace->GetFVarData(j), fvarindex, fvarwidth, weight);
382  }
383  }
384 
385  fvarindex += fvarwidth;
386  }
387  fv0.SetInitialized();
388  fv1.SetInitialized();
389  fv3.SetInitialized();
390 }
391 
392 template <class T>
393 void
394 HbrBilinearSubdivision<T>::transferEditsToChild(HbrFace<T>* face, HbrFace<T>* child, int index) {
395 
396  // Hand down hole tag
397  child->SetHole(face->IsHole());
398 
399  // Hand down pointers to hierarchical edits
400  if (HbrHierarchicalEdit<T>** edits = face->GetHierarchicalEdits()) {
401  while (HbrHierarchicalEdit<T>* edit = *edits) {
402  if (!edit->IsRelevantToFace(face)) break;
403  if (edit->GetNSubfaces() > face->GetDepth() &&
404  (edit->GetSubface(face->GetDepth()) == index)) {
405  child->SetHierarchicalEdits(edits);
406  break;
407  }
408  edits++;
409  }
410  }
411 }
412 
413 
414 template <class T>
415 void
417 
418  // Create new quadrilateral children faces from this face
419  HbrFace<T>* child;
420  HbrVertex<T>* vertices[4];
421  HbrHalfedge<T>* edge = face->GetFirstEdge();
422  HbrHalfedge<T>* prevedge = edge->GetPrev();
423  HbrHalfedge<T>* childedge;
424  int nv = face->GetNumVertices();
425  float sharpness;
426  bool extraordinary = (nv != 4);
427  // The funny indexing on vertices is done only for
428  // non-extraordinary faces in order to correctly preserve
429  // parametric space through the refinement. If we split an
430  // extraordinary face then it doesn't matter.
431  for (int i = 0; i < nv; ++i) {
432  if (!face->GetChild(i)) {
433 #ifdef HBR_DEBUG
434  std::cerr << "Kid " << i << "\n";
435 #endif
436  HbrVertex<T>* vertex = edge->GetOrgVertex();
437  if (extraordinary) {
438  vertices[0] = vertex->Subdivide();
439  vertices[1] = edge->Subdivide();
440  vertices[2] = face->Subdivide();
441  vertices[3] = prevedge->Subdivide();
442  } else {
443  vertices[i] = vertex->Subdivide();
444  vertices[(i+1)%4] = edge->Subdivide();
445  vertices[(i+2)%4] = face->Subdivide();
446  vertices[(i+3)%4] = prevedge->Subdivide();
447  }
448  child = mesh->NewFace(4, vertices, face, i);
449 #ifdef HBR_DEBUG
450  std::cerr << "Creating face " << *child << " during refine\n";
451 #endif
452 
453  // Hand down edge sharpnesses
454  childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
455  assert(childedge);
456  if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
457  HbrSubdivision<T>::SubdivideCreaseWeight(edge, edge->GetOrgVertex(), childedge);
458  }
459  childedge->CopyFVarInfiniteSharpness(edge);
460 
461  childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
462  assert(childedge);
463  if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
464  HbrSubdivision<T>::SubdivideCreaseWeight(prevedge, prevedge->GetDestVertex(), childedge);
465  }
466  childedge->CopyFVarInfiniteSharpness(prevedge);
467 
468  if (mesh->GetTotalFVarWidth()) {
469  transferFVarToChild(mesh, face, child, i);
470  }
471 
472  // Special handling of ptex index for extraordinary faces: make
473  // sure the children get their indices reassigned to be
474  // consecutive within the block reserved for the parent.
475  if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
476  child->SetPtexIndex(face->GetPtexIndex() + i);
477  }
478 
479  transferEditsToChild(face, child, i);
480  }
481  prevedge = edge;
482  edge = edge->GetNext();
483  }
484 }
485 
486 template <class T>
487 HbrFace<T>*
489 
490 #ifdef HBR_DEBUG
491  std::cerr << " forcing refine on " << *face << " at " << *vertex << '\n';
492 #endif
493 
494  // Create new quadrilateral children faces from this face
495  HbrHalfedge<T>* edge = face->GetFirstEdge();
496  HbrHalfedge<T>* prevedge = edge->GetPrev();
497  HbrHalfedge<T>* childedge;
498  int nv = face->GetNumVertices();
499  float sharpness;
500  bool extraordinary = (nv != 4);
501  // The funny indexing on vertices is done only for
502  // non-extraordinary faces in order to correctly preserve
503  // parametric space through the refinement. If we split an
504  // extraordinary face then it doesn't matter.
505  for (int i = 0; i < nv; ++i) {
506  if (edge->GetOrgVertex() == vertex) {
507  if (!face->GetChild(i)) {
508  HbrFace<T>* child;
509  HbrVertex<T>* vertices[4];
510  if (extraordinary) {
511  vertices[0] = vertex->Subdivide();
512  vertices[1] = edge->Subdivide();
513  vertices[2] = face->Subdivide();
514  vertices[3] = prevedge->Subdivide();
515  } else {
516  vertices[i] = vertex->Subdivide();
517  vertices[(i+1)%4] = edge->Subdivide();
518  vertices[(i+2)%4] = face->Subdivide();
519  vertices[(i+3)%4] = prevedge->Subdivide();
520  }
521 #ifdef HBR_DEBUG
522  std::cerr << "Kid " << i << "\n";
523  std::cerr << " subdivision created " << *vertices[0] << '\n';
524  std::cerr << " subdivision created " << *vertices[1] << '\n';
525  std::cerr << " subdivision created " << *vertices[2] << '\n';
526  std::cerr << " subdivision created " << *vertices[3] << '\n';
527 #endif
528  child = mesh->NewFace(4, vertices, face, i);
529 #ifdef HBR_DEBUG
530  std::cerr << "Creating face " << *child << " during refine\n";
531 #endif
532  // Hand down edge sharpness
533  childedge = vertex->Subdivide()->GetEdge(edge->Subdivide());
534  assert(childedge);
535  if ((sharpness = edge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
536  HbrSubdivision<T>::SubdivideCreaseWeight(edge, edge->GetOrgVertex(), childedge);
537  }
538  childedge->CopyFVarInfiniteSharpness(edge);
539 
540  childedge = prevedge->Subdivide()->GetEdge(vertex->Subdivide());
541  assert(childedge);
542  if ((sharpness = prevedge->GetSharpness()) > HbrHalfedge<T>::k_Smooth) {
543  HbrSubdivision<T>::SubdivideCreaseWeight(prevedge, prevedge->GetDestVertex(), childedge);
544  }
545  childedge->CopyFVarInfiniteSharpness(prevedge);
546 
547  if (mesh->GetTotalFVarWidth()) {
548  transferFVarToChild(mesh, face, child, i);
549  }
550 
551  // Special handling of ptex index for extraordinary faces: make
552  // sure the children get their indices reassigned to be
553  // consecutive within the block reserved for the parent.
554  if (face->GetNumVertices() != 4 && face->GetPtexIndex() != -1) {
555  child->SetPtexIndex(face->GetPtexIndex() + i);
556  }
557 
558  transferEditsToChild(face, child, i);
559  return child;
560  } else {
561  return face->GetChild(i);
562  }
563  }
564  prevedge = edge;
565  edge = edge->GetNext();
566  }
567  return 0;
568 }
569 
570 template <class T>
571 void
573  if (edge->GetOpposite()) {
574  return;
575  }
576 
577  // For the given edge: if the parent of either of its incident
578  // vertices is itself a _face_, then ensuring that this parent
579  // face has refined at a particular vertex is sufficient to
580  // ensure that both of the faces on each side of the edge have
581  // been created.
582  bool destParentWasEdge = true;
583  HbrFace<T>* parentFace = edge->GetOrgVertex()->GetParentFace();
584  HbrHalfedge<T>* parentEdge = edge->GetDestVertex()->GetParentEdge();
585  if (!parentFace) {
586  destParentWasEdge = false;
587  parentFace = edge->GetDestVertex()->GetParentFace();
588  parentEdge = edge->GetOrgVertex()->GetParentEdge();
589  }
590 
591  if (parentFace) {
592 
593  // Make sure we deal with a parent halfedge which is
594  // associated with the parent face
595  if (parentEdge->GetFace() != parentFace) {
596  parentEdge = parentEdge->GetOpposite();
597  }
598  // If one of the vertices had a parent face, the other one MUST
599  // have been a child of an edge
600  assert(parentEdge && parentEdge->GetFace() == parentFace);
601 #ifdef HBR_DEBUG
602  std::cerr << "\nparent edge is " << *parentEdge << "\n";
603 #endif
604 
605  // The vertex to refine at depends on whether the
606  // destination or origin vertex of this edge had a parent
607  // edge
608  if (destParentWasEdge) {
609  RefineFaceAtVertex(mesh, parentFace, parentEdge->GetOrgVertex());
610  } else {
611  RefineFaceAtVertex(mesh, parentFace, parentEdge->GetDestVertex());
612  }
613 
614  // It should always be the case that the opposite now exists -
615  // we can't have a boundary case here
616  assert(edge->GetOpposite());
617  } else {
618  HbrVertex<T>* parentVertex = edge->GetOrgVertex()->GetParentVertex();
619  parentEdge = edge->GetDestVertex()->GetParentEdge();
620  if (!parentVertex) {
621  parentVertex = edge->GetDestVertex()->GetParentVertex();
622  parentEdge = edge->GetOrgVertex()->GetParentEdge();
623  }
624 
625  if (parentVertex) {
626 
627  assert(parentEdge);
628 
629 #ifdef HBR_DEBUG
630  std::cerr << "\nparent edge is " << *parentEdge << "\n";
631 #endif
632 
633  // 1. Go up to the parent of my face
634 
635  parentFace = edge->GetFace()->GetParent();
636 #ifdef HBR_DEBUG
637  std::cerr << "\nparent face is " << *parentFace << "\n";
638 #endif
639 
640  // 2. Ask the opposite face (if it exists) to refine
641  if (parentFace) {
642 
643  // A vertex can be associated with either of two
644  // parent halfedges. If the parent edge that we're
645  // interested in doesn't match then we should look at
646  // its opposite
647  if (parentEdge->GetFace() != parentFace)
648  parentEdge = parentEdge->GetOpposite();
649  assert(parentEdge->GetFace() == parentFace);
650 
651  // Make sure the parent edge has its neighbor as well
652  GuaranteeNeighbor(mesh, parentEdge);
653 
654  // Now access that neighbor and refine it
655  if (parentEdge->GetRightFace()) {
656  RefineFaceAtVertex(mesh, parentEdge->GetRightFace(), parentVertex);
657 
658  // FIXME: assertion?
659  assert(edge->GetOpposite());
660  }
661  }
662  }
663  }
664 }
665 
666 template <class T>
667 void
669 
670 #ifdef HBR_DEBUG
671  std::cerr << "\n\nneighbor guarantee at " << *vertex << " invoked\n";
672 #endif
673 
674  // If the vertex is a child of a face, guaranteeing the neighbors
675  // of the vertex is simply a matter of ensuring the parent face
676  // has refined.
677  HbrFace<T>* parentFace = vertex->GetParentFace();
678  if (parentFace) {
679 
680 #ifdef HBR_DEBUG
681  std::cerr << " forcing full refine on parent face\n";
682 #endif
683  Refine(mesh, parentFace);
684  return;
685  }
686 
687  // Otherwise if the vertex is a child of an edge, we need to
688  // ensure that the parent faces on either side of the parent edge
689  // 1) exist, and 2) have refined at both vertices of the parent
690  // edge
691  HbrHalfedge<T>* parentEdge = vertex->GetParentEdge();
692  if (parentEdge) {
693 
694 #ifdef HBR_DEBUG
695  std::cerr << " forcing full refine on adjacent faces of parent edge\n";
696 #endif
697  HbrVertex<T>* dest = parentEdge->GetDestVertex();
698  HbrVertex<T>* org = parentEdge->GetOrgVertex();
699  GuaranteeNeighbor(mesh, parentEdge);
700  parentFace = parentEdge->GetLeftFace();
701  RefineFaceAtVertex(mesh, parentFace, dest);
702  RefineFaceAtVertex(mesh, parentFace, org);
703 
704 #ifdef HBR_DEBUG
705  std::cerr << " on the right face?\n";
706 #endif
707  parentFace = parentEdge->GetRightFace();
708  // The right face may not necessarily exist even after
709  // GuaranteeNeighbor
710  if (parentFace) {
711  RefineFaceAtVertex(mesh, parentFace, dest);
712  RefineFaceAtVertex(mesh, parentFace, org);
713  }
714 #ifdef HBR_DEBUG
715  std::cerr << " end force\n";
716 #endif
717  return;
718  }
719 
720  // The last case: the vertex is a child of a vertex. In this case
721  // we have to first recursively guarantee that the parent's
722  // adjacent faces also exist.
723  HbrVertex<T>* parentVertex = vertex->GetParentVertex();
724  if (parentVertex) {
725 
726 #ifdef HBR_DEBUG
727  std::cerr << " recursive parent vertex guarantee call\n";
728 #endif
729  parentVertex->GuaranteeNeighbors();
730 
731  // And then we refine all the face neighbors of the
732  // parentVertex
733  HbrHalfedge<T>* start = parentVertex->GetIncidentEdge(), *edge;
734  edge = start;
735  while (edge) {
736  HbrFace<T>* f = edge->GetLeftFace();
737  RefineFaceAtVertex(mesh, f, parentVertex);
738  edge = parentVertex->GetNextEdge(edge);
739  if (edge == start) break;
740  }
741  }
742 }
743 
744 template <class T>
745 bool
747 
748  if (face->IsHole()) return false;
749  // A limit face exists if all the bounding edges have limit curves
750  for (int i = 0; i < face->GetNumVertices(); ++i) {
751  if (!HasLimit(mesh, face->GetEdge(i))) {
752  return false;
753  }
754  }
755  return true;
756 }
757 
758 template <class T>
759 bool
761  return true;
762 }
763 
764 template <class T>
765 bool
767  vertex->GuaranteeNeighbors();
768  switch (vertex->GetMask(false)) {
771  return !vertex->OnBoundary();
772  break;
775  default:
776  return true;
777  }
778 }
779 
780 template <class T>
783 
784  // Face rule: simply average all vertices on the face
785  HbrVertex<T>* v = mesh->NewVertex();
786  T& data = v->GetData();
787  int nv = face->GetNumVertices();
788  float weight = 1.0f / nv;
789 
790  HbrHalfedge<T>* edge = face->GetFirstEdge();
791  for (int i = 0; i < face->GetNumVertices(); ++i) {
792  HbrVertex<T>* w = edge->GetOrgVertex();
793  // If there are vertex edits we have to make sure the edit
794  // has been applied
795  if (mesh->HasVertexEdits()) {
796  w->GuaranteeNeighbors();
797  }
798  data.AddWithWeight(w->GetData(), weight);
799  data.AddVaryingWithWeight(w->GetData(), weight);
800  edge = edge->GetNext();
801  }
802 #ifdef HBR_DEBUG
803  std::cerr << "Subdividing at " << *face << "\n";
804 #endif
805 
806  // Set the extraordinary flag if the face had anything other than
807  // 4 vertices
808  if (nv != 4) v->SetExtraordinary();
809 
810 #ifdef HBR_DEBUG
811  std::cerr << " created " << *v << "\n";
812 #endif
813  return v;
814 }
815 
816 template <class T>
819 
820 #ifdef HBR_DEBUG
821  float esharp = edge->GetSharpness();
822  std::cerr << "Subdividing at " << *edge << " (sharpness = " << esharp << ")";
823 #endif
824 
825  HbrVertex<T>* v = mesh->NewVertex();
826  T& data = v->GetData();
827 
828 
829  // If there's the possibility of a crease edits, make sure the
830  // edit has been applied
831  if (mesh->HasCreaseEdits()) {
832  edge->GuaranteeNeighbor();
833  }
834 
835  // If there's the possibility of vertex edits on either vertex, we
836  // have to make sure the edit has been applied
837  if (mesh->HasVertexEdits()) {
838  edge->GetOrgVertex()->GuaranteeNeighbors();
839  edge->GetDestVertex()->GuaranteeNeighbors();
840  }
841 
842  // Average the two end points
843  data.AddWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
844  data.AddWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
845 
846  // Varying data is always the average of two end points
847  data.AddVaryingWithWeight(edge->GetOrgVertex()->GetData(), 0.5f);
848  data.AddVaryingWithWeight(edge->GetDestVertex()->GetData(), 0.5f);
849 
850 #ifdef HBR_DEBUG
851  std::cerr << " created " << *v << "\n";
852 #endif
853  return v;
854 }
855 
856 template <class T>
859 
860  HbrVertex<T>* v;
861 
862  // If there are vertex edits we have to make sure the edit has
863  // been applied by guaranteeing the neighbors of the
864  // vertex. Unfortunately in this case, we can't share the data
865  // with the parent
866  if (mesh->HasVertexEdits()) {
867  vertex->GuaranteeNeighbors();
868 
869  v = mesh->NewVertex();
870  T& data = v->GetData();
871 
872  // Just copy the old value
873  data.AddWithWeight(vertex->GetData(), 1.0f);
874 
875  // Varying data is always just propagated down
876  data.AddVaryingWithWeight(vertex->GetData(), 1.0f);
877 
878  } else {
879  // Create a new vertex that just shares the same data
880  v = mesh->NewVertex(vertex->GetData());
881  }
882 
883 #ifdef HBR_DEBUG
884  std::cerr << "Subdividing at " << *vertex << "\n";
885  std::cerr << " created " << *v << "\n";
886 #endif
887  // Inherit extraordinary flag and sharpness
888  if (vertex->IsExtraordinary()) v->SetExtraordinary();
889  float sharp = vertex->GetSharpness();
890  if (sharp >= HbrVertex<T>::k_InfinitelySharp) {
891  v->SetSharpness(HbrVertex<T>::k_InfinitelySharp);
892  } else if (sharp > HbrVertex<T>::k_Smooth) {
893  sharp -= 1.0f;
894  if (sharp < (float) HbrVertex<T>::k_Smooth) {
895  sharp = (float) HbrVertex<T>::k_Smooth;
896  }
897  v->SetSharpness(sharp);
898  } else {
899  v->SetSharpness(HbrVertex<T>::k_Smooth);
900  }
901  return v;
902 }
903 
904 } // end namespace OPENSUBDIV_VERSION
905 using namespace OPENSUBDIV_VERSION;
906 
907 } // end namespace OpenSubdiv
908 
909 #endif /* HBRBILINEAR_H */
910 
HbrHalfedge< T > * GetEdge(int index) const
Definition: face.h:718
virtual int GetFaceChildrenCount(int nvertices) const
Definition: bilinear.h:62
HbrVertex< T > * NewVertex(int id, const T &data)
Definition: mesh.h:533
virtual void GuaranteeNeighbors(HbrMesh< T > *mesh, HbrVertex< T > *vertex)
Definition: bilinear.h:668
HbrFace< T > * GetRightFace() const
Definition: halfedge.h:166
void AddWithWeightAll(const HbrFVarData &fvvi, int width, float weight)
Definition: fvarData.h:120
InterpolateBoundaryMethod GetFVarInterpolateBoundaryMethod() const
Definition: mesh.h:211
void CopyFVarInfiniteSharpness(HbrHalfedge< T > *edge)
Definition: halfedge.h:185
unsigned char GetMask(bool next)
Definition: vertex.h:1179
HbrHalfedge< T > * GetFirstEdge() const
Definition: face.h:136
void SubdivideCreaseWeight(HbrHalfedge< T > *edge, HbrVertex< T > *vertex, HbrHalfedge< T > *subedge)
Definition: subdivision.h:205
virtual HbrSubdivision< T > * Clone() const
Definition: bilinear.h:42
virtual HbrFace< T > * RefineFaceAtVertex(HbrMesh< T > *mesh, HbrFace< T > *face, HbrVertex< T > *vertex)
Definition: bilinear.h:488
HbrFace< T > * GetChild(int index) const
Definition: face.h:164
HbrHalfedge< T > * GetNext() const
Definition: halfedge.h:80
HbrVertex< T > * GetDestVertex() const
Definition: halfedge.h:143
HbrHalfedge< T > * GetPreviousEdge(const HbrHalfedge< T > *edge) const
Definition: vertex.h:998
HbrFace< T > * GetLeftFace() const
Definition: halfedge.h:169
float GetFVarSharpness(int datum, bool ignoreGeometry=false)
Definition: halfedge.h:684
HbrVertex< T > * GetParentVertex() const
Definition: vertex.h:222
HbrVertex< T > * Subdivide()
Definition: face.h:786
virtual void GuaranteeNeighbor(HbrMesh< T > *mesh, HbrHalfedge< T > *edge)
Definition: bilinear.h:572
HbrFVarData< T > & GetFVarData(int index)
Definition: face.h:221
unsigned char GetFVarMask(int datum)
Definition: vertex.h:1251
HbrHalfedge< T > * GetIncidentEdge() const
Definition: vertex.h:285
virtual bool FaceIsExtraordinary(HbrMesh< T > const *, HbrFace< T > *face)
Definition: bilinear.h:60
HbrHalfedge< T > * GetNextEdge(const HbrHalfedge< T > *edge) const
Definition: vertex.h:990
HbrHalfedge< T > * GetOpposite() const
Definition: halfedge.h:74
HbrVertex< T > * GetVertex(int index) const
Definition: face.h:730
HbrVertex< T > * GetOrgVertex() const
Definition: halfedge.h:125
virtual void Refine(HbrMesh< T > *mesh, HbrFace< T > *face)
Definition: bilinear.h:416
virtual bool VertexIsExtraordinary(HbrMesh< T > const *, HbrVertex< T > *vertex)
Definition: bilinear.h:59
HbrFace< T > * NewFace(int nvertices, const int *vtx, int uindex)
Definition: mesh.h:607
virtual bool HasLimit(HbrMesh< T > *mesh, HbrFace< T > *face)
Definition: bilinear.h:746
virtual HbrVertex< T > * Subdivide(HbrMesh< T > *mesh, HbrFace< T > *face)
Definition: bilinear.h:782
const int * GetFVarWidths() const
Definition: mesh.h:187
HbrHalfedge< T > * GetPrev() const
Definition: halfedge.h:98