All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
topologyRefiner.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 FAR_TOPOLOGY_REFINER_H
25 #define FAR_TOPOLOGY_REFINER_H
26 
27 #include "../version.h"
28 
29 #include "../sdc/type.h"
30 #include "../sdc/options.h"
31 #include "../sdc/catmarkScheme.h"
32 #include "../vtr/level.h"
33 #include "../vtr/fvarLevel.h"
34 #include "../vtr/refinement.h"
35 #include "../vtr/fvarRefinement.h"
36 #include "../vtr/maskInterfaces.h"
37 #include "../far/types.h"
38 
39 #include <vector>
40 #include <cassert>
41 #include <cstdio>
42 
43 namespace OpenSubdiv {
44 namespace OPENSUBDIV_VERSION {
45 
46 namespace Vtr { class SparseSelector; }
47 
48 namespace Far {
49 
50 template <class MESH> class TopologyRefinerFactory;
51 
56 
57 public:
58 
61 
64 
66  Sdc::Type GetSchemeType() const { return _subdivType; }
67 
69  Sdc::Options GetSchemeOptions() const { return _subdivOptions; }
70 
72  bool IsUniform() const { return _isUniform; }
73 
75  int GetMaxLevel() const { return _maxLevel; }
76 
77  // XXXX barfowl -- should cache these internally for trivial return)
78 
80  int GetNumVerticesTotal() const;
81 
83  int GetNumEdgesTotal() const;
84 
86  int GetNumFacesTotal() const;
87 
89  int GetNumFaceVerticesTotal() const;
90 
91 
92  //
93  // High level refinement and related methods:
94  //
95  // XXXX barfowl -- need some variants here for different refinement
96  // options, i.e. single refine method plus struct
97  // RefineOptions
98  //
99 
100 
108  void RefineUniform(int maxLevel, bool fullTopologyInLastLevel = false);
109 
117  void RefineAdaptive(int maxLevel, bool fullTopologyInLastLevel = false);
118 
120  void Unrefine();
121 
123  void Clear();
124 
125 #ifdef _VTR_COMPUTE_MASK_WEIGHTS_ENABLED
126  void ComputeMaskWeights();
127 #endif
128 
129 
130  //
131  // Primvar data interpolation:
132  //
133 
134 
145  template <class T, class U> void Interpolate(T const * src, U * dst) const;
146 
160  template <class T, class U> void Interpolate(int level, T const * src, U * dst) const;
161 
162 
175  template <class T, class U> void InterpolateVarying(T const * src, U * dst) const;
176 
192  template <class T, class U> void InterpolateVarying(int level, T const * src, U * dst) const;
193 
195  // associated with a particular face-varying channel
197  template <class T, class U> void InterpolateFaceVarying(T const * src, U * dst, int channel = 0) const;
198 
199  template <class T, class U> void InterpolateFaceVarying(int level, T const * src, U * dst, int channel = 0) const;
200 
201 
202  //
203  // Inspection of components per level:
204  //
205 
206 
208  int GetNumVertices(int level) const {
209  return _levels[level].getNumVertices();
210  }
211 
213  int GetNumEdges(int level) const {
214  return _levels[level].getNumEdges();
215  }
216 
218  int GetNumFaces(int level) const {
219  return _levels[level].getNumFaces();
220  }
221 
223  int GetNumFaceVertices(int level) const {
224  return _levels[level].getNumFaceVerticesTotal();
225  }
226 
228  float GetEdgeSharpness(int level, Index edge) const {
229  return _levels[level].getEdgeSharpness(edge);
230  }
231 
233  float GetVertexSharpness(int level, Index vert) const {
234  return _levels[level].getVertexSharpness(vert);
235  }
236 
238  Sdc::Crease::Rule GetVertexRule(int level, Index vert) const {
239  return _levels[level].getVertexRule(vert);
240  }
241 
242 
243  //
244  // Topological relations -- incident/adjacent components:
245  //
246 
247 
249  IndexArray const GetFaceVertices(int level, Index face) const {
250  return _levels[level].getFaceVertices(face);
251  }
252 
254  IndexArray const GetFaceEdges( int level, Index face) const {
255  return _levels[level].getFaceEdges(face);
256  }
257 
259  IndexArray const GetEdgeVertices(int level, Index edge) const {
260  return _levels[level].getEdgeVertices(edge);
261  }
262 
264  IndexArray const GetEdgeFaces( int level, Index edge) const {
265  return _levels[level].getEdgeFaces(edge);
266  }
267 
269  IndexArray const GetVertexFaces( int level, Index vert) const {
270  return _levels[level].getVertexFaces(vert);
271  }
272 
274  IndexArray const GetVertexEdges( int level, Index vert) const {
275  return _levels[level].getVertexEdges(vert);
276  }
277 
279  LocalIndexArray const VertexFaceLocalIndices(int level, Index vert) const {
280  return _levels[level].getVertexFaceLocalIndices(vert);
281  }
282 
284  LocalIndexArray const VertexEdgeLocalIndices(int level, Index vert) const {
285  return _levels[level].getVertexEdgeLocalIndices(vert);
286  }
287 
290  Index FindEdge(int level, Index v0, Index v1) const {
291  return _levels[level].findEdge(v0, v1);
292  }
293 
294 
295  //
296  // Inspection of face-varying channels and their contents:
297  //
298 
299 
301  int GetNumFVarChannels() const {
302  return _levels[0].getNumFVarChannels();
303  }
304 
306  int GetNumFVarValuesTotal(int channel = 0) const;
307 
309  int GetNumFVarValues(int level, int channel = 0) const {
310  return _levels[level].getNumFVarValues(channel);
311  }
312 
314  IndexArray const GetFVarFaceValues(int level, Index face, int channel = 0) const {
315  return _levels[level].getFVarFaceValues(face, channel);
316  }
317 
318 
319  //
320  // Parent-to-child relationships, i.e. relationships between components in one level
321  // and the next (entries may be invalid if sparse):
322  //
323 
324 
326  IndexArray const GetFaceChildFaces(int level, Index f) const {
327  return _refinements[level].getFaceChildFaces(f);
328  }
329 
331  IndexArray const GetFaceChildEdges(int level, Index f) const {
332  return _refinements[level].getFaceChildEdges(f);
333  }
334 
336  IndexArray const GetEdgeChildEdges(int level, Index e) const {
337  return _refinements[level].getEdgeChildEdges(e);
338  }
339 
341  Index GetFaceChildVertex( int level, Index f) const {
342  return _refinements[level].getFaceChildVertex(f);
343  }
344 
346  Index GetEdgeChildVertex( int level, Index e) const {
347  return _refinements[level].getEdgeChildVertex(e);
348  }
349 
351  Index GetVertexChildVertex(int level, Index v) const {
352  return _refinements[level].getVertexChildVertex(v);
353  }
354 
355 
356  //
357  // Ptex:
358  //
359 
361  int GetNumPtexFaces() const;
362 
364  int GetPtexIndex(Index f) const;
365 
366 
367  //
368  // Debugging aides:
369  //
370 
371 
373  bool ValidateTopology(int level) const {
374  return _levels[level].validateTopology();
375  }
376 
378  void PrintTopology(int level, bool children = true) const {
379  _levels[level].print(children ? &_refinements[level] : 0);
380  }
381 
382 
383 protected:
384 
385  //
386  // For use by the Factory base and subclasses to construct the base level:
387  //
388  template <class MESH>
391  friend class PatchTablesFactory;
392 
393  int getNumLevels() const { return (int)_levels.size(); }
394  Vtr::Level & getBaseLevel() { return _levels.front(); }
395  Vtr::Level & getLevel(int l) { return _levels[l]; }
396  Vtr::Level const & getLevel(int l) const { return _levels[l]; }
397  Vtr::Refinement const & getRefinement(int l) const { return _refinements[l]; }
398 
399  int getNumBaseFaces() const { return GetNumFaces(0); }
400  int getNumBaseEdges() const { return GetNumEdges(0); }
401  int getNumBaseVertices() const { return GetNumVertices(0); }
402 
403  // Sizing specifications required before allocation:
404  void setNumBaseFaces( int count) { _levels[0].resizeFaces(count); }
405  void setNumBaseEdges( int count) { _levels[0].resizeEdges(count); }
406  void setNumBaseVertices(int count) { _levels[0].resizeVertices(count); }
407 
408  void setNumBaseFaceVertices(Index f, int count) { _levels[0].resizeFaceVertices(f, count); }
409  void setNumBaseEdgeFaces( Index e, int count) { _levels[0].resizeEdgeFaces(e, count); }
410  void setNumBaseVertexFaces( Index v, int count) { _levels[0].resizeVertexFaces(v, count); }
411  void setNumBaseVertexEdges( Index v, int count) { _levels[0].resizeVertexEdges(v, count); }
412 
413  // Access to populate the base level topology after allocation:
414  IndexArray setBaseFaceVertices(Index f) { return _levels[0].getFaceVertices(f); }
415  IndexArray setBaseFaceEdges( Index f) { return _levels[0].getFaceEdges(f); }
416  IndexArray setBaseEdgeVertices(Index e) { return _levels[0].getEdgeVertices(e); }
417  IndexArray setBaseEdgeFaces( Index e) { return _levels[0].getEdgeFaces(e); }
418  IndexArray setBaseVertexFaces( Index v) { return _levels[0].getVertexFaces(v); }
419  IndexArray setBaseVertexEdges( Index v) { return _levels[0].getVertexEdges(v); }
420 
421  // Not sure yet if we will determine these internally...
422  LocalIndexArray setBaseVertexFaceLocalIndices(Index v) { return _levels[0].getVertexFaceLocalIndices(v); }
423  LocalIndexArray setBaseVertexEdgeLocalIndices(Index v) { return _levels[0].getVertexEdgeLocalIndices(v); }
424 
425  // Optionally available to get/set sharpness values:
426  float& baseEdgeSharpness(Index e) { return _levels[0].getEdgeSharpness(e); }
427  float& baseVertexSharpness(Index v) { return _levels[0].getVertexSharpness(v); }
428 
429  // Face-varying modifiers for constructing face-varying channels:
430  int createFVarChannel(int numValues) {
431  return _levels[0].createFVarChannel(numValues, _subdivOptions);
432  }
433  int createFVarChannel(int numValues, Sdc::Options const& options) {
434  return _levels[0].createFVarChannel(numValues, options);
435  }
436  void completeFVarChannelTopology(int channel = 0) { _levels[0].completeFVarChannelTopology(channel); }
437 
438  IndexArray getBaseFVarFaceValues(Index face, int channel = 0) { return _levels[0].getFVarFaceValues(face, channel); }
439 
442  }
443 
444 private:
445  // Prototype -- mainly for illustrative purposes right now...
446  void catmarkFeatureAdaptiveSelector(Vtr::SparseSelector& selector);
447  void catmarkFeatureAdaptiveSelectorByFace(Vtr::SparseSelector& selector);
448 
449  template <class T, class U> void interpolateChildVertsFromFaces(Vtr::Refinement const &, T const * src, U * dst) const;
450  template <class T, class U> void interpolateChildVertsFromEdges(Vtr::Refinement const &, T const * src, U * dst) const;
451  template <class T, class U> void interpolateChildVertsFromVerts(Vtr::Refinement const &, T const * src, U * dst) const;
452 
453  template <class T, class U> void varyingInterpolateChildVertsFromFaces(Vtr::Refinement const &, T const * src, U * dst) const;
454  template <class T, class U> void varyingInterpolateChildVertsFromEdges(Vtr::Refinement const &, T const * src, U * dst) const;
455  template <class T, class U> void varyingInterpolateChildVertsFromVerts(Vtr::Refinement const &, T const * src, U * dst) const;
456 
457  template <class T, class U> void faceVaryingInterpolateChildVertsFromFaces(Vtr::Refinement const &, T const * src, U * dst, int channel) const;
458  template <class T, class U> void faceVaryingInterpolateChildVertsFromEdges(Vtr::Refinement const &, T const * src, U * dst, int channel) const;
459  template <class T, class U> void faceVaryingInterpolateChildVertsFromVerts(Vtr::Refinement const &, T const * src, U * dst, int channel) const;
460 
461 
462  void initializePtexIndices() const;
463 
464 private:
465  // The following should be private but leaving it open while still early...
466  Sdc::Type _subdivType;
467  Sdc::Options _subdivOptions;
468 
469  bool _isUniform;
470  int _maxLevel;
471 
472  std::vector<Vtr::Level> _levels;
473  std::vector<Vtr::Refinement> _refinements;
474 
475  std::vector<Index> _ptexIndices;
476 };
477 
478 template <class T, class U>
479 inline void
480 TopologyRefiner::Interpolate(T const * src, U * dst) const {
481 
482  assert(_subdivType == Sdc::TYPE_CATMARK);
483 
484  for (int level=1; level<=GetMaxLevel(); ++level) {
485 
486  Interpolate(level, src, dst);
487 
488  src = dst;
489  dst += GetNumVertices(level);
490  }
491 }
492 
493 template <class T, class U>
494 inline void
495 TopologyRefiner::Interpolate(int level, T const * src, U * dst) const {
496 
497  assert(level>0 and level<=(int)_refinements.size());
498 
499  Vtr::Refinement const & refinement = _refinements[level-1];
500 
501  interpolateChildVertsFromFaces(refinement, src, dst);
502  interpolateChildVertsFromEdges(refinement, src, dst);
503  interpolateChildVertsFromVerts(refinement, src, dst);
504 }
505 
506 template <class T, class U>
507 inline void
508 TopologyRefiner::interpolateChildVertsFromFaces(
509  Vtr::Refinement const & refinement, T const * src, U * dst) const {
510 
511  Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
512 
513  const Vtr::Level& parent = refinement.parent();
514 
515  float * fVertWeights = (float *)alloca(parent.getMaxValence()*sizeof(float));
516 
517  for (int face = 0; face < parent.getNumFaces(); ++face) {
518 
519  Vtr::Index cVert = refinement.getFaceChildVertex(face);
520  if (!Vtr::IndexIsValid(cVert))
521  continue;
522 
523  // Declare and compute mask weights for this vertex relative to its parent face:
524  Vtr::IndexArray const fVerts = parent.getFaceVertices(face);
525 
526  float fVaryingWeight = 1.0f / (float) fVerts.size();
527 
528  Vtr::MaskInterface fMask(fVertWeights, 0, 0);
529  Vtr::FaceInterface fHood(fVerts.size());
530 
531  scheme.ComputeFaceVertexMask(fHood, fMask);
532 
533  // Apply the weights to the parent face's vertices:
534  U & vdst = dst[cVert];
535 
536  vdst.Clear();
537 
538  for (int i = 0; i < fVerts.size(); ++i) {
539 
540  vdst.AddWithWeight(src[fVerts[i]], fVertWeights[i]);
541 
542  vdst.AddVaryingWithWeight(src[fVerts[i]], fVaryingWeight);
543  }
544  }
545 }
546 
547 template <class T, class U>
548 inline void
549 TopologyRefiner::interpolateChildVertsFromEdges(
550  Vtr::Refinement const & refinement, T const * src, U * dst) const {
551 
552  assert(_subdivType == Sdc::TYPE_CATMARK);
553  Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
554 
555  const Vtr::Level& parent = refinement.parent();
556  const Vtr::Level& child = refinement.child();
557 
558  Vtr::EdgeInterface eHood(parent);
559 
560  float eVertWeights[2],
561  * eFaceWeights = (float *)alloca(parent.getMaxEdgeFaces()*sizeof(float));
562 
563  for (int edge = 0; edge < parent.getNumEdges(); ++edge) {
564 
565  Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
566  if (!Vtr::IndexIsValid(cVert))
567  continue;
568 
569  // Declare and compute mask weights for this vertex relative to its parent edge:
570  Vtr::IndexArray const eVerts = parent.getEdgeVertices(edge);
571  Vtr::IndexArray const eFaces = parent.getEdgeFaces(edge);
572 
573  Vtr::MaskInterface eMask(eVertWeights, 0, eFaceWeights);
574 
575  eHood.SetIndex(edge);
576 
577  Sdc::Crease::Rule pRule = (parent.getEdgeSharpness(edge) > 0.0) ? Sdc::Crease::RULE_CREASE : Sdc::Crease::RULE_SMOOTH;
578  Sdc::Crease::Rule cRule = child.getVertexRule(cVert);
579 
580  scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
581 
582  // Apply the weights to the parent edges's vertices and (if applicable) to
583  // the child vertices of its incident faces:
584  U & vdst = dst[cVert];
585 
586  vdst.Clear();
587  vdst.AddWithWeight(src[eVerts[0]], eVertWeights[0]);
588  vdst.AddWithWeight(src[eVerts[1]], eVertWeights[1]);
589 
590  vdst.AddVaryingWithWeight(src[eVerts[0]], 0.5f);
591  vdst.AddVaryingWithWeight(src[eVerts[1]], 0.5f);
592 
593  if (eMask.GetNumFaceWeights() > 0) {
594 
595  for (int i = 0; i < eFaces.size(); ++i) {
596 
597  Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
598  assert(Vtr::IndexIsValid(cVertOfFace));
599  vdst.AddWithWeight(dst[cVertOfFace], eFaceWeights[i]);
600  }
601  }
602  }
603 }
604 
605 template <class T, class U>
606 inline void
607 TopologyRefiner::interpolateChildVertsFromVerts(
608  Vtr::Refinement const & refinement, T const * src, U * dst) const {
609 
610  assert(_subdivType == Sdc::TYPE_CATMARK);
611  Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
612 
613  const Vtr::Level& parent = refinement.parent();
614  const Vtr::Level& child = refinement.child();
615 
616  Vtr::VertexInterface vHood(parent, child);
617 
618  float * weightBuffer = (float *)alloca(2*parent.getMaxValence()*sizeof(float));
619 
620  for (int vert = 0; vert < parent.getNumVertices(); ++vert) {
621 
622  Vtr::Index cVert = refinement.getVertexChildVertex(vert);
623  if (!Vtr::IndexIsValid(cVert))
624  continue;
625 
626  // Declare and compute mask weights for this vertex relative to its parent edge:
627  Vtr::IndexArray const vEdges = parent.getVertexEdges(vert);
628  Vtr::IndexArray const vFaces = parent.getVertexFaces(vert);
629 
630  float vVertWeight,
631  * vEdgeWeights = weightBuffer,
632  * vFaceWeights = vEdgeWeights + vEdges.size();
633 
634  Vtr::MaskInterface vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
635 
636  vHood.SetIndex(vert, cVert);
637 
638  Sdc::Crease::Rule pRule = parent.getVertexRule(vert);
639  Sdc::Crease::Rule cRule = child.getVertexRule(cVert);
640 
641  scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
642 
643  // Apply the weights to the parent vertex, the vertices opposite its incident
644  // edges, and the child vertices of its incident faces:
645  U & vdst = dst[cVert];
646 
647  vdst.Clear();
648  vdst.AddWithWeight(src[vert], vVertWeight);
649  vdst.AddVaryingWithWeight(src[vert], 1.0f);
650 
651  if (vMask.GetNumEdgeWeights() > 0) {
652 
653  for (int i = 0; i < vEdges.size(); ++i) {
654 
655  Vtr::IndexArray const eVerts = parent.getEdgeVertices(vEdges[i]);
656  Vtr::Index pVertOppositeEdge = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
657 
658  vdst.AddWithWeight(src[pVertOppositeEdge], vEdgeWeights[i]);
659  }
660  }
661  if (vMask.GetNumFaceWeights() > 0) {
662 
663  for (int i = 0; i < vFaces.size(); ++i) {
664 
665  Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
666  assert(Vtr::IndexIsValid(cVertOfFace));
667  vdst.AddWithWeight(dst[cVertOfFace], vFaceWeights[i]);
668  }
669  }
670  }
671 }
672 
673 //
674 // Varying only interpolation
675 //
676 
677 template <class T, class U>
678 inline void
679 TopologyRefiner::InterpolateVarying(T const * src, U * dst) const {
680 
681  assert(_subdivType == Sdc::TYPE_CATMARK);
682 
683  for (int level=1; level<=GetMaxLevel(); ++level) {
684 
685  InterpolateVarying(level, src, dst);
686 
687  src = dst;
688  dst += GetNumVertices(level);
689  }
690 }
691 
692 template <class T, class U>
693 inline void
694 TopologyRefiner::InterpolateVarying(int level, T const * src, U * dst) const {
695 
696  assert(level>0 and level<=(int)_refinements.size());
697 
698  Vtr::Refinement const & refinement = _refinements[level-1];
699 
700  varyingInterpolateChildVertsFromFaces(refinement, src, dst);
701  varyingInterpolateChildVertsFromEdges(refinement, src, dst);
702  varyingInterpolateChildVertsFromVerts(refinement, src, dst);
703 }
704 
705 template <class T, class U>
706 inline void
707 TopologyRefiner::varyingInterpolateChildVertsFromFaces(
708  Vtr::Refinement const & refinement, T const * src, U * dst) const {
709 
710  const Vtr::Level& parent = refinement.parent();
711 
712  for (int face = 0; face < parent.getNumFaces(); ++face) {
713 
714  Vtr::Index cVert = refinement.getFaceChildVertex(face);
715  if (!Vtr::IndexIsValid(cVert))
716  continue;
717 
718  Vtr::IndexArray const fVerts = parent.getFaceVertices(face);
719 
720  float fVaryingWeight = 1.0f / (float) fVerts.size();
721 
722  // Apply the weights to the parent face's vertices:
723  U & vdst = dst[cVert];
724 
725  vdst.Clear();
726 
727  for (int i = 0; i < fVerts.size(); ++i) {
728  vdst.AddVaryingWithWeight(src[fVerts[i]], fVaryingWeight);
729  }
730  }
731 }
732 
733 template <class T, class U>
734 inline void
735 TopologyRefiner::varyingInterpolateChildVertsFromEdges(
736  Vtr::Refinement const & refinement, T const * src, U * dst) const {
737 
738  assert(_subdivType == Sdc::TYPE_CATMARK);
739 
740  const Vtr::Level& parent = refinement.parent();
741 
742  for (int edge = 0; edge < parent.getNumEdges(); ++edge) {
743 
744  Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
745  if (!Vtr::IndexIsValid(cVert))
746  continue;
747 
748  // Declare and compute mask weights for this vertex relative to its parent edge:
749  Vtr::IndexArray const eVerts = parent.getEdgeVertices(edge);
750 
751  // Apply the weights to the parent edges's vertices
752  U & vdst = dst[cVert];
753 
754  vdst.Clear();
755 
756  vdst.AddVaryingWithWeight(src[eVerts[0]], 0.5f);
757  vdst.AddVaryingWithWeight(src[eVerts[1]], 0.5f);
758  }
759 }
760 
761 template <class T, class U>
762 inline void
763 TopologyRefiner::varyingInterpolateChildVertsFromVerts(
764  Vtr::Refinement const & refinement, T const * src, U * dst) const {
765 
766  assert(_subdivType == Sdc::TYPE_CATMARK);
767 
768  const Vtr::Level& parent = refinement.parent();
769 
770  for (int vert = 0; vert < parent.getNumVertices(); ++vert) {
771 
772  Vtr::Index cVert = refinement.getVertexChildVertex(vert);
773  if (!Vtr::IndexIsValid(cVert))
774  continue;
775 
776  // Apply the weights to the parent vertex
777  U & vdst = dst[cVert];
778 
779  vdst.Clear();
780  vdst.AddVaryingWithWeight(src[vert], 1.0f);
781  }
782 }
783 
784 
785 //
786 // Face-varying only interpolation
787 //
788 
789 template <class T, class U>
790 inline void
791 TopologyRefiner::InterpolateFaceVarying(T const * src, U * dst, int channel) const {
792 
793  assert(_subdivType == Sdc::TYPE_CATMARK);
794 
795  for (int level=1; level<=GetMaxLevel(); ++level) {
796 
797  InterpolateFaceVarying(level, src, dst, channel);
798 
799  src = dst;
800  dst += _levels[level].getNumFVarValues();
801  }
802 }
803 
804 template <class T, class U>
805 inline void
806 TopologyRefiner::InterpolateFaceVarying(int level, T const * src, U * dst, int channel) const {
807 
808  assert(level>0 and level<=(int)_refinements.size());
809 
810  Vtr::Refinement const & refinement = _refinements[level-1];
811 
812  faceVaryingInterpolateChildVertsFromFaces(refinement, src, dst, channel);
813  faceVaryingInterpolateChildVertsFromEdges(refinement, src, dst, channel);
814  faceVaryingInterpolateChildVertsFromVerts(refinement, src, dst, channel);
815 }
816 
817 template <class T, class U>
818 inline void
819 TopologyRefiner::faceVaryingInterpolateChildVertsFromFaces(
820  Vtr::Refinement const & refinement, T const * src, U * dst, int channel) const {
821 
822  Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
823 
824  const Vtr::Level& parent = refinement.parent();
825 
826  float * fValueWeights = (float *)alloca(parent.getMaxValence()*sizeof(float));
827 
828  for (int face = 0; face < parent.getNumFaces(); ++face) {
829 
830  Vtr::Index cVert = refinement.getFaceChildVertex(face);
831  if (!Vtr::IndexIsValid(cVert))
832  continue;
833 
834  // The only difference for face-varying here is that we get the values associated
835  // with each face-vertex directly from the FVarLevel, rather than using the parent
836  // face-vertices directly. If any face-vertex has any sibling values, then we may
837  // get the wrong one using the face-vertex index directly.
838 
839  // Declare and compute mask weights for this vertex relative to its parent face:
840  Vtr::IndexArray const fValues = parent.getFVarFaceValues(face, channel);
841 
842  Vtr::MaskInterface fMask(fValueWeights, 0, 0);
843  Vtr::FaceInterface fHood(fValues.size());
844 
845  scheme.ComputeFaceVertexMask(fHood, fMask);
846 
847  // Apply the weights to the parent face's vertices:
848  U & vdst = dst[cVert];
849 
850  vdst.Clear();
851 
852  for (int i = 0; i < fValues.size(); ++i) {
853  vdst.AddWithWeight(src[fValues[i]], fValueWeights[i]);
854  }
855  }
856 }
857 
858 template <class T, class U>
859 inline void
860 TopologyRefiner::faceVaryingInterpolateChildVertsFromEdges(
861  Vtr::Refinement const & refinement, T const * src, U * dst, int channel) const {
862 
863  assert(_subdivType == Sdc::TYPE_CATMARK);
864  Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
865 
866  const Vtr::Level& parent = refinement.parent();
867  const Vtr::Level& child = refinement.child();
868 
869  const Vtr::FVarRefinement& refineFVar = *refinement._fvarChannels[channel];
870  const Vtr::FVarLevel& parentFVar = *parent._fvarChannels[channel];
871  const Vtr::FVarLevel& childFVar = *child._fvarChannels[channel];
872 
873  //
874  // Allocate and intialize (if linearly interpolated) interpolation weights for
875  // the edge mask:
876  //
877  float eVertWeights[2],
878  * eFaceWeights = (float *)alloca(parent.getMaxEdgeFaces()*sizeof(float));
879 
880  Vtr::MaskInterface eMask(eVertWeights, 0, eFaceWeights);
881 
882  bool isLinearFVar = parentFVar._isLinear;
883  if (isLinearFVar) {
884  eMask.SetNumVertexWeights(2);
885  eMask.SetNumEdgeWeights(0);
886  eMask.SetNumFaceWeights(0);
887 
888  eVertWeights[0] = 0.5f;
889  eVertWeights[1] = 0.5f;
890  }
891 
892  Vtr::EdgeInterface eHood(parent);
893 
894  for (int edge = 0; edge < parent.getNumEdges(); ++edge) {
895 
896  Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
897  if (!Vtr::IndexIsValid(cVert))
898  continue;
899 
900  bool fvarEdgeVertMatchesVertex = childFVar.vertexTopologyMatches(cVert);
901  if (fvarEdgeVertMatchesVertex) {
902  //
903  // If smoothly interpolated, compute new weights for the edge mask:
904  //
905  if (!isLinearFVar) {
906  eHood.SetIndex(edge);
907 
908  Sdc::Crease::Rule pRule = (parent.getEdgeSharpness(edge) > 0.0) ? Sdc::Crease::RULE_CREASE : Sdc::Crease::RULE_SMOOTH;
909  Sdc::Crease::Rule cRule = child.getVertexRule(cVert);
910 
911  scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
912  }
913 
914  // Apply the weights to the parent edges's vertices and (if applicable) to
915  // the child vertices of its incident faces:
916  //
917  // Even though the face-varying topology matches the vertex topology, we need
918  // to be careful here when getting values corresponding to the two end-vertices.
919  // While the edge may be continuous, the vertices at their ends may have
920  // discontinuities elsewhere in their neighborhood (i.e. on the "other side"
921  // of the end-vertex) and so have sibling values associated with them. In most
922  // cases the topology for an end-vertex will match and we can use it directly,
923  // but we must still check and retrieve as needed.
924  //
925  // Indices for values corresponding to face-vertices are guaranteed to match,
926  // so we can use the child-vertex indices directly.
927  //
928  // And by "directly", we always use getVertexValue(vertexIndex) to reference
929  // values in the "src" to account for the possible indirection that may exist at
930  // level 0 -- where there may be fewer values than vertices and an additional
931  // indirection is necessary. We can use a vertex index directly for "dst" when
932  // it matches.
933  //
934  Vtr::Index eVertValues[2];
935 
936  // WORK-IN-PROGRESS -- using this switch for comparative purposes only...
937  bool assumeMatchingNeighborhood = false;
938  if (assumeMatchingNeighborhood) {
939  Vtr::IndexArray eVerts = parent.getEdgeVertices(edge);
940  eVertValues[0] = eVerts[0];
941  eVertValues[1] = eVerts[1];
942  } else {
943  parentFVar.getEdgeFaceValues(edge, 0, eVertValues);
944  }
945 
946  U & vdst = dst[cVert];
947 
948  vdst.Clear();
949  vdst.AddWithWeight(src[eVertValues[0]], eVertWeights[0]);
950  vdst.AddWithWeight(src[eVertValues[1]], eVertWeights[1]);
951 
952  if (eMask.GetNumFaceWeights() > 0) {
953 
954  Vtr::IndexArray const eFaces = parent.getEdgeFaces(edge);
955 
956  for (int i = 0; i < eFaces.size(); ++i) {
957 
958  Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
959  assert(Vtr::IndexIsValid(cVertOfFace));
960  vdst.AddWithWeight(dst[cVertOfFace], eFaceWeights[i]);
961  }
962  }
963  } else {
964  //
965  // Mismatched edge-verts should just be linearly interpolated between the pairs of
966  // values for each sibling of the child edge-vertex -- the question is: which face
967  // holds that pair of values for a given sibling?
968  //
969  // In the manifold case, the sibling and edge-face indices will correspond. We
970  // will eventually need to update this to account for > 3 incident faces.
971  //
972  for (int i = 0; i < childFVar.getNumVertexValues(cVert); ++i) {
973  Vtr::Index eVertValues[2];
974  int eFaceIndex = refineFVar.getChildValueParentSource(cVert, i);
975  assert(eFaceIndex == i);
976 
977  parentFVar.getEdgeFaceValues(edge, eFaceIndex, eVertValues);
978 
979  U & vdst = dst[childFVar.getVertexValue(cVert, i)];
980 
981  vdst.Clear();
982  vdst.AddWithWeight(src[eVertValues[0]], 0.5);
983  vdst.AddWithWeight(src[eVertValues[1]], 0.5);
984  }
985  }
986  }
987 }
988 
989 template <class T, class U>
990 inline void
991 TopologyRefiner::faceVaryingInterpolateChildVertsFromVerts(
992  Vtr::Refinement const & refinement, T const * src, U * dst, int channel) const {
993 
994  assert(_subdivType == Sdc::TYPE_CATMARK);
995  Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
996 
997  const Vtr::Level& parent = refinement.parent();
998  const Vtr::Level& child = refinement.child();
999 
1000  const Vtr::FVarRefinement& refineFVar = *refinement._fvarChannels[channel];
1001  const Vtr::FVarLevel& parentFVar = *parent._fvarChannels[channel];
1002  const Vtr::FVarLevel& childFVar = *child._fvarChannels[channel];
1003 
1004  bool isLinearFVar = parentFVar._isLinear;
1005 
1006  float * weightBuffer = (float *)alloca(2*parent.getMaxValence()*sizeof(float));
1007 
1008  Vtr::Index * vEdgeValues = (Vtr::Index *)alloca(parent.getMaxValence()*sizeof(Vtr::Index));
1009 
1010  Vtr::VertexInterface vHood(parent, child);
1011 
1012  for (int vert = 0; vert < parent.getNumVertices(); ++vert) {
1013 
1014  Vtr::Index cVert = refinement.getVertexChildVertex(vert);
1015  if (!Vtr::IndexIsValid(cVert))
1016  continue;
1017 
1018  bool fvarVertVertMatchesVertex = childFVar.vertexTopologyMatches(cVert);
1019  if (isLinearFVar && fvarVertVertMatchesVertex) {
1020  Vtr::Index pVertValue = parentFVar.getVertexValue(vert);
1021  Vtr::Index cVertValue = cVert;
1022 
1023  U & vdst = dst[cVertValue];
1024 
1025  vdst.Clear();
1026  vdst.AddWithWeight(src[pVertValue], 1.0f);
1027  continue;
1028  }
1029 
1030  if (fvarVertVertMatchesVertex) {
1031  //
1032  // Declare and compute mask weights for this vertex relative to its parent edge:
1033  //
1034  // (We really need to encapsulate this somewhere else for use here and in the
1035  // general case)
1036  //
1037  Vtr::IndexArray const vEdges = parent.getVertexEdges(vert);
1038 
1039  float vVertWeight;
1040  float * vEdgeWeights = weightBuffer;
1041  float * vFaceWeights = vEdgeWeights + vEdges.size();
1042 
1043  Vtr::MaskInterface vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
1044 
1045  vHood.SetIndex(vert, cVert);
1046 
1047  Sdc::Crease::Rule pRule = parent.getVertexRule(vert);
1048  Sdc::Crease::Rule cRule = child.getVertexRule(cVert);
1049 
1050  scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
1051 
1052  // Apply the weights to the parent vertex, the vertices opposite its incident
1053  // edges, and the child vertices of its incident faces:
1054  //
1055  // Even though the face-varying topology matches the vertex topology, we need
1056  // to be careful here when getting values corresponding to vertices at the
1057  // ends of edges. While the edge may be continuous, the end vertex may have
1058  // discontinuities elsewhere in their neighborhood (i.e. on the "other side"
1059  // of the end-vertex) and so have sibling values associated with them. In most
1060  // cases the topology for an end-vertex will match and we can use it directly,
1061  // but we must still check and retrieve as needed.
1062  //
1063  // Indices for values corresponding to face-vertices are guaranteed to match,
1064  // so we can use the child-vertex indices directly.
1065  //
1066  // And by "directly", we always use getVertexValue(vertexIndex) to reference
1067  // values in the "src" to account for the possible indirection that may exist at
1068  // level 0 -- where there may be fewer values than vertices and an additional
1069  // indirection is necessary. We can use a vertex index directly for "dst" when
1070  // it matches.
1071  //
1072  Vtr::Index pVertValue = parentFVar.getVertexValue(vert);
1073  Vtr::Index cVertValue = cVert;
1074 
1075  U & vdst = dst[cVertValue];
1076 
1077  vdst.Clear();
1078  vdst.AddWithWeight(src[pVertValue], vVertWeight);
1079 
1080  if (vMask.GetNumEdgeWeights() > 0) {
1081 
1082  // WORK-IN-PROGRESS -- using this switch for comparative purposes only...
1083  bool assumeMatchingNeighborhood = false;
1084  if (assumeMatchingNeighborhood) {
1085  for (int i = 0; i < vEdges.size(); ++i) {
1086  Vtr::IndexArray const eVerts = parent.getEdgeVertices(vEdges[i]);
1087  Vtr::Index pVertOppositeEdge = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
1088 
1089  vdst.AddWithWeight(src[pVertOppositeEdge], vEdgeWeights[i]);
1090  }
1091  } else {
1092  parentFVar.getVertexEdgeValues(vert, vEdgeValues);
1093 
1094  for (int i = 0; i < vEdges.size(); ++i) {
1095  vdst.AddWithWeight(src[vEdgeValues[i]], vEdgeWeights[i]);
1096  }
1097  }
1098 
1099  }
1100  if (vMask.GetNumFaceWeights() > 0) {
1101 
1102  Vtr::IndexArray const vFaces = parent.getVertexFaces(vert);
1103 
1104  for (int i = 0; i < vFaces.size(); ++i) {
1105 
1106  Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
1107  assert(Vtr::IndexIsValid(cVertOfFace));
1108  vdst.AddWithWeight(dst[cVertOfFace], vFaceWeights[i]);
1109  }
1110  }
1111  } else {
1112  //
1113  // Mismatched vert-verts may be either on corners or creases -- for now we
1114  // are presuming the hard-corner case (and so need to revisit this...)
1115  //
1116  for (int cSibling = 0; cSibling < childFVar.getNumVertexValues(cVert); ++cSibling) {
1117  int pSibling = refineFVar.getChildValueParentSource(cVert, cSibling);
1118  assert(pSibling == cSibling);
1119 
1120  Vtr::Index pVertValue = parentFVar.getVertexValue(vert, pSibling);
1121  Vtr::Index cVertValue = childFVar.getVertexValue(cVert, cSibling);
1122 
1123  U & vdst = dst[cVertValue];
1124 
1125  vdst.Clear();
1126  vdst.AddWithWeight(src[pVertValue], 1.0);
1127  }
1128  }
1129  }
1130 }
1131 
1132 } // end namespace Far
1133 
1134 } // end namespace OPENSUBDIV_VERSION
1135 using namespace OPENSUBDIV_VERSION;
1136 } // end namespace OpenSubdiv
1137 
1138 #endif /* FAR_TOPOLOGY_REFINER_H */
1139 
int GetNumFaceVerticesTotal() const
Returns the total number of face vertices in all levels.
IndexArray const GetFaceChildFaces(int level, Index f) const
Returns the child faces of face &#39;f&#39; at &#39;level&#39;.
int GetPtexIndex(Index f) const
Returns the ptex face index given a coarse face &#39;f&#39; or -1.
IndexArray const GetFaceEdges(int level, Index face) const
Returns the edges of a &#39;face&#39; at &#39;level&#39;.
std::vector< FVarLevel * > _fvarChannels
Definition: level.h:414
int GetNumFaces(int level) const
Returns the number of face vertex indices at a given level of refinement.
LocalIndexArray const VertexEdgeLocalIndices(int level, Index vert) const
Returns the local edge indices of vertex &#39;vert&#39; at &#39;level&#39;.
int GetNumFVarChannels() const
Returns the number of face-varying channels in the tables.
void PrintTopology(int level, bool children=true) const
Prints topology information to console.
void Unrefine()
Unrefine the topology (keep control cage)
float GetEdgeSharpness(int level, Index edge) const
Returns the sharpness of a given edge (at &#39;level&#39; of refinement)
int GetNumVertices(int level) const
Returns the number of vertices at a given level of refinement.
float GetVertexSharpness(int level, Index vert) const
Returns the sharpness of a given vertex (at &#39;level&#39; of refinement)
Sdc::Type GetSchemeType() const
Returns the subdivision scheme.
int GetNumFVarValues(int level, int channel=0) const
Returns the number of face-varying values at a given level of refinement.
int GetNumFaceVertices(int level) const
Returns the number of faces at a given level of refinement.
bool ValidateTopology(int level) const
Returns true if the topology of &#39;level&#39; is valid.
IndexArray getBaseFVarFaceValues(Index face, int channel=0)
int GetNumEdges(int level) const
Returns the number of edges at a given level of refinement.
int GetNumFacesTotal() const
Returns the total number of edges in all levels.
void InterpolateFaceVarying(T const *src, U *dst, int channel=0) const
Apply face-varying interpolation weights to a primvar buffer.
IndexArray const GetEdgeFaces(int level, Index edge) const
Returns the faces incident to &#39;edge&#39; at &#39;level&#39;.
Sdc::Options GetSchemeOptions() const
Returns the subdivision options.
int GetNumFVarValuesTotal(int channel=0) const
Returns the total number of face-varying values in all levels.
LocalIndexArray const VertexFaceLocalIndices(int level, Index vert) const
Returns the local face indices of vertex &#39;vert&#39; at &#39;level&#39;.
IndexArray const GetFaceVertices(int level, Index face) const
Returns the vertices of a &#39;face&#39; at &#39;level&#39;.
TopologyRefiner(Sdc::Type type, Sdc::Options options=Sdc::Options())
Constructor.
IndexArray const GetFaceChildEdges(int level, Index f) const
Returns the child edges of face &#39;f&#39; at &#39;level&#39;.
IndexArray const GetVertexFaces(int level, Index vert) const
Returns the faces incident to &#39;vertex&#39; at &#39;level&#39;.
IndexArray const GetVertexEdges(int level, Index vert) const
Returns the edges incident to &#39;vertex&#39; at &#39;level&#39;.
Sdc::Crease::Rule GetVertexRule(int level, Index vert) const
Returns the subdivision rule of a given vertex (at &#39;level&#39; of refinement)
int GetNumVerticesTotal() const
Returns the total number of vertices in all levels.
IndexArray const GetEdgeChildEdges(int level, Index e) const
Returns the child edges of edge &#39;e&#39; at &#39;level&#39;.
IndexArray const getFaceVertices(Index faceIndex) const
Definition: level.h:421
IndexArray const GetEdgeVertices(int level, Index edge) const
Returns the vertices of an &#39;edge&#39; at &#39;level&#39; (2 of them)
int GetNumPtexFaces() const
Returns the number of ptex faces in the mesh.
void InterpolateVarying(T const *src, U *dst) const
Apply only varying interpolation weights to a primvar buffer.
void Interpolate(T const *src, U *dst) const
Apply vertex and varying interpolation weights to a primvar buffer.
void RefineAdaptive(int maxLevel, bool fullTopologyInLastLevel=false)
Feature Adaptive topology refinement.
Index GetFaceChildVertex(int level, Index f) const
Returns the child vertex of face &#39;f&#39; at &#39;level&#39;.
int createFVarChannel(int numValues, Sdc::Options const &options)
int GetMaxLevel() const
Returns the highest level of refinement.
bool IndexIsValid(Index index)
Definition: types.h:63
IndexArray const GetFVarFaceValues(int level, Index face, int channel=0) const
Returns the face-varying values of a &#39;face&#39; at &#39;level&#39;.
IndexArray const getFVarFaceValues(Index faceIndex, int channel=0) const
bool IsUniform() const
Returns true if uniform subdivision has been applied.
Stores topology data for a specified set of refinement options.
Index GetVertexChildVertex(int level, Index v) const
Returns the child vertex of vertex &#39;v&#39; at &#39;level&#39;.
void RefineUniform(int maxLevel, bool fullTopologyInLastLevel=false)
Refine the topology uniformly.
Vtr::Refinement const & getRefinement(int l) const
A specialized factory for feature adaptive PatchTables.
int GetNumEdgesTotal() const
Returns the total number of edges in all levels.
Index GetEdgeChildVertex(int level, Index e) const
Returns the child vertex of edge &#39;e&#39; at &#39;level&#39;.
void Clear()
Clear the topology entirely.
Index FindEdge(int level, Index v0, Index v1) const
Returns the edge with vertices&#39;v0&#39; and &#39;v1&#39; (or -1 if they are not connected)