diff options
Diffstat (limited to 'intern/opensubdiv/internal')
4 files changed, 147 insertions, 90 deletions
diff --git a/intern/opensubdiv/internal/topology/mesh_topology.cc b/intern/opensubdiv/internal/topology/mesh_topology.cc index f8832d61cd0..e4469a83f75 100644 --- a/intern/opensubdiv/internal/topology/mesh_topology.cc +++ b/intern/opensubdiv/internal/topology/mesh_topology.cc @@ -23,7 +23,7 @@ namespace blender { namespace opensubdiv { -MeshTopology::MeshTopology() +MeshTopology::MeshTopology() : num_vertices_(0), num_edges_(0) { } @@ -31,21 +31,102 @@ MeshTopology::~MeshTopology() { } +//////////////////////////////////////////////////////////////////////////////// +// Vertices. + void MeshTopology::setNumVertices(int num_vertices) { - vertices.resize(num_vertices); + num_vertices_ = num_vertices; } + int MeshTopology::getNumVertices() const { - return vertices.size(); + return num_vertices_; } void MeshTopology::setVertexSharpness(int vertex_index, float sharpness) { assert(vertex_index >= 0); - assert(vertex_index < vertices.size()); + assert(vertex_index < getNumVertices()); + + ensureVertexTagsSize(vertex_index + 1); + + vertex_tags_[vertex_index].sharpness = sharpness; +} + +float MeshTopology::getVertexSharpness(int vertex_index) const +{ + assert(vertex_index >= 0); + assert(vertex_index < getNumVertices()); - vertices[vertex_index].sharpness = sharpness; + if (vertex_index >= vertex_tags_.size()) { + // Sharpness for the vertex was never provided. + return 0.0f; + } + + return vertex_tags_[vertex_index].sharpness; +} + +void MeshTopology::ensureVertexTagsSize(int num_vertices) +{ + if (vertex_tags_.size() < num_vertices) { + vertex_tags_.resize(num_vertices); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Edges. + +void MeshTopology::setNumEdges(int num_edges) +{ + num_edges_ = num_edges; +} + +int MeshTopology::getNumEdges() const +{ + return num_edges_; +} + +void MeshTopology::setEdgeSharpness(int edge_index, float sharpness) +{ + assert(edge_index >= 0); + + ensureNumEdgesAtLeast(edge_index + 1); + + if (sharpness < 1e-6f) { + return; + } + + ensureEdgeTagsSize(edge_index + 1); + + edge_tags_[edge_index].sharpness = sharpness; +} + +float MeshTopology::getEdgeSharpness(int edge_index) const +{ + assert(edge_index >= 0); + + if (edge_index >= edge_tags_.size()) { + // NOTE: It's possible that full topology is not known and that there was + // never sharpness assigned to any of the edges. + return 0.0f; + } + + return edge_tags_[edge_index].sharpness; +} + +void MeshTopology::ensureNumEdgesAtLeast(int num_edges) +{ + if (getNumEdges() < num_edges) { + setNumEdges(num_edges); + } +} + +void MeshTopology::ensureEdgeTagsSize(int num_edges) +{ + if (edge_tags_.size() < num_edges) { + edge_tags_.resize(num_edges); + } } } // namespace opensubdiv diff --git a/intern/opensubdiv/internal/topology/mesh_topology.h b/intern/opensubdiv/internal/topology/mesh_topology.h index 9893c70dac8..183f5eb45d4 100644 --- a/intern/opensubdiv/internal/topology/mesh_topology.h +++ b/intern/opensubdiv/internal/topology/mesh_topology.h @@ -27,7 +27,12 @@ struct OpenSubdiv_Converter; namespace blender { namespace opensubdiv { -class VertexTopology { +class VertexTopologyTag { + public: + float sharpness = 0.0f; +}; + +class EdgeTopologyTag { public: float sharpness = 0.0f; }; @@ -45,12 +50,44 @@ class MeshTopology { MeshTopology &operator=(const MeshTopology &other) = default; MeshTopology &operator=(MeshTopology &&other) = default; + ////////////////////////////////////////////////////////////////////////////// + // Vertices. + void setNumVertices(int num_vertices); int getNumVertices() const; void setVertexSharpness(int vertex_index, float sharpness); + float getVertexSharpness(int vertex_index) const; + + ////////////////////////////////////////////////////////////////////////////// + // Edges. + + void setNumEdges(int num_edges); + + // NOTE: Unless full topology was specified will return number of edges based + // on last edge index for which topology tag was specified. + int getNumEdges() const; + + void setEdgeSharpness(int edge_index, float sharpness); + float getEdgeSharpness(int edge_index) const; + + protected: + // Unless full topology was specified the number of edges is not know ahead + // of a time. + void ensureNumEdgesAtLeast(int num_edges); + + // Geometry tags are stored sparsly. + // + // These functions ensures that the storage can be addressed by an index which + // corresponds to the given size. + void ensureVertexTagsSize(int num_vertices); + void ensureEdgeTagsSize(int num_edges); + + int num_vertices_; + vector<VertexTopologyTag> vertex_tags_; - vector<VertexTopology> vertices; + int num_edges_; + vector<EdgeTopologyTag> edge_tags_; MEM_CXX_CLASS_ALLOC_FUNCS("MeshTopology"); }; diff --git a/intern/opensubdiv/internal/topology/topology_refiner_factory.cc b/intern/opensubdiv/internal/topology/topology_refiner_factory.cc index c9c72f18349..a0e0269936c 100644 --- a/intern/opensubdiv/internal/topology/topology_refiner_factory.cc +++ b/intern/opensubdiv/internal/topology/topology_refiner_factory.cc @@ -77,6 +77,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology // Edges and edge-faces. const int num_edges = converter->getNumEdges(converter); + base_mesh_topology->setNumEdges(num_edges); setNumBaseEdges(refiner, num_edges); for (int edge_index = 0; edge_index < num_edges; ++edge_index) { const int num_edge_faces = converter->getNumEdgeFaces(converter, edge_index); @@ -161,9 +162,12 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags( const int num_edges = converter->getNumEdges(converter); for (int edge_index = 0; edge_index < num_edges; ++edge_index) { const float sharpness = converter->getEdgeSharpness(converter, edge_index); + base_mesh_topology->setEdgeSharpness(edge_index, sharpness); + if (sharpness < 1e-6f) { continue; } + if (full_topology_specified) { setBaseEdgeSharpness(refiner, edge_index, sharpness); } diff --git a/intern/opensubdiv/internal/topology/topology_refiner_impl_compare.cc b/intern/opensubdiv/internal/topology/topology_refiner_impl_compare.cc index d51d0eb7f54..06612a9e6a1 100644 --- a/intern/opensubdiv/internal/topology/topology_refiner_impl_compare.cc +++ b/intern/opensubdiv/internal/topology/topology_refiner_impl_compare.cc @@ -18,7 +18,6 @@ #include "internal/topology/topology_refiner_impl.h" -#include "internal/base/edge_map.h" #include "internal/base/type.h" #include "internal/base/type_convert.h" #include "internal/topology/mesh_topology.h" @@ -233,102 +232,37 @@ bool checkGeometryMatches(const TopologyRefinerImpl *topology_refiner_impl, } //////////////////////////////////////////////////////////////////////////////// -// Compare attributes which affects on topology +// Compare attributes which affects on topology. -inline bool checkSingleEdgeSharpnessMatch(const OpenSubdiv::Far::TopologyLevel &base_level, - int base_level_edge_index, - const OpenSubdiv_Converter *converter, - int converter_edge_index) +// TODO(sergey): Make this function usable by factory as well. +float getEffectiveEdgeSharpness(const OpenSubdiv_Converter *converter, const int edge_index) { - // NOTE: Boundary and non-manifold edges are internally forced to an infinite - // sharpness. So we can not reliably compare those. - // - // TODO(sergey): Watch for NON_MANIFOLD_SHARP option. - if (base_level.IsEdgeBoundary(base_level_edge_index) || - base_level.IsEdgeNonManifold(base_level_edge_index)) { - return true; - } - const float sharpness = base_level.GetEdgeSharpness(base_level_edge_index); - const float converter_sharpness = converter->getEdgeSharpness(converter, converter_edge_index); - if (sharpness != converter_sharpness) { - return false; + if (converter->getEdgeSharpness != nullptr) { + return converter->getEdgeSharpness(converter, edge_index); } - return true; -} -inline bool checkSingleEdgeTagMatch(const OpenSubdiv::Far::TopologyLevel &base_level, - int base_level_edge_index, - const OpenSubdiv_Converter *converter, - int converter_edge_index) -{ - return checkSingleEdgeSharpnessMatch( - base_level, base_level_edge_index, converter, converter_edge_index); + return 0.0f; } -// Compares edge tags between topology refiner and converter in a case when -// converter specifies a full topology. -// This is simplest loop, since we know that order of edges matches. -bool checkEdgeTagsMatchFullTopology(const TopologyRefinerImpl *topology_refiner_impl, - const OpenSubdiv_Converter *converter) +bool checkEdgeTagsMatch(const TopologyRefinerImpl *topology_refiner_impl, + const OpenSubdiv_Converter *converter) { - using OpenSubdiv::Far::ConstIndexArray; - using OpenSubdiv::Far::TopologyLevel; - const TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner_impl); - const int num_edges = base_level.GetNumEdges(); - for (int edge_index = 0; edge_index < num_edges; ++edge_index) { - if (!checkSingleEdgeTagMatch(base_level, edge_index, converter, edge_index)) { - return false; - } - } - return true; -} + const MeshTopology &base_mesh_topology = topology_refiner_impl->base_mesh_topology; -// Compares tags of edges in the case when orientation of edges is left up to -// OpenSubdiv. In this case we do need to take care of mapping edges from the -// converter to current topology refiner, since the order is not guaranteed. -bool checkEdgeTagsMatchAutoOrient(const TopologyRefinerImpl *topology_refiner_impl, - const OpenSubdiv_Converter *converter) -{ - using OpenSubdiv::Far::ConstIndexArray; - using OpenSubdiv::Far::TopologyLevel; - const TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner_impl); - const int num_edges = base_level.GetNumEdges(); - // Create mapping for quick lookup of edge index from its vertices indices. - // - // TODO(sergey): Consider caching it in some sort of wrapper around topology - // refiner. - EdgeTagMap<int> edge_map; + const int num_edges = base_mesh_topology.getNumEdges(); for (int edge_index = 0; edge_index < num_edges; ++edge_index) { - ConstIndexArray edge_vertices = base_level.GetEdgeVertices(edge_index); - edge_map.insert(edge_vertices[0], edge_vertices[1], edge_index); - } - // Compare all edges. - for (int converter_edge_index = 0; converter_edge_index < num_edges; ++converter_edge_index) { - // Get edge vertices indices, and lookup corresponding edge index in the - // base topology level. - int edge_vertices[2]; - converter->getEdgeVertices(converter, converter_edge_index, edge_vertices); - const int base_level_edge_index = edge_map.at(edge_vertices[0], edge_vertices[1]); - // Perform actual test. - if (!checkSingleEdgeTagMatch( - base_level, base_level_edge_index, converter, converter_edge_index)) { + const float current_sharpness = base_mesh_topology.getEdgeSharpness(edge_index); + const float requested_sharpness = getEffectiveEdgeSharpness(converter, edge_index); + + if (current_sharpness != requested_sharpness) { return false; } } - return true; -} -bool checkEdgeTagsMatch(const TopologyRefinerImpl *topology_refiner_impl, - const OpenSubdiv_Converter *converter) -{ - if (converter->specifiesFullTopology(converter)) { - return checkEdgeTagsMatchFullTopology(topology_refiner_impl, converter); - } - else { - return checkEdgeTagsMatchAutoOrient(topology_refiner_impl, converter); - } + return true; } +// TODO(sergey): Make this function usable by factory as well. float getEffectiveVertexSharpness(const OpenSubdiv_Converter *converter, const int vertex_index) { if (converter->isInfiniteSharpVertex != nullptr && @@ -350,13 +284,14 @@ bool checkVertexSharpnessMatch(const TopologyRefinerImpl *topology_refiner_impl, const int num_vertices = base_mesh_topology.getNumVertices(); for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { - const float current_sharpness = base_mesh_topology.vertices[vertex_index].sharpness; + const float current_sharpness = base_mesh_topology.getVertexSharpness(vertex_index); const float requested_sharpness = getEffectiveVertexSharpness(converter, vertex_index); if (current_sharpness != requested_sharpness) { return false; } } + return true; } |