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"
48namespace OPENSUBDIV_VERSION {
55template <
typename REAL>
113 template <
class T,
class U>
void Interpolate(
int level, T
const & src, U & dst)
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;
264template <
typename REAL>
265template <
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);
290template <
typename REAL>
291template <
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);
316template <
typename REAL>
317template <
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);
341template <
typename REAL>
342template <
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);
366template <
typename REAL>
367template <
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);
391template <
typename REAL>
392template <
class T,
class U>
396 assert(level>0 && level<=(
int)_refiner._refinements.size());
398 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
399 Vtr::internal::Level
const & child = refinement.child();
401 for (
int cFace = 0; cFace < child.getNumFaces(); ++cFace) {
403 Vtr::Index pFace = refinement.getChildFaceParentFace(cFace);
405 dst[cFace] = src[pFace];
409template <
typename REAL>
410template <
class T,
class U>
414 assert(level>0 && level<=(
int)_refiner._refinements.size());
416 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
417 Vtr::internal::Level
const & parent = refinement.parent();
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);
455 for (
int vert = 0; vert < parent.getNumVertices(); ++vert) {
457 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
462 dst[cVert].AddWithWeight(src[vert], 1.0f);
472template <
typename REAL>
473template <Sdc::SchemeType SCHEME,
class T,
class U>
477 Vtr::internal::Refinement
const & refinement = _refiner.getRefinement(level-1);
478 Vtr::internal::Level
const & parent = refinement.parent();
480 if (refinement.getNumChildVerticesFromFaces() == 0)
return;
484 Vtr::internal::StackBuffer<Weight,16> fVertWeights(parent.getMaxValence());
486 for (
int face = 0; face < parent.getNumFaces(); ++face) {
488 Vtr::Index cVert = refinement.getFaceChildVertex(face);
495 Mask fMask(fVertWeights, 0, 0);
496 Vtr::internal::FaceInterface fHood(fVerts.
size());
498 scheme.ComputeFaceVertexMask(fHood, fMask);
503 for (
int i = 0; i < fVerts.
size(); ++i) {
505 dst[cVert].AddWithWeight(src[fVerts[i]], fVertWeights[i]);
510template <
typename REAL>
511template <Sdc::SchemeType SCHEME,
class T,
class U>
513PrimvarRefinerReal<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]);
580template <
typename REAL>
581template <Sdc::SchemeType SCHEME,
class T,
class U>
583PrimvarRefinerReal<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);
654template <
typename REAL>
655template <Sdc::SchemeType SCHEME,
class T,
class U>
657PrimvarRefinerReal<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]);
703template <
typename REAL>
704template <Sdc::SchemeType SCHEME,
class T,
class U>
706PrimvarRefinerReal<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);
848template <
typename REAL>
849template <Sdc::SchemeType SCHEME,
class T,
class U>
851PrimvarRefinerReal<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);
969 Vtr::internal::FVarLevel::ConstValueTagArray pValueTags = parentFVar.getVertexValueTags(vert);
970 Vtr::internal::FVarLevel::ConstValueTagArray cValueTags = childFVar.getVertexValueTags(cVert);
972 for (
int cSiblingIndex = 0; cSiblingIndex < cVertValues.size(); ++cSiblingIndex) {
973 int pSiblingIndex = refineFVar.getChildValueParentSource(cVert, cSiblingIndex);
974 assert(pSiblingIndex == cSiblingIndex);
976 typedef Vtr::internal::FVarLevel::Sibling SiblingIntType;
978 SiblingIntType cSibling = (SiblingIntType) cSiblingIndex;
979 SiblingIntType pSibling = (SiblingIntType) pSiblingIndex;
981 Vtr::Index pVertValue = pVertValues[pSibling];
982 Vtr::Index cVertValue = cVertValues[cSibling];
984 dst[cVertValue].Clear();
985 if (isLinearFVar || cValueTags[cSibling].isCorner()) {
986 dst[cVertValue].AddWithWeight(src[pVertValue], 1.0f);
993 parentFVar.getVertexCreaseEndValues(vert, pSibling, pEndValues);
995 Weight vWeight = 0.75f;
996 Weight eWeight = 0.125f;
1003 if (pValueTags[pSibling].isSemiSharp()) {
1004 Weight wCorner = pValueTags[pSibling].isDepSharp()
1005 ? refineFVar.getFractionalWeight(vert, !pSibling, cVert, !cSibling)
1006 : refineFVar.getFractionalWeight(vert, pSibling, cVert, cSibling);
1007 Weight wCrease = 1.0f - wCorner;
1009 vWeight = wCrease * 0.75f + wCorner;
1010 eWeight = wCrease * 0.125f;
1012 dst[cVertValue].AddWithWeight(src[pEndValues[0]], eWeight);
1013 dst[cVertValue].AddWithWeight(src[pEndValues[1]], eWeight);
1014 dst[cVertValue].AddWithWeight(src[pVertValue], vWeight);
1021template <
typename REAL>
1022template <Sdc::SchemeType SCHEME,
class T,
class U,
class U1,
class U2>
1024PrimvarRefinerReal<REAL>::limit(T
const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr)
const {
1026 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1028 Vtr::internal::Level
const & level = _refiner.getLevel(_refiner.GetMaxLevel());
1030 int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
1031 bool hasTangents = (dstTan1Ptr && dstTan2Ptr);
1032 int numMasks = 1 + (hasTangents ? 2 : 0);
1034 Vtr::internal::StackBuffer<Index,33> indexBuffer(maxWeightsPerMask);
1035 Vtr::internal::StackBuffer<Weight,99> weightBuffer(numMasks * maxWeightsPerMask);
1037 Weight * vPosWeights = weightBuffer,
1038 * ePosWeights = vPosWeights + 1,
1039 * fPosWeights = ePosWeights + level.getMaxValence();
1040 Weight * vTan1Weights = vPosWeights + maxWeightsPerMask,
1041 * eTan1Weights = ePosWeights + maxWeightsPerMask,
1042 * fTan1Weights = fPosWeights + maxWeightsPerMask;
1043 Weight * vTan2Weights = vTan1Weights + maxWeightsPerMask,
1044 * eTan2Weights = eTan1Weights + maxWeightsPerMask,
1045 * fTan2Weights = fTan1Weights + maxWeightsPerMask;
1047 Mask posMask( vPosWeights, ePosWeights, fPosWeights);
1048 Mask tan1Mask(vTan1Weights, eTan1Weights, fTan1Weights);
1049 Mask tan2Mask(vTan2Weights, eTan2Weights, fTan2Weights);
1053 Vtr::internal::VertexInterface vHood(level, level);
1055 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1061 if (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0)) {
1062 dstPos[vert].Clear();
1063 dstPos[vert].AddWithWeight(src[vert], 1.0);
1065 (*dstTan1Ptr)[vert].Clear();
1066 (*dstTan2Ptr)[vert].Clear();
1079 vHood.SetIndex(vert, vert);
1082 scheme.ComputeVertexLimitMask(vHood, posMask, tan1Mask, tan2Mask, vRule);
1084 scheme.ComputeVertexLimitMask(vHood, posMask, vRule);
1091 Index * eIndices = indexBuffer;
1092 Index * fIndices = indexBuffer + vEdges.size();
1094 for (
int i = 0; i < vEdges.size(); ++i) {
1097 eIndices[i] = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
1099 if (posMask.GetNumFaceWeights() || (hasTangents && tan1Mask.GetNumFaceWeights())) {
1103 for (
int i = 0; i < vFaces.size(); ++i) {
1107 if (vOppInFace >= fVerts.size()) vOppInFace -= (
LocalIndex)fVerts.size();
1109 fIndices[i] = level.getFaceVertices(vFaces[i])[vOppInFace];
1119 dstPos[vert].Clear();
1120 for (
int i = 0; i < posMask.GetNumFaceWeights(); ++i) {
1121 dstPos[vert].AddWithWeight(src[fIndices[i]], fPosWeights[i]);
1123 for (
int i = 0; i < posMask.GetNumEdgeWeights(); ++i) {
1124 dstPos[vert].AddWithWeight(src[eIndices[i]], ePosWeights[i]);
1126 dstPos[vert].AddWithWeight(src[vert], vPosWeights[0]);
1134 assert(tan1Mask.GetNumFaceWeights() == tan2Mask.GetNumFaceWeights());
1135 assert(tan1Mask.GetNumEdgeWeights() == tan2Mask.GetNumEdgeWeights());
1137 U1 & dstTan1 = *dstTan1Ptr;
1138 U2 & dstTan2 = *dstTan2Ptr;
1140 dstTan1[vert].Clear();
1141 dstTan2[vert].Clear();
1142 for (
int i = 0; i < tan1Mask.GetNumFaceWeights(); ++i) {
1143 dstTan1[vert].AddWithWeight(src[fIndices[i]], fTan1Weights[i]);
1144 dstTan2[vert].AddWithWeight(src[fIndices[i]], fTan2Weights[i]);
1146 for (
int i = 0; i < tan1Mask.GetNumEdgeWeights(); ++i) {
1147 dstTan1[vert].AddWithWeight(src[eIndices[i]], eTan1Weights[i]);
1148 dstTan2[vert].AddWithWeight(src[eIndices[i]], eTan2Weights[i]);
1150 dstTan1[vert].AddWithWeight(src[vert], vTan1Weights[0]);
1151 dstTan2[vert].AddWithWeight(src[vert], vTan2Weights[0]);
1156template <
typename REAL>
1157template <Sdc::SchemeType SCHEME,
class T,
class U>
1159PrimvarRefinerReal<REAL>::limitFVar(T
const & src, U & dst,
int channel)
const {
1161 Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
1163 Vtr::internal::Level
const & level = _refiner.getLevel(_refiner.GetMaxLevel());
1164 Vtr::internal::FVarLevel
const & fvarChannel = level.getFVarLevel(channel);
1166 int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
1168 Vtr::internal::StackBuffer<Weight,33> weightBuffer(maxWeightsPerMask);
1169 Vtr::internal::StackBuffer<Index,16> vEdgeBuffer(level.getMaxValence());
1172 Vtr::internal::VertexInterface vHood(level, level);
1174 for (
int vert = 0; vert < level.getNumVertices(); ++vert) {
1185 bool isIncomplete = (level.getVertexTag(vert)._incomplete || (vEdges.size() == 0));
1186 if (isIncomplete || fvarChannel.isLinear()) {
1187 for (
int i = 0; i < vValues.size(); ++i) {
1190 dst[vValue].Clear();
1191 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1196 bool fvarVertMatchesVertex = fvarChannel.valueTopologyMatches(vValues[0]);
1197 if (fvarVertMatchesVertex) {
1201 Weight * vWeights = weightBuffer,
1202 * eWeights = vWeights + 1,
1203 * fWeights = eWeights + vEdges.size();
1205 Mask vMask(vWeights, eWeights, fWeights);
1207 vHood.SetIndex(vert, vert);
1209 scheme.ComputeVertexLimitMask(vHood, vMask, level.getVertexRule(vert));
1216 dst[vValue].Clear();
1217 if (vMask.GetNumFaceWeights() > 0) {
1218 assert(!vMask.AreFaceWeightsForFaceCenters());
1223 for (
int i = 0; i < vFaces.size(); ++i) {
1226 if (vOppInFace >= faceValues.size()) vOppInFace -= faceValues.size();
1228 Index vValueOppositeFace = faceValues[vOppInFace];
1230 dst[vValue].AddWithWeight(src[vValueOppositeFace], fWeights[i]);
1233 if (vMask.GetNumEdgeWeights() > 0) {
1234 Index * vEdgeValues = vEdgeBuffer;
1235 fvarChannel.getVertexEdgeValues(vert, vEdgeValues);
1237 for (
int i = 0; i < vEdges.size(); ++i) {
1238 dst[vValue].AddWithWeight(src[vEdgeValues[i]], eWeights[i]);
1241 dst[vValue].AddWithWeight(src[vValue], vWeights[0]);
1246 for (
int i = 0; i < vValues.size(); ++i) {
1249 dst[vValue].Clear();
1250 if (fvarChannel.getValueTag(vValue).isCorner()) {
1251 dst[vValue].AddWithWeight(src[vValue], 1.0f);
1253 Index vEndValues[2];
1254 fvarChannel.getVertexCreaseEndValues(vert, i, vEndValues);
1256 dst[vValue].AddWithWeight(src[vEndValues[0]], 1.0f/6.0f);
1257 dst[vValue].AddWithWeight(src[vEndValues[1]], 1.0f/6.0f);
1258 dst[vValue].AddWithWeight(src[vValue], 2.0f/3.0f);
1274using namespace OPENSUBDIV_VERSION;
Vtr::LocalIndex LocalIndex
void Error(ErrorType err, const char *format,...)
Sends an OSD error with a message (internal use only)
Vtr::ConstIndexArray ConstIndexArray
Vtr::ConstLocalIndexArray ConstLocalIndexArray
@ FAR_RUNTIME_ERROR
Issue a generic runtime error, but continue execution.
bool IndexIsValid(Index index)
Applies refinement operations to generic primvar data.
void Limit(T const &src, U &dstPos) const
Apply limit weights to a primvar buffer.
PrimvarRefinerReal(TopologyRefiner const &refiner)
void Limit(T const &src, U &dstPos, U1 &dstTan1, U2 &dstTan2) const
void InterpolateFaceUniform(int level, T const &src, U &dst) const
Refine uniform (per-face) primvar data between levels.
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.
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 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 LimitFaceVarying(T const &src, U &dst, int channel=0) const
PrimvarRefiner(TopologyRefiner const &refiner)
Stores topology data for a specified set of refinement options.
Scheme is a class template which provides all implementation for the subdivision schemes supported by...