mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2025-01-17 19:50:06 +00:00
Generalized limit functions to support all schemes:
- added detection of sharp corners in generic scheme limit mask query - tweaked Loop limit mask to simplify the regular case - updated TopologyRefiner::Limit() methods to support all schemes
This commit is contained in:
parent
eb3f35ba74
commit
5c99660f47
@ -552,6 +552,9 @@ private:
|
||||
template <Sdc::Type SCHEME, class T, class U> void faceVaryingInterpolateChildVertsFromEdges(Vtr::Refinement const &, T const & src, U & dst, int channel) const;
|
||||
template <Sdc::Type SCHEME, class T, class U> void faceVaryingInterpolateChildVertsFromVerts(Vtr::Refinement const &, T const & src, U & dst, int channel) const;
|
||||
|
||||
template <Sdc::Type SCHEME, class T, class U> void limit(T const & src, U * dst) const;
|
||||
|
||||
template <Sdc::Type SCHEME, class T, class U> void faceVaryingLimit(T const & src, U * dst, int channel) const;
|
||||
|
||||
void initializePtexIndices() const;
|
||||
|
||||
@ -1301,6 +1304,25 @@ template <class T, class U>
|
||||
inline void
|
||||
TopologyRefiner::Limit(T const & src, U * dst) const {
|
||||
|
||||
assert(GetMaxLevel() > 0);
|
||||
|
||||
switch (_subdivType) {
|
||||
case Sdc::TYPE_CATMARK:
|
||||
limit<Sdc::TYPE_CATMARK>(src, dst);
|
||||
break;
|
||||
case Sdc::TYPE_LOOP:
|
||||
limit<Sdc::TYPE_LOOP>(src, dst);
|
||||
break;
|
||||
case Sdc::TYPE_BILINEAR:
|
||||
limit<Sdc::TYPE_BILINEAR>(src, dst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <Sdc::Type SCHEME, class T, class U>
|
||||
inline void
|
||||
TopologyRefiner::limit(T const & src, U * dst) const {
|
||||
|
||||
//
|
||||
// Work in progress...
|
||||
// - does not support tangents yet (unclear how)
|
||||
@ -1311,11 +1333,8 @@ TopologyRefiner::Limit(T const & src, U * dst) const {
|
||||
// - currently requires one refinement to get rid of N-sided faces:
|
||||
// - could limit regular vertices from level 0
|
||||
//
|
||||
Sdc::Scheme<SCHEME> scheme(_subdivOptions);
|
||||
|
||||
assert(_subdivType == Sdc::TYPE_CATMARK);
|
||||
Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
|
||||
|
||||
assert(GetMaxLevel() > 0);
|
||||
Vtr::Level const & level = getLevel(GetMaxLevel());
|
||||
|
||||
int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
|
||||
@ -1354,8 +1373,11 @@ TopologyRefiner::Limit(T const & src, U * dst) const {
|
||||
IndexArray const vFaces = level.getVertexFaces(vert);
|
||||
LocalIndexArray const vInFace = level.getVertexFaceLocalIndices(vert);
|
||||
for (int i = 0; i < vFaces.size(); ++i) {
|
||||
LocalIndex vOppInFace = (vInFace[i] + 2) & 3;
|
||||
Index vertOppositeFace = level.getFaceVertices(vFaces[i])[vOppInFace];
|
||||
IndexArray const fVerts = level.getFaceVertices(vFaces[i]);
|
||||
|
||||
LocalIndex vOppInFace = (vInFace[i] + 2);
|
||||
if (vOppInFace >= fVerts.size()) vOppInFace -= (LocalIndex)fVerts.size();
|
||||
Index vertOppositeFace = level.getFaceVertices(vFaces[i])[vOppInFace];
|
||||
|
||||
dst[vert].AddWithWeight(src[vertOppositeFace], fWeights[i]);
|
||||
}
|
||||
@ -1376,10 +1398,27 @@ template <class T, class U>
|
||||
inline void
|
||||
TopologyRefiner::LimitFaceVarying(T const & src, U * dst, int channel) const {
|
||||
|
||||
assert(_subdivType == Sdc::TYPE_CATMARK);
|
||||
Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
|
||||
|
||||
assert(GetMaxLevel() > 0);
|
||||
|
||||
switch (_subdivType) {
|
||||
case Sdc::TYPE_CATMARK:
|
||||
faceVaryingLimit<Sdc::TYPE_CATMARK>(src, dst, channel);
|
||||
break;
|
||||
case Sdc::TYPE_LOOP:
|
||||
faceVaryingLimit<Sdc::TYPE_LOOP>(src, dst, channel);
|
||||
break;
|
||||
case Sdc::TYPE_BILINEAR:
|
||||
faceVaryingLimit<Sdc::TYPE_BILINEAR>(src, dst, channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <Sdc::Type SCHEME, class T, class U>
|
||||
inline void
|
||||
TopologyRefiner::faceVaryingLimit(T const & src, U * dst, int channel) const {
|
||||
|
||||
Sdc::Scheme<SCHEME> scheme(_subdivOptions);
|
||||
|
||||
Vtr::Level const & level = getLevel(GetMaxLevel());
|
||||
Vtr::FVarLevel const & fvarChannel = *level._fvarChannels[channel];
|
||||
|
||||
|
@ -168,7 +168,7 @@ Scheme<TYPE_LOOP>::assignSmoothMaskForVertex(VERTEX const& vertex, MASK& mask) c
|
||||
mask.SetNumFaceWeights(0);
|
||||
mask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
// Specialize for the regular case (1/16 per edge-vert + 5/8 for the vert itself):
|
||||
// Specialize for the regular case: 1/16 per edge-vert, 5/8 for the vert itself:
|
||||
Weight eWeight = (Weight) 0.0625f;
|
||||
Weight vWeight = (Weight) 0.625f;
|
||||
|
||||
@ -234,13 +234,19 @@ Scheme<TYPE_LOOP>::assignInteriorLimitMask(VERTEX const& vertex, MASK& posMask)
|
||||
posMask.SetNumFaceWeights(0);
|
||||
posMask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
Weight invValence = 1.0f / valence;
|
||||
// Specialize for the regular case: 1/12 per edge-vert, 1/2 for the vert itself:
|
||||
Weight eWeight = 1.0f / 12.0f;
|
||||
Weight vWeight = 0.5f;
|
||||
|
||||
Weight beta = 0.25f * cosf((Weight)M_PI * 2.0f * invValence) + 0.375f;
|
||||
beta = (0.625f - (beta * beta)) * invValence;;
|
||||
if (valence != 6) {
|
||||
Weight invValence = 1.0f / valence;
|
||||
|
||||
Weight eWeight = 1.0f / (valence + 3.0f / (8.0f * beta));
|
||||
Weight vWeight = (Weight)(1.0f - (eWeight * valence));
|
||||
Weight beta = 0.25f * cosf((Weight)M_PI * 2.0f * invValence) + 0.375f;
|
||||
beta = (0.625f - (beta * beta)) * invValence;;
|
||||
|
||||
eWeight = 1.0f / (valence + 3.0f / (8.0f * beta));
|
||||
vWeight = (Weight)(1.0f - (eWeight * valence));
|
||||
}
|
||||
|
||||
posMask.VertexWeight(0) = vWeight;
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
|
@ -574,6 +574,9 @@ Scheme<SCHEME>::ComputeVertexLimitMask(VERTEX const& vertex,
|
||||
{
|
||||
if (vertex.GetNumFaces() == vertex.GetNumEdges()) {
|
||||
assignInteriorLimitMask(vertex, mask);
|
||||
} else if ((vertex.GetNumFaces() == 1) &&
|
||||
(_options.GetVVarBoundaryInterpolation() == Sdc::Options::VVAR_BOUNDARY_EDGE_AND_CORNER)) {
|
||||
assignCornerMaskForVertex(vertex, mask);
|
||||
} else {
|
||||
assignBoundaryLimitMask(vertex, mask);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user