24 #ifndef OPENSUBDIV3_SDC_SCHEME_H
25 #define OPENSUBDIV3_SDC_SCHEME_H
27 #include "../version.h"
29 #include "../sdc/types.h"
30 #include "../sdc/options.h"
31 #include "../sdc/crease.h"
37 namespace OpenSubdiv {
38 namespace OPENSUBDIV_VERSION {
65 template <SchemeType SCHEME_TYPE>
80 template <
typename FACE,
typename MASK>
98 template <
typename EDGE,
typename MASK>
112 template <
typename VERTEX,
typename MASK>
141 template <
typename VERTEX,
typename MASK>
145 template <
typename VERTEX,
typename MASK>
147 MASK& tangent1Mask, MASK& tangent2Mask,
166 template <
typename EDGE,
typename MASK>
168 template <
typename EDGE,
typename MASK>
171 template <
typename VERTEX,
typename MASK>
173 template <
typename VERTEX,
typename MASK>
175 template <
typename VERTEX,
typename MASK>
181 template <
typename VERTEX,
typename MASK>
183 template <
typename VERTEX,
typename MASK>
185 template <
typename VERTEX,
typename MASK>
188 template <
typename VERTEX,
typename MASK>
190 template <
typename VERTEX,
typename MASK>
192 template <
typename VERTEX,
typename MASK>
208 template <
typename WEIGHT>
247 template <
typename USER_MASK>
259 dst.VertexWeight(0) = dstCoeff * dst.VertexWeight(0) + thisCoeff * this->
VertexWeight(0);
262 if (edgeWeightCount) {
263 if (dst.GetNumEdgeWeights() == 0) {
264 dst.SetNumEdgeWeights(edgeWeightCount);
265 for (
int i = 0; i < edgeWeightCount; ++i) {
266 dst.EdgeWeight(i) = thisCoeff * this->
EdgeWeight(i);
269 for (
int i = 0; i < edgeWeightCount; ++i) {
270 dst.EdgeWeight(i) = dstCoeff * dst.EdgeWeight(i) + thisCoeff * this->
EdgeWeight(i);
276 if (faceWeightCount) {
281 if (dst.GetNumFaceWeights() == 0) {
282 dst.SetNumFaceWeights(faceWeightCount);
285 for (
int i = 0; i < faceWeightCount; ++i) {
286 dst.FaceWeight(i) = thisCoeff * this->
FaceWeight(i);
291 for (
int i = 0; i < faceWeightCount; ++i) {
292 dst.FaceWeight(i) = dstCoeff * dst.FaceWeight(i) + thisCoeff * this->
FaceWeight(i);
305 bool _fWeightsForCenters;
314 template <SchemeType SCHEME>
315 template <
typename EDGE,
typename MASK>
319 mask.SetNumVertexWeights(2);
320 mask.SetNumEdgeWeights(0);
321 mask.SetNumFaceWeights(0);
322 mask.SetFaceWeightsForFaceCenters(
false);
324 mask.VertexWeight(0) = 0.5f;
325 mask.VertexWeight(1) = 0.5f;
328 template <SchemeType SCHEME>
329 template <
typename VERTEX,
typename MASK>
333 mask.SetNumVertexWeights(1);
334 mask.SetNumEdgeWeights(0);
335 mask.SetNumFaceWeights(0);
336 mask.SetFaceWeightsForFaceCenters(
false);
338 mask.VertexWeight(0) = 1.0f;
345 template <SchemeType SCHEME>
346 template <
typename FACE,
typename MASK>
350 int vertCount = face.GetNumVertices();
352 mask.SetNumVertexWeights(vertCount);
353 mask.SetNumEdgeWeights(0);
354 mask.SetNumFaceWeights(0);
355 mask.SetFaceWeightsForFaceCenters(
false);
357 typename MASK::Weight vWeight = 1.0f / (
typename MASK::Weight) vertCount;
358 for (
int i = 0; i < vertCount; ++i) {
359 mask.VertexWeight(i) = vWeight;
389 template <SchemeType SCHEME>
390 template <
typename EDGE,
typename MASK>
404 assignSmoothMaskForEdge(edge, mask);
408 assignCreaseMaskForEdge(edge, mask);
426 bool childIsCrease =
false;
429 childIsCrease =
true;
430 }
else if (edge.GetSharpness() >= 1.0f) {
432 childIsCrease =
true;
435 childIsCrease =
false;
438 float cEdgeSharpness[2];
439 edge.GetChildSharpnesses(crease, cEdgeSharpness);
440 childIsCrease = (cEdgeSharpness[0] > 0.0f) && (cEdgeSharpness[1] > 0.0f);
443 assignCreaseMaskForEdge(edge, mask);
457 assignSmoothMaskForEdge(edge, mask);
459 typedef typename MASK::Weight Weight;
461 Weight pWeight = edge.GetSharpness();
462 Weight cWeight = 1.0f - pWeight;
464 mask.VertexWeight(0) = pWeight * 0.5f + cWeight * mask.VertexWeight(0);
465 mask.VertexWeight(1) = pWeight * 0.5f + cWeight * mask.VertexWeight(1);
467 int faceCount = mask.GetNumFaceWeights();
468 for (
int i = 0; i < faceCount; ++i) {
469 mask.FaceWeight(i) *= cWeight;
509 template <SchemeType SCHEME>
510 template <
typename VERTEX,
typename MASK>
519 assignSmoothMaskForVertex(vertex, mask);
526 int valence = vertex.GetNumEdges();
532 float * pEdgeSharpnessBuffer = (
float *)alloca(valence*
sizeof(
float)),
533 * pEdgeSharpness = 0,
534 pVertexSharpness = 0.0f;
539 if (requireParentSharpness) {
540 pVertexSharpness = vertex.GetSharpness();
541 pEdgeSharpness = vertex.GetSharpnessPerEdge(pEdgeSharpnessBuffer);
548 assignSmoothMaskForVertex(vertex, mask);
554 assignCreaseMaskForVertex(vertex, mask, creaseEnds);
556 assignCornerMaskForVertex(vertex, mask);
558 if (cRule == pRule)
return;
565 float * cEdgeSharpnessBuffer = (
float *)alloca(valence*
sizeof(
float)),
566 * cEdgeSharpness = vertex.GetChildSharpnessPerEdge(crease, cEdgeSharpnessBuffer),
567 cVertexSharpness = vertex.GetChildSharpness(crease);
571 if (cRule == pRule)
return;
578 typedef typename MASK::Weight Weight;
580 Weight * cMaskWeights = (Weight *)alloca((1 + 2 * valence)*
sizeof(Weight));
581 LocalMask<Weight> cMask(cMaskWeights, cMaskWeights + 1, cMaskWeights + 1 + valence);
584 assignSmoothMaskForVertex(vertex, cMask);
589 assignCreaseMaskForVertex(vertex, cMask, creaseEnds);
591 assignCornerMaskForVertex(vertex, cMask);
595 valence, pEdgeSharpness, cEdgeSharpness);
596 Weight cWeight = 1.0f - pWeight;
604 template <SchemeType SCHEME>
605 template <
typename VERTEX,
typename MASK>
612 assignSmoothLimitMask(vertex, mask);
614 float * edgeSharpness = (
float *)alloca(vertex.GetNumEdges() *
sizeof(float));
615 vertex.GetSharpnessPerEdge(edgeSharpness);
620 assignCreaseLimitMask(vertex, mask, creaseEnds);
622 assignCornerLimitMask(vertex, mask);
626 template <SchemeType SCHEME>
627 template <
typename VERTEX,
typename MASK>
636 assignSmoothLimitMask(vertex, posMask);
637 assignSmoothLimitTangentMasks(vertex, tan1Mask, tan2Mask);
639 float * edgeSharpness = (
float *)alloca(vertex.GetNumEdges() *
sizeof(float));
640 vertex.GetSharpnessPerEdge(edgeSharpness);
645 assignCreaseLimitMask(vertex, posMask, creaseEnds);
646 assignCreaseLimitTangentMasks(vertex, tan1Mask, tan2Mask, creaseEnds);
648 assignCornerLimitMask(vertex, posMask);
649 assignCornerLimitTangentMasks(vertex, tan1Mask, tan2Mask);
657 using namespace OPENSUBDIV_VERSION;
void assignCreaseLimitMask(VERTEX const &vertex, MASK &pos, int const creaseEnds[2]) const
void SetOptions(const Options &newOptions)
Weight const & FaceWeight(int index) const
void assignCreaseMaskForVertex(VERTEX const &edge, MASK &mask, int const creaseEnds[2]) const
Scheme(Options const &options)
void ComputeEdgeVertexMask(EDGE const &edgeNeighborhood, MASK &edgeVertexMask, Crease::Rule parentRule=Crease::RULE_UNKNOWN, Crease::Rule childRule=Crease::RULE_UNKNOWN) const
Edge-vertex masks If known, the Rule for the edge and/or the derived vertex can be specified to accel...
bool AreFaceWeightsForFaceCenters() const
void ComputeVertexLimitMask(VERTEX const &vertexNeighborhood, MASK &positionMask, Crease::Rule vertexRule) const
Limit masks for vertices – position and tangents These presume that a vertex is suitably isolated for...
Split
Enumerated type for all face splitting schemes.
Rule DetermineVertexVertexRule(float vertexSharpness, int incidentEdgeCount, float const *incidentEdgeSharpness) const
void assignSmoothLimitMask(VERTEX const &vertex, MASK &pos) const
static int GetRegularFaceSize()
Weight const & EdgeWeight(int index) const
void assignSmoothMaskForVertex(VERTEX const &edge, MASK &mask) const
void ComputeFaceVertexMask(FACE const &faceNeighborhood, MASK &faceVertexMask) const
Face-vertex masks - trivial for all current schemes.
static Split GetTopologicalSplitType()
static int GetRegularVertexValence()
int GetNumEdgeWeights() const
Types, constants and utilities related to semi-sharp creasing – whose implementation is independent o...
void assignCornerLimitMask(VERTEX const &vertex, MASK &pos) const
void SetNumEdgeWeights(int count)
void assignCornerLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
void assignSmoothLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2) const
int GetNumVertexWeights() const
All supported options applying to subdivision scheme.
float ComputeFractionalWeightAtVertex(float vertexSharpness, float childVertexSharpness, int incidentEdgeCount, float const *incidentEdgeSharpness, float const *childEdgesSharpness) const
Transitional weighting: When the rules applicable to a parent vertex and its child differ...
Weight & EdgeWeight(int index)
void GetSharpEdgePairOfCrease(float const *incidentEdgeSharpness, int incidentEdgeCount, int sharpEdgePair[2]) const
void SetNumFaceWeights(int count)
static int GetLocalNeighborhoodSize()
Weight & VertexWeight(int index)
Weight & FaceWeight(int index)
void assignCreaseMaskForEdge(EDGE const &edge, MASK &mask) const
Options GetOptions() const
void ComputeVertexVertexMask(VERTEX const &vertexNeighborhood, MASK &vertexVertexMask, Crease::Rule parentRule=Crease::RULE_UNKNOWN, Crease::Rule childRule=Crease::RULE_UNKNOWN) const
Vertex-vertex masks If known, a single Rule or pair of Rules can be specified (indicating a crease tr...
int GetNumFaceWeights() const
void SetFaceWeightsForFaceCenters(bool on)
void CombineVertexVertexMasks(Weight thisCoeff, Weight dstCoeff, USER_MASK &dst) const
void assignCornerMaskForVertex(VERTEX const &edge, MASK &mask) const
void assignSmoothMaskForEdge(EDGE const &edge, MASK &mask) const
void SetNumVertexWeights(int count)
LocalMask(Weight *v, Weight *e, Weight *f)
Scheme is a class template which provides all implementation for the subdivision schemes supported by...
void assignCreaseLimitTangentMasks(VERTEX const &vertex, MASK &tan1, MASK &tan2, int const creaseEnds[2]) const
Weight const & VertexWeight(int index) const