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 {
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) :
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 <
class T,
class U>
268 assert(level>0 && level<=(
int)_refiner._refinements.size());
270 switch (_refiner._subdivType) {
272 interpFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst);
273 interpFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst);
274 interpFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst);
277 interpFromFaces<Sdc::SCHEME_LOOP>(level, src, dst);
278 interpFromEdges<Sdc::SCHEME_LOOP>(level, src, dst);
279 interpFromVerts<Sdc::SCHEME_LOOP>(level, src, dst);
282 interpFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst);
283 interpFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst);
284 interpFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst);
289 template <
class T,
class U>
293 assert(level>0 && level<=(
int)_refiner._refinements.size());
295 switch (_refiner._subdivType) {
297 interpFVarFromFaces<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
298 interpFVarFromEdges<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
299 interpFVarFromVerts<Sdc::SCHEME_CATMARK>(level, src, dst, channel);
302 interpFVarFromFaces<Sdc::SCHEME_LOOP>(level, src, dst, channel);
303 interpFVarFromEdges<Sdc::SCHEME_LOOP>(level, src, dst, channel);
304 interpFVarFromVerts<Sdc::SCHEME_LOOP>(level, src, dst, channel);
307 interpFVarFromFaces<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
308 interpFVarFromEdges<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
309 interpFVarFromVerts<Sdc::SCHEME_BILINEAR>(level, src, dst, channel);
314 template <
class T,
class U>
320 "Failure in PrimvarRefiner::Limit() -- "
321 "last level of refinement does not include full topology.");
325 switch (_refiner._subdivType) {
327 limit<Sdc::SCHEME_CATMARK>(src, dst, (U*)0, (U*)0);
330 limit<Sdc::SCHEME_LOOP>(src, dst, (U*)0, (U*)0);
333 limit<Sdc::SCHEME_BILINEAR>(src, dst, (U*)0, (U*)0);
338 template <
class T,
class U,
class U1,
class U2>
344 "Failure in PrimvarRefiner::Limit() -- "
345 "last level of refinement does not include full topology.");
349 switch (_refiner._subdivType) {
351 limit<Sdc::SCHEME_CATMARK>(src, dstPos, &dstTan1, &dstTan2);
354 limit<Sdc::SCHEME_LOOP>(src, dstPos, &dstTan1, &dstTan2);
357 limit<Sdc::SCHEME_BILINEAR>(src, dstPos, &dstTan1, &dstTan2);
362 template <
class T,
class U>
368 "Failure in PrimvarRefiner::LimitFaceVarying() -- "
369 "last level of refinement does not include full topology.");
373 switch (_refiner._subdivType) {
375 limitFVar<Sdc::SCHEME_CATMARK>(src, dst, channel);
378 limitFVar<Sdc::SCHEME_LOOP>(src, dst, channel);
381 limitFVar<Sdc::SCHEME_BILINEAR>(src, dst, channel);
386 template <
class T,
class U>
390 assert(level>0 && level<=(
int)_refiner._refinements.size());
395 for (
int cFace = 0; cFace < child.
getNumFaces(); ++cFace) {
397 Vtr::Index pFace = refinement.getChildFaceParentFace(cFace);
399 dst[cFace] = src[pFace];
403 template <
class T,
class U>
407 assert(level>0 && level<=(
int)_refiner._refinements.size());
416 if (refinement.getNumChildVerticesFromFaces() > 0) {
418 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
420 Vtr::Index cVert = refinement.getFaceChildVertex(face);
426 float fVaryingWeight = 1.0f / (float) fVerts.
size();
429 for (
int i = 0; i < fVerts.
size(); ++i) {
430 dst[cVert].AddWithWeight(src[fVerts[i]], fVaryingWeight);
435 for (
int edge = 0; edge < parent.
getNumEdges(); ++edge) {
437 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
444 dst[cVert].AddWithWeight(src[eVerts[0]], 0.5f);
445 dst[cVert].AddWithWeight(src[eVerts[1]], 0.5f);
450 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
455 dst[cVert].AddWithWeight(src[vert], 1.0f);
465 template <Sdc::SchemeType SCHEME,
class T,
class U>
467 PrimvarRefiner::interpFromFaces(
int level, T
const & src, U & dst)
const {
478 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
487 Mask fMask(fVertWeights, 0, 0);
490 scheme.ComputeFaceVertexMask(fHood, fMask);
495 for (
int i = 0; i < fVerts.
size(); ++i) {
497 dst[cVert].AddWithWeight(src[fVerts[i]], fVertWeights[i]);
502 template <Sdc::SchemeType SCHEME,
class T,
class U>
504 PrimvarRefiner::interpFromEdges(
int level, T
const & src, U & dst)
const {
506 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
507 Vtr::internal::Level
const & parent = refinement.parent();
508 Vtr::internal::Level
const & child = refinement.child();
510 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
512 Vtr::internal::EdgeInterface eHood(parent);
514 float eVertWeights[2];
515 Vtr::internal::StackBuffer<float,8> eFaceWeights(parent.getMaxEdgeFaces());
517 for (
int edge = 0; edge < parent.getNumEdges(); ++edge) {
519 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
525 eFaces = parent.getEdgeFaces(edge);
527 Mask eMask(eVertWeights, 0, eFaceWeights);
529 eHood.SetIndex(edge);
534 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
539 dst[cVert].AddWithWeight(src[eVerts[0]], eVertWeights[0]);
540 dst[cVert].AddWithWeight(src[eVerts[1]], eVertWeights[1]);
542 if (eMask.GetNumFaceWeights() > 0) {
544 for (
int i = 0; i < eFaces.size(); ++i) {
546 if (eMask.AreFaceWeightsForFaceCenters()) {
547 assert(refinement.getNumChildVerticesFromFaces() > 0);
548 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
551 dst[cVert].AddWithWeight(dst[cVertOfFace], eFaceWeights[i]);
555 pFaceVerts = parent.getFaceVertices(pFace);
558 for ( ; pFaceEdges[eInFace] != edge; ++eInFace ) ;
560 int vInFace = eInFace + 2;
561 if (vInFace >= pFaceVerts.size()) vInFace -= pFaceVerts.
size();
564 dst[cVert].AddWithWeight(src[pVertNext], eFaceWeights[i]);
571 template <Sdc::SchemeType SCHEME,
class T,
class U>
573 PrimvarRefiner::interpFromVerts(
int level, T
const & src, U & dst)
const {
575 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
576 Vtr::internal::Level
const & parent = refinement.
parent();
577 Vtr::internal::Level
const & child = refinement.child();
579 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
581 Vtr::internal::VertexInterface vHood(parent, child);
583 Vtr::internal::StackBuffer<float,32> weightBuffer(2*parent.getMaxValence());
585 for (
int vert = 0; vert < parent.getNumVertices(); ++vert) {
587 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
593 vFaces = parent.getVertexFaces(vert);
596 * vEdgeWeights = weightBuffer,
597 * vFaceWeights = vEdgeWeights + vEdges.
size();
599 Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
601 vHood.SetIndex(vert, cVert);
606 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
616 if (vMask.GetNumFaceWeights() > 0) {
617 assert(vMask.AreFaceWeightsForFaceCenters());
619 for (
int i = 0; i < vFaces.size(); ++i) {
621 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
623 dst[cVert].AddWithWeight(dst[cVertOfFace], vFaceWeights[i]);
626 if (vMask.GetNumEdgeWeights() > 0) {
628 for (
int i = 0; i < vEdges.size(); ++i) {
631 Vtr::Index pVertOppositeEdge = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
633 dst[cVert].AddWithWeight(src[pVertOppositeEdge], vEdgeWeights[i]);
636 dst[cVert].AddWithWeight(src[vert], vVertWeight);
644 template <Sdc::SchemeType SCHEME,
class T,
class U>
646 PrimvarRefiner::interpFVarFromFaces(
int level, T
const & src, U & dst,
int channel)
const {
648 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
650 if (refinement.getNumChildVerticesFromFaces() == 0)
return;
652 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
654 Vtr::internal::Level
const & parentLevel = refinement.parent();
655 Vtr::internal::Level
const & childLevel = refinement.child();
657 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
658 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
660 Vtr::internal::StackBuffer<float,16> fValueWeights(parentLevel.getMaxValence());
662 for (
int face = 0; face < parentLevel.getNumFaces(); ++face) {
664 Vtr::Index cVert = refinement.getFaceChildVertex(face);
668 Vtr::Index cVertValue = childFVar.getVertexValueOffset(cVert);
678 Mask fMask(fValueWeights, 0, 0);
679 Vtr::internal::FaceInterface fHood(fValues.size());
681 scheme.ComputeFaceVertexMask(fHood, fMask);
684 dst[cVertValue].Clear();
686 for (
int i = 0; i < fValues.size(); ++i) {
687 dst[cVertValue].AddWithWeight(src[fValues[i]], fValueWeights[i]);
692 template <Sdc::SchemeType SCHEME,
class T,
class U>
694 PrimvarRefiner::interpFVarFromEdges(
int level, T
const & src, U & dst,
int channel)
const {
696 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
698 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
700 Vtr::internal::Level
const & parentLevel = refinement.parent();
701 Vtr::internal::Level
const & childLevel = refinement.child();
703 Vtr::internal::FVarRefinement
const & refineFVar = refinement.getFVarRefinement(channel);
704 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
705 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
711 float eVertWeights[2];
712 Vtr::internal::StackBuffer<float,8> eFaceWeights(parentLevel.getMaxEdgeFaces());
714 Mask eMask(eVertWeights, 0, eFaceWeights);
718 eMask.SetNumVertexWeights(2);
719 eMask.SetNumEdgeWeights(0);
720 eMask.SetNumFaceWeights(0);
722 eVertWeights[0] = 0.5f;
723 eVertWeights[1] = 0.5f;
726 Vtr::internal::EdgeInterface eHood(parentLevel);
728 for (
int edge = 0; edge < parentLevel.getNumEdges(); ++edge) {
730 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
736 bool fvarEdgeVertMatchesVertex = childFVar.valueTopologyMatches(cVertValues[0]);
737 if (fvarEdgeVertMatchesVertex) {
742 eHood.SetIndex(edge);
748 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
773 parentFVar.getEdgeFaceValues(edge, 0, eVertValues);
775 Index cVertValue = cVertValues[0];
777 dst[cVertValue].Clear();
778 dst[cVertValue].AddWithWeight(src[eVertValues[0]], eVertWeights[0]);
779 dst[cVertValue].AddWithWeight(src[eVertValues[1]], eVertWeights[1]);
781 if (eMask.GetNumFaceWeights() > 0) {
785 for (
int i = 0; i < eFaces.size(); ++i) {
786 if (eMask.AreFaceWeightsForFaceCenters()) {
788 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
791 Vtr::Index cValueOfFace = childFVar.getVertexValueOffset(cVertOfFace);
792 dst[cVertValue].AddWithWeight(dst[cValueOfFace], eFaceWeights[i]);
796 pFaceVerts = parentLevel.getFaceVertices(pFace);
799 for ( ; pFaceEdges[eInFace] != edge; ++eInFace ) ;
802 int vInFace = eInFace + 2;
803 if (vInFace >= pFaceVerts.size()) vInFace -= pFaceVerts.
size();
805 Vtr::Index pValueNext = parentFVar.getFaceValues(pFace)[vInFace];
806 dst[cVertValue].AddWithWeight(src[pValueNext], eFaceWeights[i]);
819 for (
int i = 0; i < cVertValues.size(); ++i) {
821 int eFaceIndex = refineFVar.getChildValueParentSource(cVert, i);
822 assert(eFaceIndex == i);
824 parentFVar.getEdgeFaceValues(edge, eFaceIndex, eVertValues);
826 Index cVertValue = cVertValues[i];
828 dst[cVertValue].Clear();
829 dst[cVertValue].AddWithWeight(src[eVertValues[0]], 0.5);
830 dst[cVertValue].AddWithWeight(src[eVertValues[1]], 0.5);
836 template <Sdc::SchemeType SCHEME,
class T,
class U>
838 PrimvarRefiner::interpFVarFromVerts(
int level, T
const & src, U & dst,
int channel)
const {
840 Vtr::internal::Refinement
const & refinement = _refiner.
getRefinement(level-1);
842 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
844 Vtr::internal::Level
const & parentLevel = refinement.parent();
845 Vtr::internal::Level
const & childLevel = refinement.child();
847 Vtr::internal::FVarRefinement
const & refineFVar = refinement.getFVarRefinement(channel);
848 Vtr::internal::FVarLevel
const & parentFVar = parentLevel.getFVarLevel(channel);
849 Vtr::internal::FVarLevel
const & childFVar = childLevel.getFVarLevel(channel);
853 Vtr::internal::StackBuffer<float,32> weightBuffer(2*parentLevel.getMaxValence());
855 Vtr::internal::StackBuffer<Vtr::Index,16> vEdgeValues(parentLevel.getMaxValence());
857 Vtr::internal::VertexInterface vHood(parentLevel, childLevel);
859 for (
int vert = 0; vert < parentLevel.getNumVertices(); ++vert) {
861 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
866 cVertValues = childFVar.getVertexValues(cVert);
868 bool fvarVertVertMatchesVertex = childFVar.valueTopologyMatches(cVertValues[0]);
869 if (isLinearFVar && fvarVertVertMatchesVertex) {
870 dst[cVertValues[0]].Clear();
871 dst[cVertValues[0]].AddWithWeight(src[pVertValues[0]], 1.0f);
875 if (fvarVertVertMatchesVertex) {
885 float * vEdgeWeights = weightBuffer;
886 float * vFaceWeights = vEdgeWeights + vEdges.
size();
888 Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
890 vHood.SetIndex(vert, cVert);
895 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
924 dst[cVertValue].Clear();
925 if (vMask.GetNumFaceWeights() > 0) {
926 assert(vMask.AreFaceWeightsForFaceCenters());
930 for (
int i = 0; i < vFaces.size(); ++i) {
932 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
935 Vtr::Index cValueOfFace = childFVar.getVertexValueOffset(cVertOfFace);
936 dst[cVertValue].AddWithWeight(dst[cValueOfFace], vFaceWeights[i]);
939 if (vMask.GetNumEdgeWeights() > 0) {
941 parentFVar.getVertexEdgeValues(vert, vEdgeValues);
943 for (
int i = 0; i < vEdges.size(); ++i) {
944 dst[cVertValue].AddWithWeight(src[vEdgeValues[i]], vEdgeWeights[i]);
947 dst[cVertValue].AddWithWeight(src[pVertValue], vVertWeight);
959 for (
int cSibling = 0; cSibling < cVertValues.size(); ++cSibling) {
960 int pSibling = refineFVar.getChildValueParentSource(cVert, cSibling);
961 assert(pSibling == cSibling);
963 Vtr::Index pVertValue = pVertValues[pSibling];
964 Vtr::Index cVertValue = cVertValues[cSibling];
966 dst[cVertValue].Clear();
967 if (isLinearFVar || cValueTags[cSibling].isCorner()) {
968 dst[cVertValue].AddWithWeight(src[pVertValue], 1.0f);
975 parentFVar.getVertexCreaseEndValues(vert, pSibling, pEndValues);
977 float vWeight = 0.75f;
978 float eWeight = 0.125f;
985 if (pValueTags[pSibling].isSemiSharp()) {
986 float wCorner = pValueTags[pSibling].isDepSharp()
987 ? refineFVar.getFractionalWeight(vert, !pSibling, cVert, !cSibling)
988 : refineFVar.getFractionalWeight(vert, pSibling, cVert, cSibling);
989 float wCrease = 1.0f - wCorner;
991 vWeight = wCrease * 0.75f + wCorner;
992 eWeight = wCrease * 0.125f;
994 dst[cVertValue].AddWithWeight(src[pEndValues[0]], eWeight);
995 dst[cVertValue].AddWithWeight(src[pEndValues[1]], eWeight);
996 dst[cVertValue].AddWithWeight(src[pVertValue], vWeight);
1003 template <Sdc::SchemeType SCHEME,
class T,
class U,
class U1,
class U2>
1005 PrimvarRefiner::limit(T
const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr)
const {
1007 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1012 bool hasTangents = (dstTan1Ptr && dstTan2Ptr);
1013 int numMasks = 1 + (hasTangents ? 2 : 0);
1015 Vtr::internal::StackBuffer<Index,33> indexBuffer(maxWeightsPerMask);
1016 Vtr::internal::StackBuffer<float,99> weightBuffer(numMasks * maxWeightsPerMask);
1018 float * vPosWeights = weightBuffer,
1019 * ePosWeights = vPosWeights + 1,
1020 * fPosWeights = ePosWeights + level.getMaxValence();
1021 float * vTan1Weights = vPosWeights + maxWeightsPerMask,
1022 * eTan1Weights = ePosWeights + maxWeightsPerMask,
1023 * fTan1Weights = fPosWeights + maxWeightsPerMask;
1024 float * vTan2Weights = vTan1Weights + maxWeightsPerMask,
1025 * eTan2Weights = eTan1Weights + maxWeightsPerMask,
1026 * fTan2Weights = fTan1Weights + maxWeightsPerMask;
1028 Mask posMask( vPosWeights, ePosWeights, fPosWeights);
1029 Mask tan1Mask(vTan1Weights, eTan1Weights, fTan1Weights);
1030 Mask tan2Mask(vTan2Weights, eTan2Weights, fTan2Weights);
1034 Vtr::internal::VertexInterface vHood(level, level);
1036 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1042 if (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0)) {
1043 dstPos[vert].Clear();
1044 dstPos[vert].AddWithWeight(src[vert], 1.0);
1046 (*dstTan1Ptr)[vert].Clear();
1047 (*dstTan2Ptr)[vert].Clear();
1060 vHood.SetIndex(vert, vert);
1063 scheme.ComputeVertexLimitMask(vHood, posMask, tan1Mask, tan2Mask, vRule);
1065 scheme.ComputeVertexLimitMask(vHood, posMask, vRule);
1072 Index * eIndices = indexBuffer;
1073 Index * fIndices = indexBuffer + vEdges.size();
1075 for (
int i = 0; i < vEdges.size(); ++i) {
1078 eIndices[i] = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
1080 if (posMask.GetNumFaceWeights() || (hasTangents && tan1Mask.GetNumFaceWeights())) {
1084 for (
int i = 0; i < vFaces.size(); ++i) {
1088 if (vOppInFace >= fVerts.size()) vOppInFace -= (
LocalIndex)fVerts.size();
1090 fIndices[i] = level.getFaceVertices(vFaces[i])[vOppInFace];
1100 dstPos[vert].Clear();
1101 for (
int i = 0; i < posMask.GetNumFaceWeights(); ++i) {
1102 dstPos[vert].AddWithWeight(src[fIndices[i]], fPosWeights[i]);
1104 for (
int i = 0; i < posMask.GetNumEdgeWeights(); ++i) {
1105 dstPos[vert].AddWithWeight(src[eIndices[i]], ePosWeights[i]);
1107 dstPos[vert].AddWithWeight(src[vert], vPosWeights[0]);
1115 assert(tan1Mask.GetNumFaceWeights() == tan2Mask.GetNumFaceWeights());
1116 assert(tan1Mask.GetNumEdgeWeights() == tan2Mask.GetNumEdgeWeights());
1118 U1 & dstTan1 = *dstTan1Ptr;
1119 U2 & dstTan2 = *dstTan2Ptr;
1121 dstTan1[vert].Clear();
1122 dstTan2[vert].Clear();
1123 for (
int i = 0; i < tan1Mask.GetNumFaceWeights(); ++i) {
1124 dstTan1[vert].AddWithWeight(src[fIndices[i]], fTan1Weights[i]);
1125 dstTan2[vert].AddWithWeight(src[fIndices[i]], fTan2Weights[i]);
1127 for (
int i = 0; i < tan1Mask.GetNumEdgeWeights(); ++i) {
1128 dstTan1[vert].AddWithWeight(src[eIndices[i]], eTan1Weights[i]);
1129 dstTan2[vert].AddWithWeight(src[eIndices[i]], eTan2Weights[i]);
1131 dstTan1[vert].AddWithWeight(src[vert], vTan1Weights[0]);
1132 dstTan2[vert].AddWithWeight(src[vert], vTan2Weights[0]);
1137 template <Sdc::SchemeType SCHEME,
class T,
class U>
1139 PrimvarRefiner::limitFVar(T
const & src, U * dst,
int channel)
const {
1141 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1144 Vtr::internal::FVarLevel
const & fvarChannel = level.
getFVarLevel(channel);
1146 int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
1148 Vtr::internal::StackBuffer<float,33> weightBuffer(maxWeightsPerMask);
1149 Vtr::internal::StackBuffer<Index,16> vEdgeBuffer(level.getMaxValence());
1152 Vtr::internal::VertexInterface vHood(level, level);
1154 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1165 bool isIncomplete = (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0));
1166 if (isIncomplete || fvarChannel.isLinear()) {
1167 for (
int i = 0; i < vValues.size(); ++i) {
1170 dst[vValue].Clear();
1171 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1176 bool fvarVertMatchesVertex = fvarChannel.valueTopologyMatches(vValues[0]);
1177 if (fvarVertMatchesVertex) {
1181 float * vWeights = weightBuffer,
1182 * eWeights = vWeights + 1,
1183 * fWeights = eWeights + vEdges.size();
1185 Mask vMask(vWeights, eWeights, fWeights);
1187 vHood.SetIndex(vert, vert);
1189 scheme.ComputeVertexLimitMask(vHood, vMask, level.getVertexRule(vert));
1196 dst[vValue].Clear();
1197 if (vMask.GetNumFaceWeights() > 0) {
1198 assert(!vMask.AreFaceWeightsForFaceCenters());
1203 for (
int i = 0; i < vFaces.size(); ++i) {
1206 if (vOppInFace >= faceValues.size()) vOppInFace -= faceValues.size();
1208 Index vValueOppositeFace = faceValues[vOppInFace];
1210 dst[vValue].AddWithWeight(src[vValueOppositeFace], fWeights[i]);
1213 if (vMask.GetNumEdgeWeights() > 0) {
1214 Index * vEdgeValues = vEdgeBuffer;
1215 fvarChannel.getVertexEdgeValues(vert, vEdgeValues);
1217 for (
int i = 0; i < vEdges.size(); ++i) {
1218 dst[vValue].AddWithWeight(src[vEdgeValues[i]], eWeights[i]);
1221 dst[vValue].AddWithWeight(src[vValue], vWeights[0]);
1226 for (
int i = 0; i < vValues.size(); ++i) {
1229 dst[vValue].Clear();
1230 if (fvarChannel.getValueTag(vValue).isCorner()) {
1231 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1233 Index vEndValues[2];
1234 fvarChannel.getVertexCreaseEndValues(vert, i, vEndValues);
1236 dst[vValue].AddWithWeight(src[vEndValues[0]], 1.0f/6.0f);
1237 dst[vValue].AddWithWeight(src[vEndValues[1]], 1.0f/6.0f);
1238 dst[vValue].AddWithWeight(src[vValue], 2.0f/3.0f);
1248 using namespace OPENSUBDIV_VERSION;
Index getFaceChildVertex(Index f) const
Vtr::internal::Level & getLevel(int l)
int getNumVertices() const
Vtr::ConstLocalIndexArray ConstLocalIndexArray
int getNumChildVerticesFromFaces() const
void Error(ErrorType err, const char *format,...)
Sends an OSD error with a message (internal use only)
Vtr::ConstIndexArray ConstIndexArray
void Limit(T const &src, U &dstPos) const
Apply limit weights to a primvar buffer.
Level const & parent() const
FVarLevel & getFVarLevel(int channel)
bool IndexIsValid(Index index)
Scheme is a class template which provides all implementation for the subdivision schemes supported by...
ConstIndexArray getFaceVertices(Index faceIndex) const
TopologyRefiner const & GetTopologyRefiner() const
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...
Issue a generic runtime error, but continue execution.
Vtr::LocalIndex LocalIndex
Applies refinement operations to generic primvar data.
Vtr::ConstArray< ValueTag > ConstValueTagArray
void InterpolateFaceUniform(int level, T const &src, U &dst) const
Refine uniform (per-face) primvar data between levels.
Stores topology data for a specified set of refinement options.
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...
Vtr::internal::Refinement & getRefinement(int l)
int getMaxValence() const
ConstIndexArray getEdgeVertices(Index edgeIndex) const
void Interpolate(int level, T const &src, U &dst) const
Apply vertex interpolation weights to a primvar buffer for a single level of refinement.
void LimitFaceVarying(T const &src, U &dst, int channel=0) const
int GetMaxLevel() const
Returns the highest level of refinement.
PrimvarRefiner(TopologyRefiner const &refiner)