mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-25 04:50:06 +00:00
Added more functionality missing from stubs for Sdc limit masks:
- modified main LimitMask queries to include subdivision Rule - split internal mask assignments into corner, crease and smooth cases - adapted all three schemes to the new structure - completed limit tangents for Loop - update TopologyRefiner Limit methods to pass newly required Rule
This commit is contained in:
parent
f5c1617b0f
commit
6ba910cd95
@ -37,6 +37,7 @@
|
||||
#include "../vtr/fvarRefinement.h"
|
||||
#include "../vtr/maskInterfaces.h"
|
||||
#include "../far/types.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
@ -1418,7 +1419,11 @@ template <class T, class U>
|
||||
inline void
|
||||
TopologyRefiner::Limit(T const & src, U * dst) const {
|
||||
|
||||
assert(GetMaxLevel() > 0);
|
||||
if (getLevel(GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
|
||||
Error(FAR_RUNTIME_ERROR,
|
||||
"Cannot compute limit points -- last level of refinement does not include full topology.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_subdivType) {
|
||||
case Sdc::SCHEME_CATMARK:
|
||||
@ -1461,6 +1466,18 @@ TopologyRefiner::limit(T const & src, U * dst) const {
|
||||
for (int vert = 0; vert < level.getNumVertices(); ++vert) {
|
||||
ConstIndexArray vEdges = level.getVertexEdges(vert);
|
||||
|
||||
// Incomplete vertices (present in sparse refinement) do not have their full
|
||||
// topological neighborhood to determine a proper limit -- just leave the
|
||||
// vertex at the refined location and continue to the next:
|
||||
//
|
||||
if (level._vertTags[vert]._incomplete || (vEdges.size() == 0)) {
|
||||
dst[vert].Clear();
|
||||
dst[vert].AddWithWeight(src[vert], 1.0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Assign the mask weights to the common buffer and compute the mask:
|
||||
//
|
||||
float * vWeights = weightBuffer,
|
||||
* eWeights = vWeights + 1,
|
||||
* fWeights = eWeights + vEdges.size();
|
||||
@ -1470,7 +1487,7 @@ TopologyRefiner::limit(T const & src, U * dst) const {
|
||||
// This is a bit obscure -- child vertex index will be ignored here
|
||||
vHood.SetIndex(vert, vert);
|
||||
|
||||
scheme.ComputeVertexLimitMask(vHood, vMask);
|
||||
scheme.ComputeVertexLimitMask(vHood, vMask, level.getVertexRule(vert));
|
||||
|
||||
// Apply the weights to the vertex, the vertices opposite its incident
|
||||
// edges, and the opposite vertices of its incident faces:
|
||||
@ -1512,7 +1529,11 @@ template <class T, class U>
|
||||
inline void
|
||||
TopologyRefiner::LimitFaceVarying(T const & src, U * dst, int channel) const {
|
||||
|
||||
assert(GetMaxLevel() > 0);
|
||||
if (getLevel(GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
|
||||
Error(FAR_RUNTIME_ERROR,
|
||||
"Cannot compute limit points -- last level of refinement does not include full topology.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_subdivType) {
|
||||
case Sdc::SCHEME_CATMARK:
|
||||
@ -1546,21 +1567,31 @@ TopologyRefiner::faceVaryingLimit(T const & src, U * dst, int channel) const {
|
||||
|
||||
for (int vert = 0; vert < level.getNumVertices(); ++vert) {
|
||||
|
||||
ConstIndexArray vEdges = level.getVertexEdges(vert);
|
||||
ConstIndexArray vValues = fvarChannel.getVertexValues(vert);
|
||||
|
||||
// Incomplete vertices (present in sparse refinement) do not have their full
|
||||
// topological neighborhood to determine a proper limit -- just leave the
|
||||
// values (perhaps more than one per vertex) at the refined location.
|
||||
//
|
||||
// The same can be done if the face-varying channel is purely linear.
|
||||
//
|
||||
bool isIncomplete = (level._vertTags[vert]._incomplete || (vEdges.size() == 0));
|
||||
if (isIncomplete || fvarChannel._isLinear) {
|
||||
for (int i = 0; i < vValues.size(); ++i) {
|
||||
Vtr::Index vValue = vValues[i];
|
||||
|
||||
dst[vValue].Clear();
|
||||
dst[vValue].AddWithWeight(src[vValue], 1.0f);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool fvarVertMatchesVertex = fvarChannel.valueTopologyMatches(vValues[0]);
|
||||
if (fvarChannel._isLinear && fvarVertMatchesVertex) {
|
||||
Vtr::Index srcValueIndex = fvarChannel.getVertexValue(vert);
|
||||
Vtr::Index dstValueIndex = vValues[0];
|
||||
if (fvarVertMatchesVertex) {
|
||||
|
||||
dst[dstValueIndex].Clear();
|
||||
dst[dstValueIndex].AddWithWeight(src[srcValueIndex], 1.0f);
|
||||
} else if (fvarVertMatchesVertex) {
|
||||
// Assign the mask weights to the common buffer and compute the mask:
|
||||
//
|
||||
// Compute the limit mask based on vertex topology:
|
||||
//
|
||||
ConstIndexArray vEdges = level.getVertexEdges(vert);
|
||||
|
||||
float * vWeights = weightBuffer,
|
||||
* eWeights = vWeights + 1,
|
||||
* fWeights = eWeights + vEdges.size();
|
||||
@ -1569,7 +1600,7 @@ TopologyRefiner::faceVaryingLimit(T const & src, U * dst, int channel) const {
|
||||
|
||||
vHood.SetIndex(vert, vert);
|
||||
|
||||
scheme.ComputeVertexLimitMask(vHood, vMask);
|
||||
scheme.ComputeVertexLimitMask(vHood, vMask, level.getVertexRule(vert));
|
||||
|
||||
//
|
||||
// Apply mask to corresponding FVar values for neighboring vertices:
|
||||
|
@ -76,13 +76,12 @@ Scheme<SCHEME_BILINEAR>::ComputeVertexVertexMask(VERTEX const& vertex, MASK& mas
|
||||
|
||||
|
||||
//
|
||||
// Limit masks for any bilinear vertex are the vertex itself, with all tangents being
|
||||
// zero for now as tangents are not unique (what did Hbr do?):
|
||||
// Limit masks for position -- the limit position of all vertices is the refined vertex.
|
||||
//
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_BILINEAR>::assignInteriorLimitMask(VERTEX const& /* vertex */, MASK& posMask) const {
|
||||
Scheme<SCHEME_BILINEAR>::assignCornerLimitMask(VERTEX const& /* vertex */, MASK& posMask) const {
|
||||
|
||||
posMask.SetNumVertexWeights(1);
|
||||
posMask.SetNumEdgeWeights(0);
|
||||
@ -95,38 +94,65 @@ Scheme<SCHEME_BILINEAR>::assignInteriorLimitMask(VERTEX const& /* vertex */, MAS
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_BILINEAR>::assignBoundaryLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
Scheme<SCHEME_BILINEAR>::assignCreaseLimitMask(VERTEX const& vertex, MASK& posMask,
|
||||
int const /* creaseEnds */[2]) const {
|
||||
|
||||
assignInteriorLimitMask(vertex, posMask);
|
||||
assignCornerLimitMask(vertex, posMask);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_BILINEAR>::assignInteriorLimitTangentMasks(VERTEX const& /* vertex */,
|
||||
Scheme<SCHEME_BILINEAR>::assignSmoothLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
|
||||
assignCornerLimitMask(vertex, posMask);
|
||||
}
|
||||
|
||||
//
|
||||
// Limit masks for tangents -- these are ambibuous around all vertices. Provide
|
||||
// the tangents based on the incident edges of the first face.
|
||||
//
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_BILINEAR>::assignCornerLimitTangentMasks(VERTEX const& /* vertex */,
|
||||
MASK& tan1Mask, MASK& tan2Mask) const {
|
||||
|
||||
tan1Mask.SetNumVertexWeights(1);
|
||||
tan1Mask.SetNumEdgeWeights(0);
|
||||
tan1Mask.SetNumEdgeWeights(2);
|
||||
tan1Mask.SetNumFaceWeights(0);
|
||||
tan1Mask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
tan2Mask.SetNumVertexWeights(1);
|
||||
tan2Mask.SetNumEdgeWeights(0);
|
||||
tan2Mask.SetNumEdgeWeights(2);
|
||||
tan2Mask.SetNumFaceWeights(0);
|
||||
tan2Mask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
tan1Mask.VertexWeight(0) = 0.0f;
|
||||
tan2Mask.VertexWeight(0) = 0.0f;
|
||||
tan1Mask.VertexWeight(0) = -1.0f;
|
||||
tan1Mask.EdgeWeight(0) = 1.0f;
|
||||
tan1Mask.EdgeWeight(1) = 0.0f;
|
||||
|
||||
tan2Mask.VertexWeight(0) = -1.0f;
|
||||
tan2Mask.EdgeWeight(0) = 0.0f;
|
||||
tan2Mask.EdgeWeight(1) = 1.0f;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_BILINEAR>::assignBoundaryLimitTangentMasks(VERTEX const& vertex,
|
||||
Scheme<SCHEME_BILINEAR>::assignCreaseLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask, int const /* creaseEnds */[2]) const {
|
||||
|
||||
assignCornerLimitTangentMasks(vertex, tan1Mask, tan2Mask);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_BILINEAR>::assignSmoothLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask) const {
|
||||
|
||||
assignInteriorLimitTangentMasks(vertex, tan1Mask, tan2Mask);
|
||||
assignCornerLimitTangentMasks(vertex, tan1Mask, tan2Mask);
|
||||
}
|
||||
|
||||
} // end namespace sdc
|
||||
|
@ -145,8 +145,8 @@ Scheme<SCHEME_CATMARK>::assignSmoothMaskForEdge(EDGE const& edge, MASK& mask) co
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_CATMARK>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& mask, float const edgeSharpness[]) const {
|
||||
|
||||
Scheme<SCHEME_CATMARK>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& mask,
|
||||
int const creaseEnds[2]) const {
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
||||
int valence = vertex.GetNumEdges();
|
||||
@ -160,25 +160,11 @@ Scheme<SCHEME_CATMARK>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& ma
|
||||
Weight eWeight = 0.125f;
|
||||
|
||||
mask.VertexWeight(0) = vWeight;
|
||||
|
||||
//
|
||||
// NOTE -- at some point the sharpness vector was optional, and topology would be used
|
||||
// to identify a boundary crease. We are currently no longer passing a null sharpness
|
||||
// vector and may not support it in future, in which case this test can be removed:
|
||||
//
|
||||
if (edgeSharpness != 0) {
|
||||
// Use the sharpness values to identify the crease edges:
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
mask.EdgeWeight(i) = (edgeSharpness[i] > 0.0f) ? eWeight : 0.0f;
|
||||
}
|
||||
} else {
|
||||
// Use the boundary edges (first and last) as the crease edges:
|
||||
mask.EdgeWeight(0) = eWeight;
|
||||
for (int i = 1; i < (valence - 1); ++i) {
|
||||
mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
mask.EdgeWeight(valence-1) = eWeight;
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
mask.EdgeWeight(creaseEnds[0]) = eWeight;
|
||||
mask.EdgeWeight(creaseEnds[1]) = eWeight;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -225,7 +211,21 @@ Scheme<SCHEME_CATMARK>::assignSmoothMaskForVertex(VERTEX const& vertex, MASK& ma
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_CATMARK>::assignBoundaryLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
Scheme<SCHEME_CATMARK>::assignCornerLimitMask(VERTEX const& /* vertex */, MASK& posMask) const {
|
||||
|
||||
posMask.SetNumVertexWeights(1);
|
||||
posMask.SetNumEdgeWeights(0);
|
||||
posMask.SetNumFaceWeights(0);
|
||||
posMask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
posMask.VertexWeight(0) = 1.0f;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_CATMARK>::assignCreaseLimitMask(VERTEX const& vertex, MASK& posMask,
|
||||
int const creaseEnds[2]) const {
|
||||
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
||||
@ -240,17 +240,17 @@ Scheme<SCHEME_CATMARK>::assignBoundaryLimitMask(VERTEX const& vertex, MASK& posM
|
||||
Weight eWeight = 1.0f / 6.0f;
|
||||
|
||||
posMask.VertexWeight(0) = vWeight;
|
||||
posMask.EdgeWeight(0) = eWeight;
|
||||
for (int i = 1; i < valence - 1; ++i) {
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
posMask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
posMask.EdgeWeight(valence - 1) = eWeight;
|
||||
posMask.EdgeWeight(creaseEnds[0]) = eWeight;
|
||||
posMask.EdgeWeight(creaseEnds[1]) = eWeight;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_CATMARK>::assignInteriorLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
Scheme<SCHEME_CATMARK>::assignSmoothLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
||||
@ -262,11 +262,16 @@ Scheme<SCHEME_CATMARK>::assignInteriorLimitMask(VERTEX const& vertex, MASK& posM
|
||||
posMask.SetNumFaceWeights(valence);
|
||||
posMask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
// Probably a good idea to test for and assign the regular case as a special case:
|
||||
// Specialize for the regular case:
|
||||
Weight fWeight = 1.0f / 36.0f;
|
||||
Weight eWeight = 1.0f / 9.0f;
|
||||
Weight vWeight = 4.0f / 9.0f;
|
||||
|
||||
Weight fWeight = 1.0f / (Weight)(valence * (valence + 5.0f));
|
||||
Weight eWeight = 4.0f * fWeight;
|
||||
Weight vWeight = (Weight)(1.0f - valence * (eWeight + fWeight));
|
||||
if (valence != 4) {
|
||||
fWeight = 1.0f / (Weight)(valence * (valence + 5.0f));
|
||||
eWeight = 4.0f * fWeight;
|
||||
vWeight = (Weight)(1.0f - valence * (eWeight + fWeight));
|
||||
}
|
||||
|
||||
posMask.VertexWeight(0) = vWeight;
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
@ -282,26 +287,91 @@ Scheme<SCHEME_CATMARK>::assignInteriorLimitMask(VERTEX const& vertex, MASK& posM
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_CATMARK>::assignBoundaryLimitTangentMasks(VERTEX const& /* vertex */,
|
||||
Scheme<SCHEME_CATMARK>::assignCornerLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask) const {
|
||||
|
||||
int valence = vertex.GetNumEdges();
|
||||
|
||||
tan1Mask.SetNumVertexWeights(1);
|
||||
tan1Mask.SetNumEdgeWeights(0);
|
||||
tan1Mask.SetNumEdgeWeights(valence);
|
||||
tan1Mask.SetNumFaceWeights(0);
|
||||
tan1Mask.SetFaceWeightsForFaceCenters(false);
|
||||
tan1Mask.VertexWeight(0) = 0.0f;
|
||||
|
||||
tan2Mask.SetNumVertexWeights(1);
|
||||
tan2Mask.SetNumEdgeWeights(0);
|
||||
tan2Mask.SetNumEdgeWeights(valence);
|
||||
tan2Mask.SetNumFaceWeights(0);
|
||||
tan2Mask.SetFaceWeightsForFaceCenters(false);
|
||||
tan2Mask.VertexWeight(0) = 0.0f;
|
||||
|
||||
// Should be at least 2 edges -- be sure to clear weights for any more:
|
||||
tan1Mask.VertexWeight(0) = -1.0f;
|
||||
tan1Mask.EdgeWeight(0) = 1.0f;
|
||||
tan1Mask.EdgeWeight(1) = 0.0f;
|
||||
|
||||
tan2Mask.VertexWeight(0) = -1.0f;
|
||||
tan2Mask.EdgeWeight(0) = 0.0f;
|
||||
tan2Mask.EdgeWeight(1) = 1.0f;
|
||||
|
||||
for (int i = 2; i < valence; ++i) {
|
||||
tan1Mask.EdgeWeight(i) = 0.0f;
|
||||
tan2Mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_CATMARK>::assignInteriorLimitTangentMasks(VERTEX const& vertex,
|
||||
Scheme<SCHEME_CATMARK>::assignCreaseLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask, int const creaseEnds[2]) const {
|
||||
|
||||
int valence = vertex.GetNumEdges();
|
||||
|
||||
tan1Mask.SetNumVertexWeights(1);
|
||||
tan1Mask.SetNumEdgeWeights(valence);
|
||||
tan1Mask.SetNumFaceWeights(0);
|
||||
tan1Mask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
tan2Mask.SetNumVertexWeights(1);
|
||||
tan2Mask.SetNumEdgeWeights(valence);
|
||||
tan2Mask.SetNumFaceWeights(0);
|
||||
tan2Mask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
// Specialize for the regular (boundary) case:
|
||||
bool isRegular = (vertex.GetNumEdges() == 3);
|
||||
if (isRegular) {
|
||||
tan1Mask.VertexWeight(0) = 0.0f;
|
||||
tan1Mask.EdgeWeight(0) = 1.0f;
|
||||
tan1Mask.EdgeWeight(1) = 0.0f;
|
||||
tan1Mask.EdgeWeight(2) = -1.0f;
|
||||
|
||||
tan2Mask.VertexWeight(0) = -1.0f;
|
||||
tan2Mask.EdgeWeight(0) = 0.0f;
|
||||
tan2Mask.EdgeWeight(1) = 1.0f;
|
||||
tan2Mask.EdgeWeight(2) = 0.0f;
|
||||
} else {
|
||||
// First, the tangent along the crease:
|
||||
tan1Mask.VertexWeight(0) = 0.0f;
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
tan1Mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
tan1Mask.EdgeWeight(creaseEnds[0]) = 1.0f;
|
||||
tan1Mask.EdgeWeight(creaseEnds[1]) = -1.0f;
|
||||
|
||||
// Second, the tangent across the interior faces:
|
||||
// - just using an interior edge for now
|
||||
// - ultimately need regular and extra-ordinary cases here:
|
||||
//
|
||||
tan2Mask.VertexWeight(0) = -1.0f;
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
tan2Mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
tan2Mask.EdgeWeight((creaseEnds[0] + creaseEnds[1]) >> 1) = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_CATMARK>::assignSmoothLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask) const {
|
||||
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
@ -165,6 +165,10 @@ public:
|
||||
float const* incidentEdgeSharpness,
|
||||
float const* childEdgesSharpness) const;
|
||||
|
||||
void GetSharpEdgePairOfCrease(float const * incidentEdgeSharpness,
|
||||
int incidentEdgeCount,
|
||||
int sharpEdgePair[2]) const;
|
||||
|
||||
// Would these really help? Maybe only need Rules for the vertex-vertex case...
|
||||
//
|
||||
// Rule DetermineEdgeVertexRule(float parentEdgeSharpness) const;
|
||||
@ -220,6 +224,20 @@ Crease::SubdivideVertexSharpness(float vertexSharpness) const {
|
||||
return decrementSharpness(vertexSharpness);
|
||||
}
|
||||
|
||||
inline void
|
||||
Crease::GetSharpEdgePairOfCrease(float const * incidentEdgeSharpness, int incidentEdgeCount,
|
||||
int sharpEdgePair[2]) const {
|
||||
|
||||
// Only to be called when a crease is present at a vertex -- exactly two sharp
|
||||
// edges are expected here:
|
||||
//
|
||||
sharpEdgePair[0] = 0;
|
||||
while (IsSmooth(incidentEdgeSharpness[sharpEdgePair[0]])) ++ sharpEdgePair[0];
|
||||
|
||||
sharpEdgePair[1] = incidentEdgeCount - 1;
|
||||
while (IsSmooth(incidentEdgeSharpness[sharpEdgePair[1]])) -- sharpEdgePair[1];
|
||||
}
|
||||
|
||||
} // end namespace sdc
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -151,8 +151,8 @@ Scheme<SCHEME_LOOP>::assignCornerMaskForVertex(VERTEX const&, MASK& mask) const
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_LOOP>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& mask, float const edgeSharpness[]) const
|
||||
{
|
||||
Scheme<SCHEME_LOOP>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& mask,
|
||||
int const creaseEnds[2]) const {
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
||||
int valence = vertex.GetNumEdges();
|
||||
@ -166,10 +166,11 @@ Scheme<SCHEME_LOOP>::assignCreaseMaskForVertex(VERTEX const& vertex, MASK& mask,
|
||||
Weight eWeight = 0.125f;
|
||||
|
||||
mask.VertexWeight(0) = vWeight;
|
||||
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
mask.EdgeWeight(i) = (edgeSharpness[i] > 0.0f) ? eWeight : 0.0f;
|
||||
mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
mask.EdgeWeight(creaseEnds[0]) = eWeight;
|
||||
mask.EdgeWeight(creaseEnds[1]) = eWeight;
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -215,7 +216,21 @@ Scheme<SCHEME_LOOP>::assignSmoothMaskForVertex(VERTEX const& vertex, MASK& mask)
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_LOOP>::assignBoundaryLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
Scheme<SCHEME_LOOP>::assignCornerLimitMask(VERTEX const& /* vertex */, MASK& posMask) const {
|
||||
|
||||
posMask.SetNumVertexWeights(1);
|
||||
posMask.SetNumEdgeWeights(0);
|
||||
posMask.SetNumFaceWeights(0);
|
||||
posMask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
posMask.VertexWeight(0) = 1.0f;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_LOOP>::assignCreaseLimitMask(VERTEX const& vertex, MASK& posMask,
|
||||
int const creaseEnds[2]) const {
|
||||
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
||||
@ -226,21 +241,32 @@ Scheme<SCHEME_LOOP>::assignBoundaryLimitMask(VERTEX const& vertex, MASK& posMask
|
||||
posMask.SetNumFaceWeights(0);
|
||||
posMask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
//
|
||||
// The refinement mask for a crease vertex is (1/8, 3/4, 1/8) and for a crease
|
||||
// edge is (1/2, 1/2) -- producing a uniform B-spline curve along the crease
|
||||
// (boundary) whether the vertex or its crease is regular or not. The limit
|
||||
// mask is therefore (1/6, 2/3, 1/6) for ALL cases.
|
||||
//
|
||||
// An alternative limit mask (1/5, 3/5, 1/5) is often published for use either
|
||||
// for irregular crease vertices or for all crease/boundary vertices, but this
|
||||
// is based on an alternate refinement mask for the edge -- (3/8, 5/8) versus
|
||||
// the usual (1/2, 1/2) -- and will not produce the B-spline curve desired.
|
||||
//
|
||||
Weight vWeight = 4.0f / 6.0f;
|
||||
Weight eWeight = 1.0f / 6.0f;
|
||||
|
||||
posMask.VertexWeight(0) = vWeight;
|
||||
posMask.EdgeWeight(0) = eWeight;
|
||||
for (int i = 1; i < valence - 1; ++i) {
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
posMask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
posMask.EdgeWeight(valence - 1) = eWeight;
|
||||
posMask.EdgeWeight(creaseEnds[0]) = eWeight;
|
||||
posMask.EdgeWeight(creaseEnds[1]) = eWeight;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_LOOP>::assignInteriorLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
Scheme<SCHEME_LOOP>::assignSmoothLimitMask(VERTEX const& vertex, MASK& posMask) const {
|
||||
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
||||
@ -275,31 +301,221 @@ Scheme<SCHEME_LOOP>::assignInteriorLimitMask(VERTEX const& vertex, MASK& posMask
|
||||
//
|
||||
// Limit masks for tangents:
|
||||
//
|
||||
// A note on tangent magnitudes:
|
||||
//
|
||||
// Several formulae exist for limit tangents at a vertex to accomodate the
|
||||
// different topological configurations around the vertex. While these produce
|
||||
// the desired direction, there is inconsistency in the resulting magnitudes.
|
||||
// Ideally a regular mesh of uniformly shaped triangles with similar edge lengths
|
||||
// should produce tangents of similar magnitudes throughout -- including corners
|
||||
// and boundaries. So some of the common formulae for these are adjusted with
|
||||
// scale factors.
|
||||
//
|
||||
// For uses where magnitude does not matter, this scaling should be irrelevant.
|
||||
// But just as with patches, where the magnitudes of partial derivates are
|
||||
// consistent between similar patches, the magnitudes of limit tangents should
|
||||
// also be similar.
|
||||
//
|
||||
// The reference tangents, in terms of magnitudes, are those produced by the
|
||||
// limit tangent mask for smooth interior vertices, for which well established
|
||||
// sin/cos formulae apply -- these remain unscaled. Formulae for the other
|
||||
// crease/boundary, corner tangents and irregular cases are scaled to be more
|
||||
// consistent with these.
|
||||
//
|
||||
// The crease/boundary tangents for the regular case can be viewed as derived
|
||||
// from the smooth interior masks with two "phantom" points extrapolated across
|
||||
// the regular boundary:
|
||||
//
|
||||
// v3 v2
|
||||
// X - - - - - X
|
||||
// / \ / \
|
||||
// / \ / \
|
||||
// v4 X - - - - - X - - - - - X v1
|
||||
// . . 0 . .
|
||||
// . . . .
|
||||
// . . . .
|
||||
// (v5) (v6)
|
||||
//
|
||||
// where v5 = v0 + (v4 - v3) and v6 = v0 + v1 - v2.
|
||||
//
|
||||
// When the standard limit tangent mask is applied, the cosines of increments
|
||||
// of pi/3 gives us coefficients that are mutliples of 1/2, leading to the first
|
||||
// tangent T1 = 3/2 * (v1 - v4), rather than the widely used T1 = v1 - v4. So
|
||||
// this scale factor of 3/2 is applied to insure tangents along the boundaries
|
||||
// are of similar magnitude as tangents in the immediate interior (which may be
|
||||
// parallel).
|
||||
//
|
||||
// Tangents at corners are essentially a form of boundary tangent, and so its
|
||||
// simple difference formula is scaled to be consistent with adjoining boundary
|
||||
// tangents -- not just with the 3/2 factor from above, but with an additional
|
||||
// 2.0 to compensate for the fact that the difference of only side of the vertex
|
||||
// is considered here. The resulting scale factor of 3.0 for the regular corner
|
||||
// is what similarly arises by extrapolating an interior region around the
|
||||
// vertex and using the interior mask for the first tangent.
|
||||
//
|
||||
// The cross-tangent formula for the regular crease/boundary is similarly found
|
||||
// from the above construction of the boundary, but the commonly used weights of
|
||||
// +/- 1 and 2 result from omitting the common factor of sqrt(3)/2 (arising from
|
||||
// the sines of increments of pi/3). With that scale factor close to one, it has
|
||||
// less impact than the irregular cases, which are analogous to corner tangents
|
||||
// in that differences on only one side of the vertex are considered. While a
|
||||
// scaling of 3.0 is similarly understandable for the valence 2 and 3 cases, it is
|
||||
// less obvious in the irregular formula for valence > 4, but similarly effective.
|
||||
//
|
||||
// The end result of these adjustments should be a set of limit tangents that are
|
||||
// of similar magnitude over a regular mesh including boundaries and corners.
|
||||
//
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_LOOP>::assignBoundaryLimitTangentMasks(VERTEX const& /* vertex */,
|
||||
Scheme<SCHEME_LOOP>::assignCornerLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask) const {
|
||||
|
||||
// Need to dig up formulae for this case...
|
||||
int valence = vertex.GetNumEdges();
|
||||
|
||||
tan1Mask.SetNumVertexWeights(1);
|
||||
tan1Mask.SetNumEdgeWeights(0);
|
||||
tan1Mask.SetNumEdgeWeights(valence);
|
||||
tan1Mask.SetNumFaceWeights(0);
|
||||
tan1Mask.SetFaceWeightsForFaceCenters(false);
|
||||
tan1Mask.VertexWeight(0) = 0.0f;
|
||||
|
||||
tan2Mask.SetNumVertexWeights(1);
|
||||
tan2Mask.SetNumEdgeWeights(0);
|
||||
tan2Mask.SetNumEdgeWeights(valence);
|
||||
tan2Mask.SetNumFaceWeights(0);
|
||||
tan2Mask.SetFaceWeightsForFaceCenters(false);
|
||||
tan2Mask.VertexWeight(0) = 0.0f;
|
||||
|
||||
// See note above regarding scale factor of 3.0:
|
||||
tan1Mask.VertexWeight(0) = -3.0f;
|
||||
tan1Mask.EdgeWeight(0) = 3.0f;
|
||||
tan1Mask.EdgeWeight(1) = 0.0f;
|
||||
|
||||
tan2Mask.VertexWeight(0) = -3.0f;
|
||||
tan2Mask.EdgeWeight(0) = 0.0f;
|
||||
tan2Mask.EdgeWeight(1) = 3.0f;
|
||||
|
||||
// Should be at least 2 edges -- be sure to clear weights for any more:
|
||||
for (int i = 2; i < valence; ++i) {
|
||||
tan1Mask.EdgeWeight(i) = 0.0f;
|
||||
tan2Mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_LOOP>::assignInteriorLimitTangentMasks(VERTEX const& vertex,
|
||||
Scheme<SCHEME_LOOP>::assignCreaseLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask, int const creaseEnds[2]) const {
|
||||
|
||||
typedef typename MASK::Weight Weight;
|
||||
|
||||
//
|
||||
// First, the tangent along the crease:
|
||||
// The first crease edge is considered the "leading" edge of the span
|
||||
// of surface for which we are evaluating tangents and the second edge the
|
||||
// "trailing edge". By convention, the tangent along the crease is oriented
|
||||
// in the direction of the leading edge.
|
||||
//
|
||||
int valence = vertex.GetNumEdges();
|
||||
|
||||
tan1Mask.SetNumVertexWeights(1);
|
||||
tan1Mask.SetNumEdgeWeights(valence);
|
||||
tan1Mask.SetNumFaceWeights(0);
|
||||
tan1Mask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
tan1Mask.VertexWeight(0) = 0.0f;
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
tan1Mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
|
||||
// See the note above regarding scale factor of 1.5:
|
||||
tan1Mask.EdgeWeight(creaseEnds[0]) = 1.5f;
|
||||
tan1Mask.EdgeWeight(creaseEnds[1]) = -1.5f;
|
||||
|
||||
//
|
||||
// Second, the tangent across the interior faces:
|
||||
// Note this is ambigous for an interior vertex. We currently return
|
||||
// the tangent for the surface in the counter-clockwise span between the
|
||||
// leading and trailing edges that form the crease. Given the expected
|
||||
// computation of a surface normal as Tan1 X Tan2, this tangent should be
|
||||
// oriented "inward" from the crease/boundary -- across the surface rather
|
||||
// than outward and away from it.
|
||||
//
|
||||
// There is inconsistency in the orientation of this tangent in commonly
|
||||
// published results: the general formula provided for arbitrary valence
|
||||
// has the tangent pointing across the crease and "outward" from the surface,
|
||||
// while the special cases for regular valence and lower have the tangent
|
||||
// pointing across the surface and "inward" from the crease. So if we are
|
||||
// to consistently orient the first tangent along the crease, regardless of
|
||||
// the interior topology, we have to correct this. With the first tangent
|
||||
// following the direction of the leading crease edge, we want the second
|
||||
// tangent pointing inward/across the surface -- so we flip the result of
|
||||
// the general formula.
|
||||
//
|
||||
tan2Mask.SetNumVertexWeights(1);
|
||||
tan2Mask.SetNumEdgeWeights(valence);
|
||||
tan2Mask.SetNumFaceWeights(0);
|
||||
tan2Mask.SetFaceWeightsForFaceCenters(false);
|
||||
|
||||
for (int i = 0; i < creaseEnds[0]; ++i) {
|
||||
tan2Mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
int interiorEdgeCount = creaseEnds[1] - creaseEnds[0] - 1;
|
||||
if (interiorEdgeCount == 2) {
|
||||
// See note above regarding scale factor of (sin(60 degs) == sqrt(3)/2:
|
||||
|
||||
static Weight const Root3 = (Weight) 1.73205080756887729352f;
|
||||
static Weight const Root3by2 = (Weight) (Root3 * 0.5);
|
||||
|
||||
tan2Mask.VertexWeight(0) = -Root3;
|
||||
|
||||
tan2Mask.EdgeWeight(creaseEnds[0]) = -Root3by2;
|
||||
tan2Mask.EdgeWeight(creaseEnds[1]) = -Root3by2;
|
||||
|
||||
tan2Mask.EdgeWeight(creaseEnds[0] + 1) = Root3;
|
||||
tan2Mask.EdgeWeight(creaseEnds[0] + 2) = Root3;
|
||||
} else if (interiorEdgeCount > 2) {
|
||||
// See notes above regarding scale factor of -3.0 (-1 for orientation,
|
||||
// 2.0 for considering the region as a half-disk, and 1.5 in keeping
|
||||
// with the crease tangent):
|
||||
|
||||
double theta = M_PI / (interiorEdgeCount + 1);
|
||||
|
||||
Weight cWeight = -3.0f * std::sin(theta);
|
||||
Weight eWeightCoeff = -3.0f * (2.0f * std::cos(theta) - 2.0f);
|
||||
|
||||
tan2Mask.VertexWeight(0) = 0.0f;
|
||||
|
||||
tan2Mask.EdgeWeight(creaseEnds[0]) = cWeight;
|
||||
tan2Mask.EdgeWeight(creaseEnds[1]) = cWeight;
|
||||
|
||||
for (int i = 1; i <= interiorEdgeCount; ++i) {
|
||||
tan2Mask.EdgeWeight(creaseEnds[0] + i) = eWeightCoeff * std::sin(i * theta);
|
||||
}
|
||||
} else if (interiorEdgeCount == 1) {
|
||||
// See notes above regarding scale factor of 3.0:
|
||||
|
||||
tan2Mask.VertexWeight(0) = -3.0f;
|
||||
|
||||
tan2Mask.EdgeWeight(creaseEnds[0]) = 0.0f;
|
||||
tan2Mask.EdgeWeight(creaseEnds[1]) = 0.0f;
|
||||
|
||||
tan2Mask.EdgeWeight(creaseEnds[0] + 1) = 3.0f;
|
||||
} else {
|
||||
// See notes above regarding scale factor of 3.0:
|
||||
|
||||
tan2Mask.VertexWeight(0) = -6.0f;
|
||||
|
||||
tan2Mask.EdgeWeight(creaseEnds[0]) = 3.0f;
|
||||
tan2Mask.EdgeWeight(creaseEnds[1]) = 3.0f;
|
||||
}
|
||||
for (int i = creaseEnds[1] + 1; i < valence; ++i) {
|
||||
tan2Mask.EdgeWeight(i) = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename VERTEX, typename MASK>
|
||||
inline void
|
||||
Scheme<SCHEME_LOOP>::assignSmoothLimitTangentMasks(VERTEX const& vertex,
|
||||
MASK& tan1Mask, MASK& tan2Mask) const {
|
||||
|
||||
typedef typename MASK::Weight Weight;
|
||||
@ -320,11 +536,29 @@ Scheme<SCHEME_LOOP>::assignInteriorLimitTangentMasks(VERTEX const& vertex,
|
||||
tan1Mask.VertexWeight(0) = 0.0f;
|
||||
tan2Mask.VertexWeight(0) = 0.0f;
|
||||
|
||||
Weight alpha = (Weight) (2.0f * M_PI / valence);
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
double alphaI = alpha * i;
|
||||
tan1Mask.EdgeWeight(i) = std::cos(alphaI);
|
||||
tan2Mask.EdgeWeight(i) = std::sin(alphaI);
|
||||
if (valence == 6) {
|
||||
static Weight const Root3by2 = (Weight)(0.5f * 1.73205080756887729352f);
|
||||
|
||||
tan1Mask.EdgeWeight(0) = 1.0f;
|
||||
tan1Mask.EdgeWeight(1) = 0.5f;
|
||||
tan1Mask.EdgeWeight(2) = -0.5f;
|
||||
tan1Mask.EdgeWeight(3) = -1.0f;
|
||||
tan1Mask.EdgeWeight(4) = -0.5f;
|
||||
tan1Mask.EdgeWeight(5) = 0.5f;
|
||||
|
||||
tan2Mask.EdgeWeight(0) = 0.0f;
|
||||
tan2Mask.EdgeWeight(1) = Root3by2;
|
||||
tan2Mask.EdgeWeight(2) = Root3by2;
|
||||
tan2Mask.EdgeWeight(3) = 0.0f;
|
||||
tan2Mask.EdgeWeight(4) = -Root3by2;
|
||||
tan2Mask.EdgeWeight(5) = -Root3by2;
|
||||
} else {
|
||||
Weight alpha = (Weight) (2.0f * M_PI / valence);
|
||||
for (int i = 0; i < valence; ++i) {
|
||||
double alphaI = alpha * i;
|
||||
tan1Mask.EdgeWeight(i) = std::cos(alphaI);
|
||||
tan2Mask.EdgeWeight(i) = std::sin(alphaI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,21 +115,22 @@ public:
|
||||
Crease::Rule childRule = Crease::RULE_UNKNOWN) const;
|
||||
|
||||
///
|
||||
/// \brief IN PROGRESS -- NOT YET FULLY FUNCTIONAL...
|
||||
///
|
||||
/// Masks for limit points and tangents -- note that these require the vertex be
|
||||
/// suitably isolated such that its limit is well-defined.
|
||||
///
|
||||
/// These are stubs that are still being completed. The position masks are now
|
||||
/// supported but tangent masks need work.
|
||||
/// \brief Limit masks for vertices -- position and tangents
|
||||
/// These presume that a vertex is suitably isolated for its limit to be well-defined
|
||||
/// and, unlike the refinement masks, the subdivision Rule for the vertex (presumably at
|
||||
/// its last level of refinement) is required rather than being optional. In the
|
||||
/// presence of semi-sharp creasing that has not decayed to zero, the limit is unknown
|
||||
/// and it is up to the caller to provide the Rule for either a smooth or sharp limit in
|
||||
/// such cases.
|
||||
///
|
||||
template <typename VERTEX, typename MASK>
|
||||
void ComputeVertexLimitMask(VERTEX const& vertexNeighborhood, MASK& positionMask) const;
|
||||
void ComputeVertexLimitMask(VERTEX const& vertexNeighborhood, MASK& positionMask,
|
||||
Crease::Rule vertexRule) const;
|
||||
|
||||
template <typename VERTEX, typename MASK>
|
||||
void ComputeVertexLimitMask(VERTEX const& vertexNeighborhood, MASK& positionMask,
|
||||
MASK& tangent1Mask,
|
||||
MASK& tangent2Mask) const;
|
||||
MASK& tangent1Mask, MASK& tangent2Mask,
|
||||
Crease::Rule vertexRule) const;
|
||||
|
||||
//
|
||||
// Static methods defining traits/properties of the scheme:
|
||||
@ -155,22 +156,26 @@ protected:
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignCornerMaskForVertex(VERTEX const& edge, MASK& mask) const;
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignCreaseMaskForVertex(VERTEX const& edge, MASK& mask, float const sharpness[]) const;
|
||||
void assignCreaseMaskForVertex(VERTEX const& edge, MASK& mask, int const creaseEnds[2]) const;
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignSmoothMaskForVertex(VERTEX const& edge, MASK& mask) const;
|
||||
|
||||
//
|
||||
// Limit masks for position and tangents -- boundary and interior cases for both:
|
||||
// Limit masks for position and tangents at vertices -- three cases for each:
|
||||
//
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignBoundaryLimitMask(VERTEX const& vertex, MASK& pos) const;
|
||||
void assignCornerLimitMask(VERTEX const& vertex, MASK& pos) const;
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignInteriorLimitMask(VERTEX const& vertex, MASK& pos) const;
|
||||
void assignCreaseLimitMask(VERTEX const& vertex, MASK& pos, int const creaseEnds[2]) const;
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignSmoothLimitMask(VERTEX const& vertex, MASK& pos) const;
|
||||
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignBoundaryLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2) const;
|
||||
void assignCornerLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2) const;
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignInteriorLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2) const;
|
||||
void assignCreaseLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2, int const creaseEnds[2]) const;
|
||||
template <typename VERTEX, typename MASK>
|
||||
void assignSmoothLimitTangentMasks(VERTEX const& vertex, MASK& tan1, MASK& tan2) const;
|
||||
|
||||
private:
|
||||
Options _options;
|
||||
@ -521,15 +526,17 @@ Scheme<SCHEME>::ComputeVertexVertexMask(VERTEX const& vertex,
|
||||
pEdgeSharpness = vertex.GetSharpnessPerEdge(pEdgeSharpnessBuffer);
|
||||
|
||||
if (pRule == Crease::RULE_UNKNOWN) {
|
||||
Crease crease(_options);
|
||||
pRule = crease.DetermineVertexVertexRule(pVertexSharpness, valence, pEdgeSharpness);
|
||||
pRule = Crease(_options).DetermineVertexVertexRule(pVertexSharpness, valence, pEdgeSharpness);
|
||||
}
|
||||
}
|
||||
if ((pRule == Crease::RULE_SMOOTH) || (pRule == Crease::RULE_DART)) {
|
||||
assignSmoothMaskForVertex(vertex, mask);
|
||||
return; // As done on entry, we can return immediately if parent is Smooth/Dart
|
||||
} else if (pRule == Crease::RULE_CREASE) {
|
||||
assignCreaseMaskForVertex(vertex, mask, pEdgeSharpness);
|
||||
int creaseEnds[2];
|
||||
Crease(_options).GetSharpEdgePairOfCrease(pEdgeSharpness, valence, creaseEnds);
|
||||
|
||||
assignCreaseMaskForVertex(vertex, mask, creaseEnds);
|
||||
} else {
|
||||
assignCornerMaskForVertex(vertex, mask);
|
||||
}
|
||||
@ -561,7 +568,10 @@ Scheme<SCHEME>::ComputeVertexVertexMask(VERTEX const& vertex,
|
||||
if ((cRule == Crease::RULE_SMOOTH) || (cRule == Crease::RULE_DART)) {
|
||||
assignSmoothMaskForVertex(vertex, cMask);
|
||||
} else if (cRule == Crease::RULE_CREASE) {
|
||||
assignCreaseMaskForVertex(vertex, cMask, cEdgeSharpness);
|
||||
int creaseEnds[2];
|
||||
Crease(_options).GetSharpEdgePairOfCrease(cEdgeSharpness, valence, creaseEnds);
|
||||
|
||||
assignCreaseMaskForVertex(vertex, cMask, creaseEnds);
|
||||
} else {
|
||||
assignCornerMaskForVertex(vertex, cMask);
|
||||
}
|
||||
@ -580,15 +590,21 @@ template <SchemeType SCHEME>
|
||||
template <typename VERTEX, typename MASK>
|
||||
void
|
||||
Scheme<SCHEME>::ComputeVertexLimitMask(VERTEX const& vertex,
|
||||
MASK& mask) const {
|
||||
MASK& mask,
|
||||
Crease::Rule rule) const {
|
||||
|
||||
if (vertex.GetNumFaces() == vertex.GetNumEdges()) {
|
||||
assignInteriorLimitMask(vertex, mask);
|
||||
} else if ((vertex.GetNumFaces() == 1) &&
|
||||
(_options.GetVtxBoundaryInterpolation() == Sdc::Options::VTX_BOUNDARY_EDGE_AND_CORNER)) {
|
||||
assignCornerMaskForVertex(vertex, mask);
|
||||
if ((rule == Crease::RULE_SMOOTH) || (rule == Crease::RULE_DART)) {
|
||||
assignSmoothLimitMask(vertex, mask);
|
||||
} else if (rule == Crease::RULE_CREASE) {
|
||||
float * edgeSharpness = (float *)alloca(vertex.GetNumEdges() * sizeof(float));
|
||||
vertex.GetSharpnessPerEdge(edgeSharpness);
|
||||
|
||||
int creaseEnds[2];
|
||||
Crease(_options).GetSharpEdgePairOfCrease(edgeSharpness, vertex.GetNumEdges(), creaseEnds);
|
||||
|
||||
assignCreaseLimitMask(vertex, mask, creaseEnds);
|
||||
} else {
|
||||
assignBoundaryLimitMask(vertex, mask);
|
||||
assignCornerLimitMask(vertex, mask);
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,14 +614,24 @@ void
|
||||
Scheme<SCHEME>::ComputeVertexLimitMask(VERTEX const& vertex,
|
||||
MASK& posMask,
|
||||
MASK& tan1Mask,
|
||||
MASK& tan2Mask) const {
|
||||
MASK& tan2Mask,
|
||||
Crease::Rule rule) const {
|
||||
|
||||
if (vertex.GetNumFaces() == vertex.GetNumEdges()) {
|
||||
assignInteriorLimitMask(vertex, posMask);
|
||||
assignInteriorLimitTangentMasks(vertex, tan1Mask, tan2Mask);
|
||||
if ((rule == Crease::RULE_SMOOTH) || (rule == Crease::RULE_DART)) {
|
||||
assignSmoothLimitMask(vertex, posMask);
|
||||
assignSmoothLimitTangentMasks(vertex, tan1Mask, tan2Mask);
|
||||
} else if (rule == Crease::RULE_CREASE) {
|
||||
float * edgeSharpness = (float *)alloca(vertex.GetNumEdges() * sizeof(float));
|
||||
vertex.GetSharpnessPerEdge(edgeSharpness);
|
||||
|
||||
int creaseEnds[2];
|
||||
Crease(_options).GetSharpEdgePairOfCrease(edgeSharpness, vertex.GetNumEdges(), creaseEnds);
|
||||
|
||||
assignCreaseLimitMask(vertex, posMask, creaseEnds);
|
||||
assignCreaseLimitTangentMasks(vertex, tan1Mask, tan2Mask, creaseEnds);
|
||||
} else {
|
||||
assignBoundaryLimitMask(vertex, posMask);
|
||||
assignBoundaryLimitTangentMasks(vertex, tan1Mask, tan2Mask);
|
||||
assignCornerLimitMask(vertex, posMask);
|
||||
assignCornerLimitTangentMasks(vertex, tan1Mask, tan2Mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user