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:
barfowl 2014-11-21 16:19:21 -08:00
parent eb3f35ba74
commit 5c99660f47
3 changed files with 63 additions and 15 deletions

View File

@ -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];

View File

@ -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) {

View File

@ -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);
}