diff --git a/opensubdiv/sdc/crease.h b/opensubdiv/sdc/crease.h index 199d940a..a79a27a1 100644 --- a/opensubdiv/sdc/crease.h +++ b/opensubdiv/sdc/crease.h @@ -34,18 +34,18 @@ namespace OPENSUBDIV_VERSION { namespace Sdc { /// -/// \brief Types, constants and utilities related to semi-sharp creasing -- whose implementation is -/// independent of the subdivision scheme. +/// \brief Types, constants and utilities related to semi-sharp creasing -- whose implementation +/// is independent of the subdivision scheme. /// /// Crease is intended to be a light-weight, trivially constructed class that computes -/// crease-related properties. An instance of an Crease is defined with a set of options -/// that include current and future variations that will impact computations involving -/// sharpness values. +/// crease-related properties -- typically sharpness values and associated interpolation +/// weights. An instance of Crease is defined with a set of options that include current +/// and future variations that will impact computations involving sharpness values. /// -/// We do not to use Neighborhoods here as input. Since their sharpness values are potentially -/// not specified (and gathered on demand), and the methods here rely more on the sharpness -/// values and less on the topology, we choose to work directly with the sharpness values for -/// more flexibility. We also follow the trend of using primitive arrays in the interface. +/// The Crease methods do not use topological neighborhoods as input. The methods here +/// rely more on the sharpness values and less on the topology, so we choose to work directly +/// with the sharpness values. We also follow the trend of using primitive arrays in the +/// interface to encourage local gathering for re-use. /// /// Note on the need for and use of sharpness values: /// In general, mask queries rely on the sharpness values. The common case of a smooth @@ -60,13 +60,11 @@ namespace Sdc { /// class Crease { - public: - //@{ /// Constants and related queries of sharpness values: /// - static float const SHARPNESS_SMOOTH; // = 0.0f, do we really need this? + static float const SHARPNESS_SMOOTH; // = 0.0f, do we really need this? static float const SHARPNESS_INFINITE; // = 10.0f; static bool IsSmooth(float sharpness) { return sharpness <= SHARPNESS_SMOOTH; } @@ -78,7 +76,8 @@ public: /// /// Enum for the types of subdivision rules applied based on sharpness values (note these /// correspond to Hbr's vertex "mask"). The values are assigned to bit positions as it is - /// useful to OR the corners of faces to quickly inspect its applicable rules. + /// useful to use bitwise operations to inspect collections of vertices (i.e. all of the + /// vertices incident a particular face). /// enum Rule { RULE_UNKNOWN = 0, @@ -89,40 +88,34 @@ public: }; public: - Crease() : _options() { } Crease(Options const& options) : _options(options) { } ~Crease() { } - // - // Considering labeling the current/default/normal creasing method as "simple" in contrast - // to all others that are "complex". The idea is that code can make certain assumptions - // and take some "simple" action in some cases to avoid the higher costs of dealing with - // more complex implementations. - // bool IsUniform() const { return _options.GetCreasingMethod() == Options::CREASE_UNIFORM; } //@{ - /// /// Optional sharp features: /// Since options treat certain topological features as infinitely sharp -- boundaries - /// or nonmanifold features -- sharpness values should be adjusted before use. The following - /// methods will adjust specific according to the options applied. + /// or (in future) nonmanifold features -- sharpness values should be adjust before use. + /// The following methods will adjust (by return) specific values according to the options + /// applied. /// float SharpenBoundaryEdge(float edgeSharpness) const; float SharpenBoundaryVertex(float edgeSharpness) const; - float SharpenNonManifoldEdge(float edgeSharpness) const; - float SharpenNonManifoldVertex(float edgeSharpness) const; + // For future consideration + //float SharpenNonManifoldEdge(float edgeSharpness) const; + //float SharpenNonManifoldVertex(float edgeSharpness) const; //@} //@{ /// Sharpness subdivision: - /// The simple case for computing a subdivided sharpness value is as follows: + /// The computation of a Uniform subdivided sharpness value is as follows: /// - Smooth edges or verts stay Smooth /// - Sharp edges or verts stay Sharp /// - semi-sharp edges or verts are decremented by 1.0 - /// but for Chaikin (and potentially future creasing schemes that improve upon it) the + /// but for Chaikin (and potentially future non-uniform schemes that improve upon it) the /// computation is more involved. In the case of edges in particular, the sharpness of a /// child edge is determined by the sharpness in the neighborhood of the end vertex /// corresponding to the child. For this reason, an alternative to subdividing sharpness @@ -155,7 +148,7 @@ public: int sharpEdgeCount) const; //@} - /// \brief Transitional weighting + /// \brief Transitional weighting: /// When the rules applicable to a parent vertex and its child differ, one or more /// sharpness values has "decayed" to zero. Both rules are then applicable and blended /// by a weight between 0 and 1 that reflects the transition. Most often this will be @@ -166,19 +159,6 @@ public: /// So to properly determine a transitional weight, sharpness values for both the /// parent and child must be inspected, combined and clamped accordingly. /// - /// Open questions: - /// - does this method need to be public, or can it reside within the mask - /// query classes? (though it would be the same for anything non-linear, so - /// may be worth making a protected method somewhere) - /// - does this need further consideration at an edge-vertex? - /// - no, the edge-vertex case is far more trivial: one non-zero sharpness - /// for the edge that decays to zero for one or both child edges -- the - /// transitional weight is simply the edge sharpness (clamped to 1) - /// ? why pass only the parent vertex sharpness... - /// - because it is so trivial to compute the child vertex sharpness? - /// - may be better off passing both parent and child for both vertex and edge - /// just to be clear here. - /// float ComputeFractionalWeightAtVertex(float vertexSharpness, float childVertexSharpness, int incidentEdgeCount, @@ -197,14 +177,19 @@ private: Options _options; }; + // -// Non-trivial inline declarations: +// Inline declarations: // inline float -Crease::SharpenBoundaryEdge(float edgeSharpness) const { +Crease::SharpenBoundaryEdge(float /* edgeSharpness */) const { - return (_options.GetVtxBoundaryInterpolation() != Options::VTX_BOUNDARY_NONE) ? - SHARPNESS_INFINITE : edgeSharpness; + // + // Despite the presence of the BOUNDARY_NONE option, boundary edges are always sharpened. + // Much of the code relies on sharpess to indicate boundaries to avoid the more complex + // topological inspection + // + return SHARPNESS_INFINITE; } inline float diff --git a/opensubdiv/sdc/options.h b/opensubdiv/sdc/options.h index 49c39aa8..2476bcda 100644 --- a/opensubdiv/sdc/options.h +++ b/opensubdiv/sdc/options.h @@ -31,22 +31,6 @@ namespace OPENSUBDIV_VERSION { namespace Sdc { -// BETA NOTES: -// Several of these options are being reconsidered in light of the divergence of -// OSD 3.0 from Hbr. In some cases the options can be expressed more clearly and free -// of any RenderMan legacy for future use. Details are noted below: -// "VtxBoundaryInterpolation" -// - its effect is to sharpen edges/corners, but edges are always sharpened -// - the "None" case serves no purpose (and would be discouraged) -// "FVarLinearInterpolation": -// - the new "corner only" mode will sharpen corners and NEVER sharpen smooth -// boundaries, which we believe to be expected when sharping corners -- the -// old "edge and corner" mode would sharpen boundaries under some situations -// (e.g. more than three fvar values at a vertex) -// "NonManifoldInterpolation": -// - rules still need to be defined and implemented -// - /// /// \brief All supported options applying to subdivision scheme. /// @@ -63,6 +47,23 @@ namespace Sdc { /// scheme. Ideally it remains a set of bit-fields (essentially an int) and so /// remains light weight and easily passed down by value. /// + +// +// BETA NOTES: +// Several of these options are being reconsidered in light of the divergence of +// OSD 3.0 from Hbr. In some cases the options can be expressed more clearly and free +// of any RenderMan legacy for future use. Details are noted below: +// "VtxBoundaryInterpolation" +// - its effect is to sharpen edges/corners, but edges are always sharpened +// - the "None" case serves no purpose (and would be discouraged) +// "FVarLinearInterpolation": +// - the new "corner only" mode will sharpen corners and NEVER sharpen smooth +// boundaries, which we believe to be expected when sharping corners -- the +// old "edge and corner" mode would sharpen boundaries under some situations +// (e.g. more than three fvar values at a vertex) +// "NonManifoldInterpolation": +// - rules still need to be defined and implemented +// class Options { public: enum VtxBoundaryInterpolation { diff --git a/opensubdiv/sdc/scheme.h b/opensubdiv/sdc/scheme.h index 4614fe53..f7a84d24 100644 --- a/opensubdiv/sdc/scheme.h +++ b/opensubdiv/sdc/scheme.h @@ -101,7 +101,7 @@ public: Crease::Rule childRule = Crease::RULE_UNKNOWN) const; /// - /// ]brief Vertex-vertex masks + /// \brief Vertex-vertex masks /// If known, a single Rule or pair of Rules can be specified (indicating a crease /// transition) to accelerate the computation. Either no Rules, the first, or both should /// be specified. Specification of only the first Rule implies it to be true for both diff --git a/opensubdiv/vtr/level.h b/opensubdiv/vtr/level.h index 1b7783b3..d92a693a 100644 --- a/opensubdiv/vtr/level.h +++ b/opensubdiv/vtr/level.h @@ -219,8 +219,8 @@ public: ConstLocalIndexArray getVertexEdgeLocalIndices(Index vertIndex) const; // Replace these with access to sharpness buffers/arrays rather than elements: - Sharpness getEdgeSharpness(Index edgeIndex) const; - Sharpness getVertexSharpness(Index vertIndex) const; + float getEdgeSharpness(Index edgeIndex) const; + float getVertexSharpness(Index vertIndex) const; Sdc::Crease::Rule getVertexRule(Index vertIndex) const; Index findEdge(Index v0Index, Index v1Index) const; @@ -318,8 +318,8 @@ protected: LocalIndexArray getVertexEdgeLocalIndices(Index vertIndex); // Replace these with access to sharpness buffers/arrays rather than elements: - Sharpness& getEdgeSharpness(Index edgeIndex); - Sharpness& getVertexSharpness(Index vertIndex); + float& getEdgeSharpness(Index edgeIndex); + float& getVertexSharpness(Index vertIndex); // Create, destroy and populate face-varying channels: int createFVarChannel(int fvarValueCount, Sdc::Options const& options); @@ -442,8 +442,8 @@ protected: std::vector _edgeFaceCountsAndOffsets; // 2 per edge std::vector _edgeFaceIndices; // varies with faces per edge - std::vector _edgeSharpness; // 1 per edge - std::vector _edgeTags; // 1 per edge: manifold, boundary, etc. + std::vector _edgeSharpness; // 1 per edge + std::vector _edgeTags; // 1 per edge: manifold, boundary, etc. // Per-vertex: std::vector _vertFaceCountsAndOffsets; // 2 per vertex @@ -454,7 +454,7 @@ protected: std::vector _vertEdgeIndices; // varies with valence std::vector _vertEdgeLocalIndices; // varies with valence, 8-bit for now - std::vector _vertSharpness; // 1 per vertex + std::vector _vertSharpness; // 1 per vertex std::vector _vertTags; // 1 per vertex: manifold, Sdc::Rule, etc. // Face-varying channels: @@ -620,20 +620,20 @@ Level::trimEdgeFaces(Index edgeIndex, int count) { // // Access/modify sharpness values: // -inline Sharpness +inline float Level::getEdgeSharpness(Index edgeIndex) const { return _edgeSharpness[edgeIndex]; } -inline Sharpness& +inline float& Level::getEdgeSharpness(Index edgeIndex) { return _edgeSharpness[edgeIndex]; } -inline Sharpness +inline float Level::getVertexSharpness(Index vertIndex) const { return _vertSharpness[vertIndex]; } -inline Sharpness& +inline float& Level::getVertexSharpness(Index vertIndex) { return _vertSharpness[vertIndex]; } diff --git a/opensubdiv/vtr/refinement.cpp b/opensubdiv/vtr/refinement.cpp index 891527b9..39ebc839 100644 --- a/opensubdiv/vtr/refinement.cpp +++ b/opensubdiv/vtr/refinement.cpp @@ -880,14 +880,14 @@ Refinement::subdivideEdgeSharpness() { Index cEdge = getFirstChildEdgeFromEdges(); Index cEdgeEnd = cEdge + getNumChildEdgesFromEdges(); for ( ; cEdge < cEdgeEnd; ++cEdge) { - Sharpness& cSharpness = _child->_edgeSharpness[cEdge]; + float& cSharpness = _child->_edgeSharpness[cEdge]; Level::ETag& cEdgeTag = _child->_edgeTags[cEdge]; if (cEdgeTag._infSharp) { cSharpness = Sdc::Crease::SHARPNESS_INFINITE; } else if (cEdgeTag._semiSharp) { - Index pEdge = _childEdgeParentIndex[cEdge]; - Sharpness pSharpness = _parent->_edgeSharpness[pEdge]; + Index pEdge = _childEdgeParentIndex[cEdge]; + float pSharpness = _parent->_edgeSharpness[pEdge]; if (creasing.IsUniform()) { cSharpness = creasing.SubdivideUniformSharpness(pSharpness); @@ -924,14 +924,14 @@ Refinement::subdivideVertexSharpness() { Index cVertEnd = cVertBegin + getNumChildVerticesFromVertices(); for (Index cVert = cVertBegin; cVert < cVertEnd; ++cVert) { - Sharpness& cSharpness = _child->_vertSharpness[cVert]; + float& cSharpness = _child->_vertSharpness[cVert]; Level::VTag& cVertTag = _child->_vertTags[cVert]; if (cVertTag._infSharp) { cSharpness = Sdc::Crease::SHARPNESS_INFINITE; } else if (cVertTag._semiSharp) { - Index pVert = _childVertexParentIndex[cVert]; - Sharpness pSharpness = _parent->_vertSharpness[pVert]; + Index pVert = _childVertexParentIndex[cVert]; + float pSharpness = _parent->_vertSharpness[pVert]; cSharpness = creasing.SubdivideVertexSharpness(pSharpness); diff --git a/opensubdiv/vtr/types.h b/opensubdiv/vtr/types.h index 7552f9af..20db8ddd 100644 --- a/opensubdiv/vtr/types.h +++ b/opensubdiv/vtr/types.h @@ -36,14 +36,9 @@ namespace OPENSUBDIV_VERSION { namespace Vtr { // -// A few types (and constants) are declared here while Vtr is being -// developed. These tend to be used by more than one Vtr class, i.e. -// both Level and Refinement and are often present in their -// interfaces. +// A few types (and constants) for use within Vtr and potentially by its +// clients (appropriately exported and retyped) // -// Is the sharpness overkill -- perhaps sdc should define this... -// -typedef float Sharpness; // // Indices -- note we can't use sized integer types like uint32_t, etc. as use of @@ -63,9 +58,10 @@ static const Index INDEX_INVALID = -1; inline bool IndexIsValid(Index index) { return (index != INDEX_INVALID); } // -// Note for aggregate types the use of "vector" wraps an std:;vector (typically a -// member variable) and is fully resizable and owns its own storage, whereas "array" -// is typically used in index a fixed subset of pre-allocated memory: +// Note for aggregate types that the use of "vector" in the name indicates a class +// that wraps an std:;vector (typically a member variable) which is fully resizable +// and owns its own storage, whereas "array" indicates a fixed block of pre-allocated +// memory: // typedef std::vector IndexVector; @@ -79,9 +75,7 @@ typedef ConstArray ConstLocalIndexArray; } // end namespace Vtr } // end namespace OPENSUBDIV_VERSION - using namespace OPENSUBDIV_VERSION; - } // end namespace OpenSubdiv #endif /* VTR_TYPES_H */