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"
48 namespace OPENSUBDIV_VERSION {
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;
190 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFromFaces(
int, T
const &, U &)
const;
191 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFromEdges(
int, T
const &, U &)
const;
192 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFromVerts(
int, T
const &, U &)
const;
194 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFVarFromFaces(
int, T
const &, U &,
int)
const;
195 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFVarFromEdges(
int, T
const &, U &,
int)
const;
196 template <Sdc::SchemeType SCHEME,
class T,
class U>
void interpFVarFromVerts(
int, T
const &, U &,
int)
const;
198 template <Sdc::SchemeType SCHEME,
class T,
class U,
class U1,
class U2>
199 void limit(T
const & src, U & pos, U1 * tan1, U2 * tan2)
const;
201 template <Sdc::SchemeType SCHEME,
class T,
class U>
202 void limitFVar(T
const & src, U * dst,
int channel)
const;
206 TopologyRefiner
const & _refiner;
214 typedef float Weight;
217 Mask(Weight* v, Weight* e, Weight* f) : _vertWeights(v), _edgeWeights(e), _faceWeights(f) { }
221 int GetNumVertexWeights()
const {
return _vertCount; }
222 int GetNumEdgeWeights()
const {
return _edgeCount; }
223 int GetNumFaceWeights()
const {
return _faceCount; }
225 void SetNumVertexWeights(
int count) { _vertCount = count; }
226 void SetNumEdgeWeights(
int count) { _edgeCount = count; }
227 void SetNumFaceWeights(
int count) { _faceCount = count; }
229 Weight
const& VertexWeight(
int index)
const {
return _vertWeights[index]; }
230 Weight
const& EdgeWeight(
int index)
const {
return _edgeWeights[index]; }
231 Weight
const& FaceWeight(
int index)
const {
return _faceWeights[index]; }
233 Weight& VertexWeight(
int index) {
return _vertWeights[index]; }
234 Weight& EdgeWeight(
int index) {
return _edgeWeights[index]; }
235 Weight& FaceWeight(
int index) {
return _faceWeights[index]; }
237 bool AreFaceWeightsForFaceCenters()
const {
return _faceWeightsForFaceCenters; }
238 void SetFaceWeightsForFaceCenters(
bool on) { _faceWeightsForFaceCenters = on; }
241 Weight* _vertWeights;
242 Weight* _edgeWeights;
243 Weight* _faceWeights;
249 bool _faceWeightsForFaceCenters;
259 template <
class T,
class U>
263 assert(level>0 and level<=(
int)_refiner._refinements.size());
265 switch (_refiner._subdivType) {
267 interpFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst);
268 interpFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst);
269 interpFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst);
272 interpFromFaces<Sdc::SCHEME_LOOP>(level, src, dst);
273 interpFromEdges<Sdc::SCHEME_LOOP>(level, src, dst);
274 interpFromVerts<Sdc::SCHEME_LOOP>(level, src, dst);
277 interpFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst);
278 interpFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst);
279 interpFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst);
284 template <
class T,
class U>
288 assert(level>0 and level<=(
int)_refiner._refinements.size());
290 switch (_refiner._subdivType) {
292 interpFVarFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
293 interpFVarFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
294 interpFVarFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
297 interpFVarFromFaces<Sdc::SCHEME_LOOP>(level, src, dst, channel);
298 interpFVarFromEdges<Sdc::SCHEME_LOOP>(level, src, dst, channel);
299 interpFVarFromVerts<Sdc::SCHEME_LOOP>(level, src, dst, channel);
302 interpFVarFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
303 interpFVarFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
304 interpFVarFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
309 template <
class T,
class U>
315 "Cannot compute limit points -- last level of refinement does not include full topology.");
319 switch (_refiner._subdivType) {
321 limit<Sdc::SCHEME_CATMARK>(src, dst, (U*)0, (U*)0);
324 limit<Sdc::SCHEME_LOOP>(src, dst, (U*)0, (U*)0);
327 limit<Sdc::SCHEME_BILINEAR>(src, dst, (U*)0, (U*)0);
332 template <
class T,
class U,
class U1,
class U2>
338 "Cannot compute limit points -- last level of refinement does not include full topology.");
342 switch (_refiner._subdivType) {
344 limit<Sdc::SCHEME_CATMARK>(src, dstPos, &dstTan1, &dstTan2);
347 limit<Sdc::SCHEME_LOOP>(src, dstPos, &dstTan1, &dstTan2);
350 limit<Sdc::SCHEME_BILINEAR>(src, dstPos, &dstTan1, &dstTan2);
355 template <
class T,
class U>
361 "Cannot compute limit points -- last level of refinement does not include full topology.");
365 switch (_refiner._subdivType) {
367 limitFVar<Sdc::SCHEME_CATMARK>(src, dst, channel);
370 limitFVar<Sdc::SCHEME_LOOP>(src, dst, channel);
373 limitFVar<Sdc::SCHEME_BILINEAR>(src, dst, channel);
378 template <
class T,
class U>
382 assert(level>0 and level<=(
int)_refiner._refinements.size());
387 for (
int cFace = 0; cFace < child.
getNumFaces(); ++cFace) {
389 Vtr::Index pFace = refinement.getChildFaceParentFace(cFace);
391 dst[cFace] = src[pFace];
395 template <
class T,
class U>
399 assert(level>0 and level<=(
int)_refiner._refinements.size());
408 if (refinement.getNumChildVerticesFromFaces() > 0) {
410 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
412 Vtr::Index cVert = refinement.getFaceChildVertex(face);
418 float fVaryingWeight = 1.0f / (float) fVerts.
size();
421 for (
int i = 0; i < fVerts.
size(); ++i) {
422 dst[cVert].AddWithWeight(src[fVerts[i]], fVaryingWeight);
427 for (
int edge = 0; edge < parent.
getNumEdges(); ++edge) {
429 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
436 dst[cVert].AddWithWeight(src[eVerts[0]], 0.5f);
437 dst[cVert].AddWithWeight(src[eVerts[1]], 0.5f);
442 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
447 dst[cVert].AddWithWeight(src[vert], 1.0f);
457 template <Sdc::SchemeType SCHEME,
class T,
class U>
459 PrimvarRefiner::interpFromFaces(
int level, T
const & src, U & dst)
const {
470 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
479 Mask fMask(fVertWeights, 0, 0);
482 scheme.ComputeFaceVertexMask(fHood, fMask);
487 for (
int i = 0; i < fVerts.
size(); ++i) {
489 dst[cVert].AddWithWeight(src[fVerts[i]], fVertWeights[i]);
494 template <Sdc::SchemeType SCHEME,
class T,
class U>
496 PrimvarRefiner::interpFromEdges(
int level, T
const & src, U & dst)
const {
498 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
499 Vtr::internal::Level
const & parent = refinement.parent();
500 Vtr::internal::Level
const & child = refinement.child();
502 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
504 Vtr::internal::EdgeInterface eHood(parent);
506 float eVertWeights[2];
507 Vtr::internal::StackBuffer<float,8> eFaceWeights(parent.getMaxEdgeFaces());
509 for (
int edge = 0; edge < parent.getNumEdges(); ++edge) {
511 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
517 eFaces = parent.getEdgeFaces(edge);
519 Mask eMask(eVertWeights, 0, eFaceWeights);
521 eHood.SetIndex(edge);
526 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
531 dst[cVert].AddWithWeight(src[eVerts[0]], eVertWeights[0]);
532 dst[cVert].AddWithWeight(src[eVerts[1]], eVertWeights[1]);
534 if (eMask.GetNumFaceWeights() > 0) {
536 for (
int i = 0; i < eFaces.size(); ++i) {
538 if (eMask.AreFaceWeightsForFaceCenters()) {
539 assert(refinement.getNumChildVerticesFromFaces() > 0);
540 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
543 dst[cVert].AddWithWeight(dst[cVertOfFace], eFaceWeights[i]);
547 pFaceVerts = parent.getFaceVertices(pFace);
550 for ( ; pFaceEdges[eInFace] != edge; ++eInFace ) ;
552 int vInFace = eInFace + 2;
553 if (vInFace >= pFaceVerts.size()) vInFace -= pFaceVerts.
size();
556 dst[cVert].AddWithWeight(src[pVertNext], eFaceWeights[i]);
563 template <Sdc::SchemeType SCHEME,
class T,
class U>
565 PrimvarRefiner::interpFromVerts(
int level, T
const & src, U & dst)
const {
567 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
568 Vtr::internal::Level
const & parent = refinement.
parent();
569 Vtr::internal::Level
const & child = refinement.child();
571 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
573 Vtr::internal::VertexInterface vHood(parent, child);
575 Vtr::internal::StackBuffer<float,32> weightBuffer(2*parent.getMaxValence());
577 for (
int vert = 0; vert < parent.getNumVertices(); ++vert) {
579 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
585 vFaces = parent.getVertexFaces(vert);
588 * vEdgeWeights = weightBuffer,
589 * vFaceWeights = vEdgeWeights + vEdges.
size();
591 Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
593 vHood.SetIndex(vert, cVert);
598 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
608 if (vMask.GetNumFaceWeights() > 0) {
609 assert(vMask.AreFaceWeightsForFaceCenters());
611 for (
int i = 0; i < vFaces.size(); ++i) {
613 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
615 dst[cVert].AddWithWeight(dst[cVertOfFace], vFaceWeights[i]);
618 if (vMask.GetNumEdgeWeights() > 0) {
620 for (
int i = 0; i < vEdges.size(); ++i) {
623 Vtr::Index pVertOppositeEdge = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
625 dst[cVert].AddWithWeight(src[pVertOppositeEdge], vEdgeWeights[i]);
628 dst[cVert].AddWithWeight(src[vert], vVertWeight);
636 template <Sdc::SchemeType SCHEME,
class T,
class U>
638 PrimvarRefiner::interpFVarFromFaces(
int level, T
const & src, U & dst,
int channel)
const {
640 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
642 if (refinement.getNumChildVerticesFromFaces() == 0)
return;
644 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
646 Vtr::internal::Level
const & parentLevel = refinement.parent();
647 Vtr::internal::Level
const & childLevel = refinement.child();
649 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
650 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
652 Vtr::internal::StackBuffer<float,16> fValueWeights(parentLevel.getMaxValence());
654 for (
int face = 0; face < parentLevel.getNumFaces(); ++face) {
656 Vtr::Index cVert = refinement.getFaceChildVertex(face);
660 Vtr::Index cVertValue = childFVar.getVertexValueOffset(cVert);
670 Mask fMask(fValueWeights, 0, 0);
671 Vtr::internal::FaceInterface fHood(fValues.size());
673 scheme.ComputeFaceVertexMask(fHood, fMask);
676 dst[cVertValue].Clear();
678 for (
int i = 0; i < fValues.size(); ++i) {
679 dst[cVertValue].AddWithWeight(src[fValues[i]], fValueWeights[i]);
684 template <Sdc::SchemeType SCHEME,
class T,
class U>
686 PrimvarRefiner::interpFVarFromEdges(
int level, T
const & src, U & dst,
int channel)
const {
688 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
690 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
692 Vtr::internal::Level
const & parentLevel = refinement.parent();
693 Vtr::internal::Level
const & childLevel = refinement.child();
695 Vtr::internal::FVarRefinement
const & refineFVar = refinement.getFVarRefinement(channel);
696 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
697 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
703 float eVertWeights[2];
704 Vtr::internal::StackBuffer<float,8> eFaceWeights(parentLevel.getMaxEdgeFaces());
706 Mask eMask(eVertWeights, 0, eFaceWeights);
708 bool isLinearFVar = parentFVar.isLinear();
710 eMask.SetNumVertexWeights(2);
711 eMask.SetNumEdgeWeights(0);
712 eMask.SetNumFaceWeights(0);
714 eVertWeights[0] = 0.5f;
715 eVertWeights[1] = 0.5f;
718 Vtr::internal::EdgeInterface eHood(parentLevel);
720 for (
int edge = 0; edge < parentLevel.getNumEdges(); ++edge) {
722 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
728 bool fvarEdgeVertMatchesVertex = childFVar.valueTopologyMatches(cVertValues[0]);
729 if (fvarEdgeVertMatchesVertex) {
734 eHood.SetIndex(edge);
740 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
765 parentFVar.getEdgeFaceValues(edge, 0, eVertValues);
767 Index cVertValue = cVertValues[0];
769 dst[cVertValue].Clear();
770 dst[cVertValue].AddWithWeight(src[eVertValues[0]], eVertWeights[0]);
771 dst[cVertValue].AddWithWeight(src[eVertValues[1]], eVertWeights[1]);
773 if (eMask.GetNumFaceWeights() > 0) {
777 for (
int i = 0; i < eFaces.size(); ++i) {
778 if (eMask.AreFaceWeightsForFaceCenters()) {
780 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
783 Vtr::Index cValueOfFace = childFVar.getVertexValueOffset(cVertOfFace);
784 dst[cVertValue].AddWithWeight(dst[cValueOfFace], eFaceWeights[i]);
788 pFaceVerts = parentLevel.getFaceVertices(pFace);
791 for ( ; pFaceEdges[eInFace] != edge; ++eInFace ) ;
794 int vInFace = eInFace + 2;
795 if (vInFace >= pFaceVerts.size()) vInFace -= pFaceVerts.
size();
797 Vtr::Index pValueNext = parentFVar.getFaceValues(pFace)[vInFace];
798 dst[cVertValue].AddWithWeight(src[pValueNext], eFaceWeights[i]);
811 for (
int i = 0; i < cVertValues.size(); ++i) {
813 int eFaceIndex = refineFVar.getChildValueParentSource(cVert, i);
814 assert(eFaceIndex == i);
816 parentFVar.getEdgeFaceValues(edge, eFaceIndex, eVertValues);
818 Index cVertValue = cVertValues[i];
820 dst[cVertValue].Clear();
821 dst[cVertValue].AddWithWeight(src[eVertValues[0]], 0.5);
822 dst[cVertValue].AddWithWeight(src[eVertValues[1]], 0.5);
828 template <Sdc::SchemeType SCHEME,
class T,
class U>
830 PrimvarRefiner::interpFVarFromVerts(
int level, T
const & src, U & dst,
int channel)
const {
832 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
834 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
836 Vtr::internal::Level
const & parentLevel = refinement.parent();
837 Vtr::internal::Level
const & childLevel = refinement.child();
839 Vtr::internal::FVarRefinement
const & refineFVar = refinement.getFVarRefinement(channel);
840 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
841 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
843 bool isLinearFVar = parentFVar.isLinear();
845 Vtr::internal::StackBuffer<float,32> weightBuffer(2*parentLevel.getMaxValence());
847 Vtr::internal::StackBuffer<Vtr::Index,16> vEdgeValues(parentLevel.getMaxValence());
849 Vtr::internal::VertexInterface vHood(parentLevel, childLevel);
851 for (
int vert = 0; vert < parentLevel.getNumVertices(); ++vert) {
853 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
858 cVertValues = childFVar.getVertexValues(cVert);
860 bool fvarVertVertMatchesVertex = childFVar.valueTopologyMatches(cVertValues[0]);
861 if (isLinearFVar && fvarVertVertMatchesVertex) {
862 dst[cVertValues[0]].Clear();
863 dst[cVertValues[0]].AddWithWeight(src[pVertValues[0]], 1.0f);
867 if (fvarVertVertMatchesVertex) {
877 float * vEdgeWeights = weightBuffer;
878 float * vFaceWeights = vEdgeWeights + vEdges.
size();
880 Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
882 vHood.SetIndex(vert, cVert);
887 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
916 dst[cVertValue].Clear();
917 if (vMask.GetNumFaceWeights() > 0) {
918 assert(vMask.AreFaceWeightsForFaceCenters());
922 for (
int i = 0; i < vFaces.size(); ++i) {
924 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
927 Vtr::Index cValueOfFace = childFVar.getVertexValueOffset(cVertOfFace);
928 dst[cVertValue].AddWithWeight(dst[cValueOfFace], vFaceWeights[i]);
931 if (vMask.GetNumEdgeWeights() > 0) {
933 parentFVar.getVertexEdgeValues(vert, vEdgeValues);
935 for (
int i = 0; i < vEdges.size(); ++i) {
936 dst[cVertValue].AddWithWeight(src[vEdgeValues[i]], vEdgeWeights[i]);
939 dst[cVertValue].AddWithWeight(src[pVertValue], vVertWeight);
951 for (
int cSibling = 0; cSibling < cVertValues.size(); ++cSibling) {
952 int pSibling = refineFVar.getChildValueParentSource(cVert, cSibling);
953 assert(pSibling == cSibling);
955 Vtr::Index pVertValue = pVertValues[pSibling];
956 Vtr::Index cVertValue = cVertValues[cSibling];
958 dst[cVertValue].Clear();
959 if (cValueTags[cSibling].isCorner()) {
960 dst[cVertValue].AddWithWeight(src[pVertValue], 1.0f);
967 parentFVar.getVertexCreaseEndValues(vert, pSibling, pEndValues);
969 float vWeight = 0.75f;
970 float eWeight = 0.125f;
977 if (pValueTags[pSibling].isSemiSharp()) {
978 float wCorner = pValueTags[pSibling].isDepSharp()
979 ? refineFVar.getFractionalWeight(vert, !pSibling, cVert, !cSibling)
980 : refineFVar.getFractionalWeight(vert, pSibling, cVert, cSibling);
981 float wCrease = 1.0f - wCorner;
983 vWeight = wCrease * 0.75f + wCorner;
984 eWeight = wCrease * 0.125f;
986 dst[cVertValue].AddWithWeight(src[pEndValues[0]], eWeight);
987 dst[cVertValue].AddWithWeight(src[pEndValues[1]], eWeight);
988 dst[cVertValue].AddWithWeight(src[pVertValue], vWeight);
995 template <Sdc::SchemeType SCHEME,
class T,
class U,
class U1,
class U2>
997 PrimvarRefiner::limit(T
const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr)
const {
999 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1004 bool hasTangents = (dstTan1Ptr && dstTan2Ptr);
1005 int numMasks = 1 + (hasTangents ? 2 : 0);
1007 Vtr::internal::StackBuffer<Index,33> indexBuffer(maxWeightsPerMask);
1008 Vtr::internal::StackBuffer<float,99> weightBuffer(numMasks * maxWeightsPerMask);
1010 float * vPosWeights = weightBuffer,
1011 * ePosWeights = vPosWeights + 1,
1012 * fPosWeights = ePosWeights + level.getMaxValence();
1013 float * vTan1Weights = vPosWeights + maxWeightsPerMask,
1014 * eTan1Weights = ePosWeights + maxWeightsPerMask,
1015 * fTan1Weights = fPosWeights + maxWeightsPerMask;
1016 float * vTan2Weights = vTan1Weights + maxWeightsPerMask,
1017 * eTan2Weights = eTan1Weights + maxWeightsPerMask,
1018 * fTan2Weights = fTan1Weights + maxWeightsPerMask;
1020 Mask posMask( vPosWeights, ePosWeights, fPosWeights);
1021 Mask tan1Mask(vTan1Weights, eTan1Weights, fTan1Weights);
1022 Mask tan2Mask(vTan2Weights, eTan2Weights, fTan2Weights);
1026 Vtr::internal::VertexInterface vHood(level, level);
1028 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1034 if (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0)) {
1035 dstPos[vert].Clear();
1036 dstPos[vert].AddWithWeight(src[vert], 1.0);
1038 (*dstTan1Ptr)[vert].Clear();
1039 (*dstTan2Ptr)[vert].Clear();
1052 vHood.SetIndex(vert, vert);
1055 scheme.ComputeVertexLimitMask(vHood, posMask, tan1Mask, tan2Mask, vRule);
1057 scheme.ComputeVertexLimitMask(vHood, posMask, vRule);
1064 Index * eIndices = indexBuffer;
1065 Index * fIndices = indexBuffer + vEdges.size();
1067 for (
int i = 0; i < vEdges.size(); ++i) {
1070 eIndices[i] = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
1072 if (posMask.GetNumFaceWeights() || (hasTangents && tan1Mask.GetNumFaceWeights())) {
1076 for (
int i = 0; i < vFaces.size(); ++i) {
1080 if (vOppInFace >= fVerts.size()) vOppInFace -= (
LocalIndex)fVerts.size();
1082 fIndices[i] = level.getFaceVertices(vFaces[i])[vOppInFace];
1092 dstPos[vert].Clear();
1093 for (
int i = 0; i < posMask.GetNumFaceWeights(); ++i) {
1094 dstPos[vert].AddWithWeight(src[fIndices[i]], fPosWeights[i]);
1096 for (
int i = 0; i < posMask.GetNumEdgeWeights(); ++i) {
1097 dstPos[vert].AddWithWeight(src[eIndices[i]], ePosWeights[i]);
1099 dstPos[vert].AddWithWeight(src[vert], vPosWeights[0]);
1107 assert(tan1Mask.GetNumFaceWeights() == tan2Mask.GetNumFaceWeights());
1108 assert(tan1Mask.GetNumEdgeWeights() == tan2Mask.GetNumEdgeWeights());
1110 U1 & dstTan1 = *dstTan1Ptr;
1111 U2 & dstTan2 = *dstTan2Ptr;
1113 dstTan1[vert].Clear();
1114 dstTan2[vert].Clear();
1115 for (
int i = 0; i < tan1Mask.GetNumFaceWeights(); ++i) {
1116 dstTan1[vert].AddWithWeight(src[fIndices[i]], fTan1Weights[i]);
1117 dstTan2[vert].AddWithWeight(src[fIndices[i]], fTan2Weights[i]);
1119 for (
int i = 0; i < tan1Mask.GetNumEdgeWeights(); ++i) {
1120 dstTan1[vert].AddWithWeight(src[eIndices[i]], eTan1Weights[i]);
1121 dstTan2[vert].AddWithWeight(src[eIndices[i]], eTan2Weights[i]);
1123 dstTan1[vert].AddWithWeight(src[vert], vTan1Weights[0]);
1124 dstTan2[vert].AddWithWeight(src[vert], vTan2Weights[0]);
1129 template <Sdc::SchemeType SCHEME,
class T,
class U>
1131 PrimvarRefiner::limitFVar(T
const & src, U * dst,
int channel)
const {
1133 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1136 Vtr::internal::FVarLevel
const & fvarChannel = level.
getFVarLevel(channel);
1138 int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
1140 Vtr::internal::StackBuffer<float,33> weightBuffer(maxWeightsPerMask);
1141 Vtr::internal::StackBuffer<Index,16> vEdgeBuffer(level.getMaxValence());
1144 Vtr::internal::VertexInterface vHood(level, level);
1146 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1157 bool isIncomplete = (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0));
1158 if (isIncomplete || fvarChannel.isLinear()) {
1159 for (
int i = 0; i < vValues.size(); ++i) {
1162 dst[vValue].Clear();
1163 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1168 bool fvarVertMatchesVertex = fvarChannel.valueTopologyMatches(vValues[0]);
1169 if (fvarVertMatchesVertex) {
1173 float * vWeights = weightBuffer,
1174 * eWeights = vWeights + 1,
1175 * fWeights = eWeights + vEdges.size();
1177 Mask vMask(vWeights, eWeights, fWeights);
1179 vHood.SetIndex(vert, vert);
1181 scheme.ComputeVertexLimitMask(vHood, vMask, level.getVertexRule(vert));
1188 dst[vValue].Clear();
1189 if (vMask.GetNumFaceWeights() > 0) {
1190 assert(!vMask.AreFaceWeightsForFaceCenters());
1195 for (
int i = 0; i < vFaces.size(); ++i) {
1198 if (vOppInFace >= faceValues.size()) vOppInFace -= faceValues.size();
1200 Index vValueOppositeFace = faceValues[vOppInFace];
1202 dst[vValue].AddWithWeight(src[vValueOppositeFace], fWeights[i]);
1205 if (vMask.GetNumEdgeWeights() > 0) {
1206 Index * vEdgeValues = vEdgeBuffer;
1207 fvarChannel.getVertexEdgeValues(vert, vEdgeValues);
1209 for (
int i = 0; i < vEdges.size(); ++i) {
1210 dst[vValue].AddWithWeight(src[vEdgeValues[i]], eWeights[i]);
1213 dst[vValue].AddWithWeight(src[vValue], vWeights[0]);
1218 for (
int i = 0; i < vValues.size(); ++i) {
1221 dst[vValue].Clear();
1222 if (fvarChannel.getValueTag(vValue).isCorner()) {
1223 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1225 Index vEndValues[2];
1226 fvarChannel.getVertexCreaseEndValues(vert, i, vEndValues);
1228 dst[vValue].AddWithWeight(src[vEndValues[0]], 1.0f/6.0f);
1229 dst[vValue].AddWithWeight(src[vEndValues[1]], 1.0f/6.0f);
1230 dst[vValue].AddWithWeight(src[vValue], 2.0f/3.0f);
1240 using namespace OPENSUBDIV_VERSION;
int GetMaxLevel() const
Returns the highest level of refinement.
bool IndexIsValid(Index index)
FVarLevel & getFVarLevel(int channel)
Level const & parent() const
TopologyRefiner const & GetTopologyRefiner() const
ConstIndexArray getEdgeVertices(Index edgeIndex) const
void Error(ErrorType err)
Sends an OSD error.
Vtr::ConstArray< ValueTag > ConstValueTagArray
Vtr::LocalIndex LocalIndex
Issue a generic runtime error, but continue execution.
void InterpolateFaceUniform(int level, T const &src, U &dst) const
Refine uniform (per-face) primvar data between levels.
Vtr::internal::Refinement & getRefinement(int l)
Scheme is a class template which provides all implementation for the subdivision schemes supported by...
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...
ConstIndexArray getFaceVertices(Index faceIndex) const
int getNumChildVerticesFromFaces() const
Vtr::ConstLocalIndexArray ConstLocalIndexArray
Vtr::ConstIndexArray ConstIndexArray
Vtr::internal::Level & getLevel(int l)
Stores topology data for a specified set of refinement options.
void InterpolateVarying(int level, T const &src, U &dst) const
Apply only varying interpolation weights to a primvar buffer for a single level level of refinement...
void Limit(T const &src, U &dstPos) const
Apply limit weights to a primvar buffer.
int getNumVertices() const
Index getFaceChildVertex(Index f) const
void Interpolate(int level, T const &src, U &dst) const
Apply vertex interpolation weights to a primvar buffer for a single level level of refinement...
void LimitFaceVarying(T const &src, U &dst, int channel=0) const
int getMaxValence() const
PrimvarRefiner(TopologyRefiner const &refiner)
Applies refinement operations to generic primvar data.