diff options
Diffstat (limited to 'intern')
3 files changed, 67 insertions, 52 deletions
diff --git a/intern/opensubdiv/internal/topology/topology_refiner_capi.cc b/intern/opensubdiv/internal/topology/topology_refiner_capi.cc index 58c0ffbb7cf..8c3f8f1f896 100644 --- a/intern/opensubdiv/internal/topology/topology_refiner_capi.cc +++ b/intern/opensubdiv/internal/topology/topology_refiner_capi.cc @@ -22,6 +22,7 @@ #include "internal/base/edge_map.h" #include "internal/base/type.h" #include "internal/base/type_convert.h" +#include "internal/topology/mesh_topology.h" #include "internal/topology/topology_refiner_impl.h" #include "opensubdiv_converter_capi.h" @@ -553,55 +554,32 @@ bool checkEdgeTagsMatch(const OpenSubdiv_TopologyRefiner *topology_refiner, } } -bool checkvertexSharpnessMatch(const OpenSubdiv_TopologyRefiner *topology_refiner, - const OpenSubdiv_Converter *converter) +float getEffectiveVertexSharpness(const OpenSubdiv_Converter *converter, const int vertex_index) { - using OpenSubdiv::Far::ConstIndexArray; - using OpenSubdiv::Far::TopologyLevel; - using OpenSubdiv::Sdc::Crease; - const TopologyLevel &base_level = getOSDTopologyRefiner(topology_refiner)->GetLevel(0); - // 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. - const int num_edges = base_level.GetNumEdges(); - EdgeTagMap<int> edge_map; - for (int edge_index = 0; edge_index < num_edges; ++edge_index) { - int edge_vertices[2]; - converter->getEdgeVertices(converter, edge_index, edge_vertices); - edge_map.insert(edge_vertices[0], edge_vertices[1], edge_index); + if (converter->isInfiniteSharpVertex != nullptr && + converter->isInfiniteSharpVertex(converter, vertex_index)) { + return OpenSubdiv::Sdc::Crease::SHARPNESS_INFINITE; + } + + if (converter->getVertexSharpness != nullptr) { + return converter->getVertexSharpness(converter, vertex_index); } - const int num_vertices = base_level.GetNumVertices(); + + return 0.0f; +} + +bool checkVertexSharpnessMatch(const OpenSubdiv_TopologyRefiner *topology_refiner, + const OpenSubdiv_Converter *converter) +{ + const MeshTopology &base_mesh_topology = topology_refiner->impl->base_mesh_topology; + + const int num_vertices = base_mesh_topology.getNumVertices(); for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { - const float current_sharpness = base_level.GetVertexSharpness(vertex_index); - if (converter->isInfiniteSharpVertex(converter, vertex_index)) { - if (current_sharpness != Crease::SHARPNESS_INFINITE) { - return false; - } - } - else { - ConstIndexArray vertex_edges = base_level.GetVertexEdges(vertex_index); - float sharpness = converter->getVertexSharpness(converter, vertex_index); - if (vertex_edges.size() == 2) { - const int edge0 = vertex_edges[0], edge1 = vertex_edges[1]; - // Construct keys for lookup. - ConstIndexArray edge0_vertices = base_level.GetEdgeVertices(edge0); - ConstIndexArray edge1_vertices = base_level.GetEdgeVertices(edge1); - EdgeKey edge0_key(edge0_vertices[0], edge0_vertices[1]); - EdgeKey edge1_key(edge1_vertices[0], edge1_vertices[1]); - // Lookup edge indices in the converter. - const int edge0_converter_index = edge_map[edge0_key]; - const int edge1_converter_index = edge_map[edge1_key]; - // Lookup sharpness. - const float sharpness0 = converter->getEdgeSharpness(converter, edge0_converter_index); - const float sharpness1 = converter->getEdgeSharpness(converter, edge1_converter_index); - // TODO(sergey): Find a better mixing between edge and vertex sharpness. - sharpness += min(sharpness0, sharpness1); - sharpness = min(sharpness, 10.0f); - } - if (sharpness != current_sharpness) { - return false; - } + const float current_sharpness = base_mesh_topology.vertices[vertex_index].sharpness; + const float requested_sharpness = getEffectiveVertexSharpness(converter, vertex_index); + + if (current_sharpness != requested_sharpness) { + return false; } } return true; @@ -652,7 +630,7 @@ bool checkTopologyAttributesMatch(const OpenSubdiv_TopologyRefiner *topology_ref const OpenSubdiv_Converter *converter) { return checkEdgeTagsMatch(topology_refiner, converter) && - checkvertexSharpnessMatch(topology_refiner, converter) && + checkVertexSharpnessMatch(topology_refiner, converter) && checkUVLayersMatch(topology_refiner, converter); } diff --git a/intern/opensubdiv/internal/topology/topology_refiner_factory.cc b/intern/opensubdiv/internal/topology/topology_refiner_factory.cc index 1a51fce6e24..c9c72f18349 100644 --- a/intern/opensubdiv/internal/topology/topology_refiner_factory.cc +++ b/intern/opensubdiv/internal/topology/topology_refiner_factory.cc @@ -29,6 +29,8 @@ #include "internal/base/type.h" #include "internal/base/type_convert.h" +#include "internal/topology/mesh_topology.h" + #include "opensubdiv_converter_capi.h" using blender::opensubdiv::min; @@ -37,6 +39,7 @@ using blender::opensubdiv::vector; struct TopologyRefinerData { const OpenSubdiv_Converter *converter; + blender::opensubdiv::MeshTopology *base_mesh_topology; }; typedef OpenSubdiv::Far::TopologyRefinerFactory<TopologyRefinerData> TopologyRefinerFactoryType; @@ -49,7 +52,11 @@ template<> inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology( TopologyRefiner &refiner, const TopologyRefinerData &cb_data) { + using blender::opensubdiv::MeshTopology; + const OpenSubdiv_Converter *converter = cb_data.converter; + MeshTopology *base_mesh_topology = cb_data.base_mesh_topology; + // Faces and face-vertices. const int num_faces = converter->getNumFaces(converter); setNumBaseFaces(refiner, num_faces); @@ -57,13 +64,17 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology const int num_face_vertices = converter->getNumFaceVertices(converter, face_index); setNumBaseFaceVertices(refiner, face_index, num_face_vertices); } + // Vertices. const int num_vertices = converter->getNumVertices(converter); + base_mesh_topology->setNumVertices(num_vertices); setNumBaseVertices(refiner, num_vertices); + // If converter does not provide full topology, we are done. if (!converter->specifiesFullTopology(converter)) { return true; } + // Edges and edge-faces. const int num_edges = converter->getNumEdges(converter); setNumBaseEdges(refiner, num_edges); @@ -71,6 +82,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology const int num_edge_faces = converter->getNumEdgeFaces(converter, edge_index); setNumBaseEdgeFaces(refiner, edge_index, num_edge_faces); } + // Vertex-faces and vertex-edges. for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { const int num_vert_edges = converter->getNumVertexEdges(converter, vertex_index); @@ -78,6 +90,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology setNumBaseVertexEdges(refiner, vertex_index, num_vert_edges); setNumBaseVertexFaces(refiner, vertex_index, num_vert_faces); } + return true; } @@ -137,8 +150,12 @@ template<> inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags( TopologyRefiner &refiner, const TopologyRefinerData &cb_data) { + using blender::opensubdiv::MeshTopology; using OpenSubdiv::Sdc::Crease; + const OpenSubdiv_Converter *converter = cb_data.converter; + MeshTopology *base_mesh_topology = cb_data.base_mesh_topology; + const bool full_topology_specified = converter->specifiesFullTopology(converter); if (full_topology_specified || converter->getEdgeVertices != NULL) { const int num_edges = converter->getNumEdges(converter); @@ -151,6 +168,8 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags( setBaseEdgeSharpness(refiner, edge_index, sharpness); } else { + // TODO(sergey): Should be a faster way to find reconstructed edge to + // specify sharpness for (assuming, findBaseEdge has linear complexity). int edge_vertices[2]; converter->getEdgeVertices(converter, edge_index, edge_vertices); const int base_edge_index = findBaseEdge(refiner, edge_vertices[0], edge_vertices[1]); @@ -162,6 +181,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags( } } } + // OpenSubdiv expects non-manifold vertices to be sharp but at the time it // handles correct cases when vertex is a corner of plane. Currently mark // vertices which are adjacent to a loose edge as sharp, but this decision @@ -170,6 +190,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags( for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { ConstIndexArray vertex_edges = getBaseVertexEdges(refiner, vertex_index); if (converter->isInfiniteSharpVertex(converter, vertex_index)) { + base_mesh_topology->setVertexSharpness(vertex_index, Crease::SHARPNESS_INFINITE); setBaseVertexSharpness(refiner, vertex_index, Crease::SHARPNESS_INFINITE); continue; } @@ -178,6 +199,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags( float sharpness = 0.0f; if (converter->getVertexSharpness != NULL) { sharpness = converter->getVertexSharpness(converter, vertex_index); + base_mesh_topology->setVertexSharpness(vertex_index, sharpness); } // If it's vertex where 2 non-manifold edges meet adjust vertex sharpness to @@ -291,8 +313,11 @@ TopologyRefinerImpl *TopologyRefinerImpl::createFromConverter( { using OpenSubdiv::Far::TopologyRefiner; + blender::opensubdiv::MeshTopology base_mesh_topology; + TopologyRefinerData cb_data; cb_data.converter = converter; + cb_data.base_mesh_topology = &base_mesh_topology; // Create OpenSubdiv descriptor for the topology refiner. TopologyRefinerFactoryType::Options topology_refiner_options = getTopologyRefinerOptions( @@ -307,6 +332,7 @@ TopologyRefinerImpl *TopologyRefinerImpl::createFromConverter( TopologyRefinerImpl *topology_refiner_impl = new TopologyRefinerImpl(); topology_refiner_impl->topology_refiner = topology_refiner; topology_refiner_impl->settings = settings; + topology_refiner_impl->base_mesh_topology = move(base_mesh_topology); return topology_refiner_impl; } diff --git a/intern/opensubdiv/internal/topology/topology_refiner_impl.h b/intern/opensubdiv/internal/topology/topology_refiner_impl.h index 5232e97b24b..4a6e6c0fcec 100644 --- a/intern/opensubdiv/internal/topology/topology_refiner_impl.h +++ b/intern/opensubdiv/internal/topology/topology_refiner_impl.h @@ -26,6 +26,7 @@ #include <opensubdiv/far/topologyRefiner.h> #include "internal/base/memory.h" +#include "internal/topology/mesh_topology.h" #include "opensubdiv_topology_refiner_capi.h" struct OpenSubdiv_Converter; @@ -46,13 +47,23 @@ class TopologyRefinerImpl { OpenSubdiv::Far::TopologyRefiner *topology_refiner; // Subdivision settingsa this refiner is created for. + OpenSubdiv_TopologyRefinerSettings settings; + + // Topology of the mesh which corresponds to the base level. // - // We store it here since OpenSubdiv's refiner will only know about level and - // "adaptivity" after performing actual "refine" step. + // All the indices and values are kept exactly the same as user-defined + // converter provided them. This allows to easily compare values which might + // be touched by the refinement process. // - // Ideally, we would also support refining topology without re-importing it - // from external world, but that is for later. - OpenSubdiv_TopologyRefinerSettings settings; + // On a more technical note this allows to easier/faster to compare following + // things: + // + // - Face vertices, where OpenSubdiv could re-arrange them to keep winding + // uniform. + // + // - Vertex crease where OpenSubdiv will force crease for non-manifold or + // corner vertices. + MeshTopology base_mesh_topology; MEM_CXX_CLASS_ALLOC_FUNCS("TopologyRefinerImpl"); }; |