Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2020-05-19 12:43:58 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2020-05-27 13:07:16 +0300
commit614d70a87dc3d439d620f1df8930c37d47df3803 (patch)
tree8ef70dad44b5b05918b6bc8bb7a759d89a980660 /intern/opensubdiv
parent717d968fb9fd2daa5326a8e2322c3accee335ce3 (diff)
OpenSubdiv: Compare sharpness based on converter
This change starts the transition of topology refiner comparison to compare actual values given by the converter, which will not be affected by the refinement or face winding synchronization steps. Currently is only implemented for vertex sharpness, but will be extended further as followup development. Fixes T71908: Subdiv: Incorrect topology comparison, leading to poor performance
Diffstat (limited to 'intern/opensubdiv')
-rw-r--r--intern/opensubdiv/internal/topology/topology_refiner_capi.cc72
-rw-r--r--intern/opensubdiv/internal/topology/topology_refiner_factory.cc26
-rw-r--r--intern/opensubdiv/internal/topology/topology_refiner_impl.h21
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");
};