24 #ifndef OPENSUBDIV3_FAR_PRIMVAR_REFINER_H
25 #define OPENSUBDIV3_FAR_PRIMVAR_REFINER_H
27 #include "../version.h"
29 #include "../sdc/types.h"
30 #include "../sdc/options.h"
31 #include "../sdc/bilinearScheme.h"
32 #include "../sdc/catmarkScheme.h"
33 #include "../sdc/loopScheme.h"
34 #include "../vtr/level.h"
35 #include "../vtr/fvarLevel.h"
36 #include "../vtr/refinement.h"
37 #include "../vtr/fvarRefinement.h"
38 #include "../vtr/stackBuffer.h"
39 #include "../vtr/componentInterfaces.h"
40 #include "../far/types.h"
41 #include "../far/error.h"
42 #include "../far/topologyLevel.h"
43 #include "../far/topologyRefiner.h"
47 namespace OpenSubdiv {
48 namespace OPENSUBDIV_VERSION {
55 template <
typename REAL>
113 template <
class T,
class U>
void Interpolate(
int level, T
const & src, U & dst)
const;
130 template <
class T,
class U>
void InterpolateVarying(
int level, T
const & src, U & dst)
const;
161 template <
class T,
class U>
void InterpolateFaceVarying(
int level, T
const & src, U & dst,
int channel = 0)
const;
175 template <
class T,
class U>
void Limit(T
const & src, U & dstPos)
const;
177 template <
class T,
class U,
class U1,
class U2>
178 void Limit(T
const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2)
const;
180 template <
class T,
class U>
void LimitFaceVarying(T
const & src, U & dst,
int channel = 0)
const;
191 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFromFaces(
int, T
const &, U &)
const;
192 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFromEdges(
int, T
const &, U &)
const;
193 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFromVerts(
int, T
const &, U &)
const;
195 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFVarFromFaces(
int, T
const &, U &,
int)
const;
196 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFVarFromEdges(
int, T
const &, U &,
int)
const;
197 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFVarFromVerts(
int, T
const &, U &,
int)
const;
199 template <Sdc::SchemeType SCHEME,
class T,
class U,
class U1,
class U2>
200 void limit(T
const & src, U & pos, U1 * tan1, U2 * tan2)
const;
202 template <Sdc::SchemeType SCHEME,
class T,
class U>
203 void limitFVar(T
const & src, U & dst,
int channel)
const;
206 TopologyRefiner
const & _refiner;
217 Mask(Weight* v, Weight* e, Weight* f) :
218 _vertWeights(v), _edgeWeights(e), _faceWeights(f),
219 _vertCount(0), _edgeCount(0), _faceCount(0),
220 _faceWeightsForFaceCenters(false)
226 int GetNumVertexWeights()
const {
return _vertCount; }
227 int GetNumEdgeWeights()
const {
return _edgeCount; }
228 int GetNumFaceWeights()
const {
return _faceCount; }
230 void SetNumVertexWeights(
int count) { _vertCount = count; }
231 void SetNumEdgeWeights(
int count) { _edgeCount = count; }
232 void SetNumFaceWeights(
int count) { _faceCount = count; }
234 Weight
const& VertexWeight(
int index)
const {
return _vertWeights[index]; }
235 Weight
const& EdgeWeight(
int index)
const {
return _edgeWeights[index]; }
236 Weight
const& FaceWeight(
int index)
const {
return _faceWeights[index]; }
238 Weight& VertexWeight(
int index) {
return _vertWeights[index]; }
239 Weight& EdgeWeight(
int index) {
return _edgeWeights[index]; }
240 Weight& FaceWeight(
int index) {
return _faceWeights[index]; }
242 bool AreFaceWeightsForFaceCenters()
const {
return _faceWeightsForFaceCenters; }
243 void SetFaceWeightsForFaceCenters(
bool on) { _faceWeightsForFaceCenters = on; }
246 Weight* _vertWeights;
247 Weight* _edgeWeights;
248 Weight* _faceWeights;
254 bool _faceWeightsForFaceCenters;
264 template <
typename REAL>
265 template <
class T,
class U>
269 assert(level>0 && level<=(
int)_refiner._refinements.size());
271 switch (_refiner._subdivType) {
273 interpFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst);
274 interpFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst);
275 interpFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst);
278 interpFromFaces<Sdc::SCHEME_LOOP>(level, src, dst);
279 interpFromEdges<Sdc::SCHEME_LOOP>(level, src, dst);
280 interpFromVerts<Sdc::SCHEME_LOOP>(level, src, dst);
283 interpFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst);
284 interpFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst);
285 interpFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst);
290 template <
typename REAL>
291 template <
class T,
class U>
295 assert(level>0 && level<=(
int)_refiner._refinements.size());
297 switch (_refiner._subdivType) {
299 interpFVarFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
300 interpFVarFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
301 interpFVarFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
304 interpFVarFromFaces<Sdc::SCHEME_LOOP>(level, src, dst, channel);
305 interpFVarFromEdges<Sdc::SCHEME_LOOP>(level, src, dst, channel);
306 interpFVarFromVerts<Sdc::SCHEME_LOOP>(level, src, dst, channel);
309 interpFVarFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
310 interpFVarFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
311 interpFVarFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
316 template <
typename REAL>
317 template <
class T,
class U>
321 if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
323 "Failure in PrimvarRefiner::Limit() -- "
324 "last level of refinement does not include full topology.");
328 switch (_refiner._subdivType) {
330 limit<Sdc::SCHEME_CATMARK>(src, dst, (U*)0, (U*)0);
333 limit<Sdc::SCHEME_LOOP>(src, dst, (U*)0, (U*)0);
336 limit<Sdc::SCHEME_BILINEAR>(src, dst, (U*)0, (U*)0);
341 template <
typename REAL>
342 template <
class T,
class U,
class U1,
class U2>
346 if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
348 "Failure in PrimvarRefiner::Limit() -- "
349 "last level of refinement does not include full topology.");
353 switch (_refiner._subdivType) {
355 limit<Sdc::SCHEME_CATMARK>(src, dstPos, &dstTan1, &dstTan2);
358 limit<Sdc::SCHEME_LOOP>(src, dstPos, &dstTan1, &dstTan2);
361 limit<Sdc::SCHEME_BILINEAR>(src, dstPos, &dstTan1, &dstTan2);
366 template <
typename REAL>
367 template <
class T,
class U>
371 if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
373 "Failure in PrimvarRefiner::LimitFaceVarying() -- "
374 "last level of refinement does not include full topology.");
378 switch (_refiner._subdivType) {
380 limitFVar<Sdc::SCHEME_CATMARK>(src, dst, channel);
383 limitFVar<Sdc::SCHEME_LOOP>(src, dst, channel);
386 limitFVar<Sdc::SCHEME_BILINEAR>(src, dst, channel);
391 template <
typename REAL>
392 template <
class T,
class U>
396 assert(level>0 && level<=(
int)_refiner._refinements.size());
401 for (
int cFace = 0; cFace < child.
getNumFaces(); ++cFace) {
403 Vtr::Index pFace = refinement.getChildFaceParentFace(cFace);
405 dst[cFace] = src[pFace];
409 template <
typename REAL>
410 template <
class T,
class U>
414 assert(level>0 && level<=(
int)_refiner._refinements.size());
423 if (refinement.getNumChildVerticesFromFaces() > 0) {
425 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
427 Vtr::Index cVert = refinement.getFaceChildVertex(face);
433 Weight fVaryingWeight = 1.0f / (Weight) fVerts.
size();
436 for (
int i = 0; i < fVerts.
size(); ++i) {
437 dst[cVert].AddWithWeight(src[fVerts[i]], fVaryingWeight);
442 for (
int edge = 0; edge < parent.
getNumEdges(); ++edge) {
444 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
451 dst[cVert].AddWithWeight(src[eVerts[0]], 0.5f);
452 dst[cVert].AddWithWeight(src[eVerts[1]], 0.5f);
457 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
462 dst[cVert].AddWithWeight(src[vert], 1.0f);
472 template <
typename REAL>
473 template <Sdc::SchemeType SCHEME,
class T,
class U>
486 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
495 Mask fMask(fVertWeights, 0, 0);
498 scheme.ComputeFaceVertexMask(fHood, fMask);
503 for (
int i = 0; i < fVerts.
size(); ++i) {
505 dst[cVert].AddWithWeight(src[fVerts[i]], fVertWeights[i]);
510 template <
typename REAL>
511 template <Sdc::SchemeType SCHEME,
class T,
class U>
513 PrimvarRefinerReal<REAL>::interpFromEdges(
int level, T
const & src, U & dst)
const {
515 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
516 Vtr::internal::Level
const & parent = refinement.parent();
517 Vtr::internal::Level
const & child = refinement.child();
519 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
521 Vtr::internal::EdgeInterface eHood(parent);
523 Weight eVertWeights[2];
524 Vtr::internal::StackBuffer<Weight,8> eFaceWeights(parent.getMaxEdgeFaces());
526 for (
int edge = 0; edge < parent.getNumEdges(); ++edge) {
528 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
534 eFaces = parent.getEdgeFaces(edge);
536 Mask eMask(eVertWeights, 0, eFaceWeights);
538 eHood.SetIndex(edge);
543 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
548 dst[cVert].AddWithWeight(src[eVerts[0]], eVertWeights[0]);
549 dst[cVert].AddWithWeight(src[eVerts[1]], eVertWeights[1]);
551 if (eMask.GetNumFaceWeights() > 0) {
553 for (
int i = 0; i < eFaces.size(); ++i) {
555 if (eMask.AreFaceWeightsForFaceCenters()) {
556 assert(refinement.getNumChildVerticesFromFaces() > 0);
557 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
560 dst[cVert].AddWithWeight(dst[cVertOfFace], eFaceWeights[i]);
564 pFaceVerts = parent.getFaceVertices(pFace);
567 for ( ; pFaceEdges[eInFace] != edge; ++eInFace ) ;
569 int vInFace = eInFace + 2;
570 if (vInFace >= pFaceVerts.size()) vInFace -= pFaceVerts.
size();
573 dst[cVert].AddWithWeight(src[pVertNext], eFaceWeights[i]);
580 template <
typename REAL>
581 template <Sdc::SchemeType SCHEME,
class T,
class U>
583 PrimvarRefinerReal<REAL>::interpFromVerts(
int level, T
const & src, U & dst)
const {
585 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
586 Vtr::internal::Level
const & parent = refinement.parent();
587 Vtr::internal::Level
const & child = refinement.child();
589 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
591 Vtr::internal::VertexInterface vHood(parent, child);
593 Vtr::internal::StackBuffer<Weight,32> weightBuffer(2*parent.getMaxValence());
595 for (
int vert = 0; vert < parent.getNumVertices(); ++vert) {
597 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
603 vFaces = parent.getVertexFaces(vert);
606 * vEdgeWeights = weightBuffer,
607 * vFaceWeights = vEdgeWeights + vEdges.
size();
609 Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
611 vHood.SetIndex(vert, cVert);
616 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
626 if (vMask.GetNumFaceWeights() > 0) {
627 assert(vMask.AreFaceWeightsForFaceCenters());
629 for (
int i = 0; i < vFaces.size(); ++i) {
631 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
633 dst[cVert].AddWithWeight(dst[cVertOfFace], vFaceWeights[i]);
636 if (vMask.GetNumEdgeWeights() > 0) {
638 for (
int i = 0; i < vEdges.size(); ++i) {
641 Vtr::Index pVertOppositeEdge = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
643 dst[cVert].AddWithWeight(src[pVertOppositeEdge], vEdgeWeights[i]);
646 dst[cVert].AddWithWeight(src[vert], vVertWeight);
654 template <
typename REAL>
655 template <Sdc::SchemeType SCHEME,
class T,
class U>
657 PrimvarRefinerReal<REAL>::interpFVarFromFaces(
int level, T
const & src, U & dst,
int channel)
const {
659 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
661 if (refinement.getNumChildVerticesFromFaces() == 0)
return;
663 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
665 Vtr::internal::Level
const & parentLevel = refinement.parent();
666 Vtr::internal::Level
const & childLevel = refinement.child();
668 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
669 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
671 Vtr::internal::StackBuffer<Weight,16> fValueWeights(parentLevel.getMaxValence());
673 for (
int face = 0; face < parentLevel.getNumFaces(); ++face) {
675 Vtr::Index cVert = refinement.getFaceChildVertex(face);
679 Vtr::Index cVertValue = childFVar.getVertexValueOffset(cVert);
689 Mask fMask(fValueWeights, 0, 0);
690 Vtr::internal::FaceInterface fHood(fValues.size());
692 scheme.ComputeFaceVertexMask(fHood, fMask);
695 dst[cVertValue].Clear();
697 for (
int i = 0; i < fValues.size(); ++i) {
698 dst[cVertValue].AddWithWeight(src[fValues[i]], fValueWeights[i]);
703 template <
typename REAL>
704 template <Sdc::SchemeType SCHEME,
class T,
class U>
706 PrimvarRefinerReal<REAL>::interpFVarFromEdges(
int level, T
const & src, U & dst,
int channel)
const {
708 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
710 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
712 Vtr::internal::Level
const & parentLevel = refinement.parent();
713 Vtr::internal::Level
const & childLevel = refinement.child();
715 Vtr::internal::FVarRefinement
const & refineFVar = refinement.getFVarRefinement(channel);
716 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
717 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
723 Weight eVertWeights[2];
724 Vtr::internal::StackBuffer<Weight,8> eFaceWeights(parentLevel.getMaxEdgeFaces());
726 Mask eMask(eVertWeights, 0, eFaceWeights);
730 eMask.SetNumVertexWeights(2);
731 eMask.SetNumEdgeWeights(0);
732 eMask.SetNumFaceWeights(0);
734 eVertWeights[0] = 0.5f;
735 eVertWeights[1] = 0.5f;
738 Vtr::internal::EdgeInterface eHood(parentLevel);
740 for (
int edge = 0; edge < parentLevel.getNumEdges(); ++edge) {
742 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
748 bool fvarEdgeVertMatchesVertex = childFVar.valueTopologyMatches(cVertValues[0]);
749 if (fvarEdgeVertMatchesVertex) {
754 eHood.SetIndex(edge);
760 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
785 parentFVar.getEdgeFaceValues(edge, 0, eVertValues);
787 Index cVertValue = cVertValues[0];
789 dst[cVertValue].Clear();
790 dst[cVertValue].AddWithWeight(src[eVertValues[0]], eVertWeights[0]);
791 dst[cVertValue].AddWithWeight(src[eVertValues[1]], eVertWeights[1]);
793 if (eMask.GetNumFaceWeights() > 0) {
797 for (
int i = 0; i < eFaces.size(); ++i) {
798 if (eMask.AreFaceWeightsForFaceCenters()) {
800 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
803 Vtr::Index cValueOfFace = childFVar.getVertexValueOffset(cVertOfFace);
804 dst[cVertValue].AddWithWeight(dst[cValueOfFace], eFaceWeights[i]);
808 pFaceVerts = parentLevel.getFaceVertices(pFace);
811 for ( ; pFaceEdges[eInFace] != edge; ++eInFace ) ;
814 int vInFace = eInFace + 2;
815 if (vInFace >= pFaceVerts.size()) vInFace -= pFaceVerts.
size();
817 Vtr::Index pValueNext = parentFVar.getFaceValues(pFace)[vInFace];
818 dst[cVertValue].AddWithWeight(src[pValueNext], eFaceWeights[i]);
831 for (
int i = 0; i < cVertValues.size(); ++i) {
833 int eFaceIndex = refineFVar.getChildValueParentSource(cVert, i);
834 assert(eFaceIndex == i);
836 parentFVar.getEdgeFaceValues(edge, eFaceIndex, eVertValues);
838 Index cVertValue = cVertValues[i];
840 dst[cVertValue].Clear();
841 dst[cVertValue].AddWithWeight(src[eVertValues[0]], 0.5);
842 dst[cVertValue].AddWithWeight(src[eVertValues[1]], 0.5);
848 template <
typename REAL>
849 template <Sdc::SchemeType SCHEME,
class T,
class U>
851 PrimvarRefinerReal<REAL>::interpFVarFromVerts(
int level, T
const & src, U & dst,
int channel)
const {
853 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
855 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
857 Vtr::internal::Level
const & parentLevel = refinement.parent();
858 Vtr::internal::Level
const & childLevel = refinement.child();
860 Vtr::internal::FVarRefinement
const & refineFVar = refinement.getFVarRefinement(channel);
861 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
862 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
866 Vtr::internal::StackBuffer<Weight,32> weightBuffer(2*parentLevel.getMaxValence());
868 Vtr::internal::StackBuffer<Vtr::Index,16> vEdgeValues(parentLevel.getMaxValence());
870 Vtr::internal::VertexInterface vHood(parentLevel, childLevel);
872 for (
int vert = 0; vert < parentLevel.getNumVertices(); ++vert) {
874 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
879 cVertValues = childFVar.getVertexValues(cVert);
881 bool fvarVertVertMatchesVertex = childFVar.valueTopologyMatches(cVertValues[0]);
882 if (isLinearFVar && fvarVertVertMatchesVertex) {
883 dst[cVertValues[0]].Clear();
884 dst[cVertValues[0]].AddWithWeight(src[pVertValues[0]], 1.0f);
888 if (fvarVertVertMatchesVertex) {
898 Weight * vEdgeWeights = weightBuffer;
899 Weight * vFaceWeights = vEdgeWeights + vEdges.
size();
901 Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
903 vHood.SetIndex(vert, cVert);
908 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
937 dst[cVertValue].Clear();
938 if (vMask.GetNumFaceWeights() > 0) {
939 assert(vMask.AreFaceWeightsForFaceCenters());
943 for (
int i = 0; i < vFaces.size(); ++i) {
945 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
948 Vtr::Index cValueOfFace = childFVar.getVertexValueOffset(cVertOfFace);
949 dst[cVertValue].AddWithWeight(dst[cValueOfFace], vFaceWeights[i]);
952 if (vMask.GetNumEdgeWeights() > 0) {
954 parentFVar.getVertexEdgeValues(vert, vEdgeValues);
956 for (
int i = 0; i < vEdges.size(); ++i) {
957 dst[cVertValue].AddWithWeight(src[vEdgeValues[i]], vEdgeWeights[i]);
960 dst[cVertValue].AddWithWeight(src[pVertValue], vVertWeight);
972 for (
int cSibling = 0; cSibling < cVertValues.size(); ++cSibling) {
973 int pSibling = refineFVar.getChildValueParentSource(cVert, cSibling);
974 assert(pSibling == cSibling);
976 Vtr::Index pVertValue = pVertValues[pSibling];
977 Vtr::Index cVertValue = cVertValues[cSibling];
979 dst[cVertValue].Clear();
980 if (isLinearFVar || cValueTags[cSibling].isCorner()) {
981 dst[cVertValue].AddWithWeight(src[pVertValue], 1.0f);
988 parentFVar.getVertexCreaseEndValues(vert, pSibling, pEndValues);
990 Weight vWeight = 0.75f;
991 Weight eWeight = 0.125f;
998 if (pValueTags[pSibling].isSemiSharp()) {
999 Weight wCorner = pValueTags[pSibling].isDepSharp()
1000 ? refineFVar.getFractionalWeight(vert, !pSibling, cVert, !cSibling)
1001 : refineFVar.getFractionalWeight(vert, pSibling, cVert, cSibling);
1002 Weight wCrease = 1.0f - wCorner;
1004 vWeight = wCrease * 0.75f + wCorner;
1005 eWeight = wCrease * 0.125f;
1007 dst[cVertValue].AddWithWeight(src[pEndValues[0]], eWeight);
1008 dst[cVertValue].AddWithWeight(src[pEndValues[1]], eWeight);
1009 dst[cVertValue].AddWithWeight(src[pVertValue], vWeight);
1016 template <
typename REAL>
1017 template <Sdc::SchemeType SCHEME,
class T,
class U,
class U1,
class U2>
1019 PrimvarRefinerReal<REAL>::limit(T
const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr)
const {
1021 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1023 Vtr::internal::Level
const & level = _refiner.getLevel(_refiner.GetMaxLevel());
1025 int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
1026 bool hasTangents = (dstTan1Ptr && dstTan2Ptr);
1027 int numMasks = 1 + (hasTangents ? 2 : 0);
1029 Vtr::internal::StackBuffer<Index,33> indexBuffer(maxWeightsPerMask);
1030 Vtr::internal::StackBuffer<Weight,99> weightBuffer(numMasks * maxWeightsPerMask);
1032 Weight * vPosWeights = weightBuffer,
1033 * ePosWeights = vPosWeights + 1,
1034 * fPosWeights = ePosWeights + level.getMaxValence();
1035 Weight * vTan1Weights = vPosWeights + maxWeightsPerMask,
1036 * eTan1Weights = ePosWeights + maxWeightsPerMask,
1037 * fTan1Weights = fPosWeights + maxWeightsPerMask;
1038 Weight * vTan2Weights = vTan1Weights + maxWeightsPerMask,
1039 * eTan2Weights = eTan1Weights + maxWeightsPerMask,
1040 * fTan2Weights = fTan1Weights + maxWeightsPerMask;
1042 Mask posMask( vPosWeights, ePosWeights, fPosWeights);
1043 Mask tan1Mask(vTan1Weights, eTan1Weights, fTan1Weights);
1044 Mask tan2Mask(vTan2Weights, eTan2Weights, fTan2Weights);
1048 Vtr::internal::VertexInterface vHood(level, level);
1050 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1056 if (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0)) {
1057 dstPos[vert].Clear();
1058 dstPos[vert].AddWithWeight(src[vert], 1.0);
1060 (*dstTan1Ptr)[vert].Clear();
1061 (*dstTan2Ptr)[vert].Clear();
1074 vHood.SetIndex(vert, vert);
1077 scheme.ComputeVertexLimitMask(vHood, posMask, tan1Mask, tan2Mask, vRule);
1079 scheme.ComputeVertexLimitMask(vHood, posMask, vRule);
1086 Index * eIndices = indexBuffer;
1087 Index * fIndices = indexBuffer + vEdges.size();
1089 for (
int i = 0; i < vEdges.size(); ++i) {
1092 eIndices[i] = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
1094 if (posMask.GetNumFaceWeights() || (hasTangents && tan1Mask.GetNumFaceWeights())) {
1098 for (
int i = 0; i < vFaces.size(); ++i) {
1102 if (vOppInFace >= fVerts.size()) vOppInFace -= (
LocalIndex)fVerts.size();
1104 fIndices[i] = level.getFaceVertices(vFaces[i])[vOppInFace];
1114 dstPos[vert].Clear();
1115 for (
int i = 0; i < posMask.GetNumFaceWeights(); ++i) {
1116 dstPos[vert].AddWithWeight(src[fIndices[i]], fPosWeights[i]);
1118 for (
int i = 0; i < posMask.GetNumEdgeWeights(); ++i) {
1119 dstPos[vert].AddWithWeight(src[eIndices[i]], ePosWeights[i]);
1121 dstPos[vert].AddWithWeight(src[vert], vPosWeights[0]);
1129 assert(tan1Mask.GetNumFaceWeights() == tan2Mask.GetNumFaceWeights());
1130 assert(tan1Mask.GetNumEdgeWeights() == tan2Mask.GetNumEdgeWeights());
1132 U1 & dstTan1 = *dstTan1Ptr;
1133 U2 & dstTan2 = *dstTan2Ptr;
1135 dstTan1[vert].Clear();
1136 dstTan2[vert].Clear();
1137 for (
int i = 0; i < tan1Mask.GetNumFaceWeights(); ++i) {
1138 dstTan1[vert].AddWithWeight(src[fIndices[i]], fTan1Weights[i]);
1139 dstTan2[vert].AddWithWeight(src[fIndices[i]], fTan2Weights[i]);
1141 for (
int i = 0; i < tan1Mask.GetNumEdgeWeights(); ++i) {
1142 dstTan1[vert].AddWithWeight(src[eIndices[i]], eTan1Weights[i]);
1143 dstTan2[vert].AddWithWeight(src[eIndices[i]], eTan2Weights[i]);
1145 dstTan1[vert].AddWithWeight(src[vert], vTan1Weights[0]);
1146 dstTan2[vert].AddWithWeight(src[vert], vTan2Weights[0]);
1151 template <
typename REAL>
1152 template <Sdc::SchemeType SCHEME,
class T,
class U>
1154 PrimvarRefinerReal<REAL>::limitFVar(T
const & src, U & dst,
int channel)
const {
1156 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1158 Vtr::internal::Level
const & level = _refiner.getLevel(_refiner.GetMaxLevel());
1159 Vtr::internal::FVarLevel
const & fvarChannel = level.getFVarLevel(channel);
1161 int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
1163 Vtr::internal::StackBuffer<Weight,33> weightBuffer(maxWeightsPerMask);
1164 Vtr::internal::StackBuffer<Index,16> vEdgeBuffer(level.getMaxValence());
1167 Vtr::internal::VertexInterface vHood(level, level);
1169 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1180 bool isIncomplete = (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0));
1181 if (isIncomplete || fvarChannel.isLinear()) {
1182 for (
int i = 0; i < vValues.size(); ++i) {
1185 dst[vValue].Clear();
1186 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1191 bool fvarVertMatchesVertex = fvarChannel.valueTopologyMatches(vValues[0]);
1192 if (fvarVertMatchesVertex) {
1196 Weight * vWeights = weightBuffer,
1197 * eWeights = vWeights + 1,
1198 * fWeights = eWeights + vEdges.size();
1200 Mask vMask(vWeights, eWeights, fWeights);
1202 vHood.SetIndex(vert, vert);
1204 scheme.ComputeVertexLimitMask(vHood, vMask, level.getVertexRule(vert));
1211 dst[vValue].Clear();
1212 if (vMask.GetNumFaceWeights() > 0) {
1213 assert(!vMask.AreFaceWeightsForFaceCenters());
1218 for (
int i = 0; i < vFaces.size(); ++i) {
1221 if (vOppInFace >= faceValues.size()) vOppInFace -= faceValues.size();
1223 Index vValueOppositeFace = faceValues[vOppInFace];
1225 dst[vValue].AddWithWeight(src[vValueOppositeFace], fWeights[i]);
1228 if (vMask.GetNumEdgeWeights() > 0) {
1229 Index * vEdgeValues = vEdgeBuffer;
1230 fvarChannel.getVertexEdgeValues(vert, vEdgeValues);
1232 for (
int i = 0; i < vEdges.size(); ++i) {
1233 dst[vValue].AddWithWeight(src[vEdgeValues[i]], eWeights[i]);
1236 dst[vValue].AddWithWeight(src[vValue], vWeights[0]);
1241 for (
int i = 0; i < vValues.size(); ++i) {
1244 dst[vValue].Clear();
1245 if (fvarChannel.getValueTag(vValue).isCorner()) {
1246 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1248 Index vEndValues[2];
1249 fvarChannel.getVertexCreaseEndValues(vert, i, vEndValues);
1251 dst[vValue].AddWithWeight(src[vEndValues[0]], 1.0f/6.0f);
1252 dst[vValue].AddWithWeight(src[vEndValues[1]], 1.0f/6.0f);
1253 dst[vValue].AddWithWeight(src[vValue], 2.0f/3.0f);
1269 using namespace OPENSUBDIV_VERSION;
TopologyRefiner const & GetTopologyRefiner() const
int getNumVertices() const
void LimitFaceVarying(T const &src, U &dst, int channel=0) const
Vtr::LocalIndex LocalIndex
void InterpolateVarying(int level, T const &src, U &dst) const
Apply only varying interpolation weights to a primvar buffer for a single level of refinement...
bool IndexIsValid(Index index)
Index getFaceChildVertex(Index f) const
Issue a generic runtime error, but continue execution.
PrimvarRefinerReal(TopologyRefiner const &refiner)
void Interpolate(int level, T const &src, U &dst) const
Apply vertex interpolation weights to a primvar buffer for a single level of refinement.
Stores topology data for a specified set of refinement options.
void Limit(T const &src, U &dstPos) const
Apply limit weights to a primvar buffer.
int getNumChildVerticesFromFaces() const
Vtr::ConstLocalIndexArray ConstLocalIndexArray
Applies refinement operations to generic primvar data.
ConstIndexArray getFaceVertices(Index faceIndex) const
void Error(ErrorType err, const char *format,...)
Sends an OSD error with a message (internal use only)
Vtr::ConstIndexArray ConstIndexArray
Level const & parent() const
void InterpolateFaceVarying(int level, T const &src, U &dst, int channel=0) const
Apply face-varying interpolation weights to a primvar buffer associated with a particular face-varyin...
void InterpolateFaceUniform(int level, T const &src, U &dst) const
Refine uniform (per-face) primvar data between levels.
Vtr::ConstArray< ValueTag > ConstValueTagArray
PrimvarRefiner(TopologyRefiner const &refiner)
Scheme is a class template which provides all implementation for the subdivision schemes supported by...
int getMaxValence() const
ConstIndexArray getEdgeVertices(Index edgeIndex) const