OpenSubdiv: Refactor, move mesh topology comparison to own file

Makes it easier to follow and extend.
This commit is contained in:
Sergey Sharybin 2020-05-19 14:30:58 +02:00
parent ece54172d0
commit 6a8193e505
5 changed files with 129 additions and 67 deletions

View File

@ -79,6 +79,7 @@ if(WITH_OPENSUBDIV)
# Topology.
internal/topology/mesh_topology.cc
internal/topology/mesh_topology_compare.cc
internal/topology/mesh_topology.h
internal/topology/topology_refiner_capi.cc
internal/topology/topology_refiner_factory.cc

View File

@ -71,6 +71,13 @@ class MeshTopology {
void setEdgeSharpness(int edge_index, float sharpness);
float getEdgeSharpness(int edge_index) const;
//////////////////////////////////////////////////////////////////////////////
// Comparison.
// Check whether this topology refiner defines same topology as the given
// converter.
bool isEqualToConverter(const OpenSubdiv_Converter *converter) const;
protected:
// Unless full topology was specified the number of edges is not know ahead
// of a time.

View File

@ -0,0 +1,111 @@
// Copyright 2020 Blender Foundation. All rights reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// Author: Sergey Sharybin
#include "internal/topology/mesh_topology.h"
#include <cassert>
#include <opensubdiv/sdc/crease.h>
#include "opensubdiv_converter_capi.h"
namespace blender {
namespace opensubdiv {
namespace {
////////////////////////////////////////////////////////////////////////////////
// Geometry tags.
// Vertices.
// TODO(sergey): Make this function usable by factory as well.
float getEffectiveVertexSharpness(const OpenSubdiv_Converter *converter, const int vertex_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);
}
return 0.0f;
}
bool isEqualVertexTags(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
{
const int num_vertices = mesh_topology.getNumVertices();
for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
const float current_sharpness = mesh_topology.getVertexSharpness(vertex_index);
const float requested_sharpness = getEffectiveVertexSharpness(converter, vertex_index);
if (current_sharpness != requested_sharpness) {
return false;
}
}
return true;
}
// Edges.
// TODO(sergey): Make this function usable by factory as well.
float getEffectiveEdgeSharpness(const OpenSubdiv_Converter *converter, const int edge_index)
{
if (converter->getEdgeSharpness != nullptr) {
return converter->getEdgeSharpness(converter, edge_index);
}
return 0.0f;
}
bool isEqualEdgeTags(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
{
const int num_edges = mesh_topology.getNumEdges();
for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
const float current_sharpness = mesh_topology.getEdgeSharpness(edge_index);
const float requested_sharpness = getEffectiveEdgeSharpness(converter, edge_index);
if (current_sharpness != requested_sharpness) {
return false;
}
}
return true;
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// Entry point.
bool MeshTopology::isEqualToConverter(const OpenSubdiv_Converter *converter) const
{
if (!isEqualVertexTags(*this, converter)) {
return false;
}
if (!isEqualEdgeTags(*this, converter)) {
return false;
}
return true;
}
} // namespace opensubdiv
} // namespace blender

View File

@ -36,15 +36,17 @@ namespace opensubdiv {
class TopologyRefinerImpl {
public:
// NOTE: Will return nullptr if topology refiner can not be created (for example, when topology
// is detected to be corrupted or invalid).
// NOTE: Will return nullptr if topology refiner can not be created (for
// example, when topology is detected to be corrupted or invalid).
static TopologyRefinerImpl *createFromConverter(
OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings &settings);
TopologyRefinerImpl();
~TopologyRefinerImpl();
// Check whether this topology refiner defines same topology as the given converter.
// Check whether this topology refiner defines same topology as the given
// converter.
// Covers options, geometry, and geometry tags.
bool isEqualToConverter(const OpenSubdiv_Converter *converter) const;
OpenSubdiv::Far::TopologyRefiner *topology_refiner;

View File

@ -22,6 +22,7 @@
#include "internal/base/type_convert.h"
#include "internal/topology/mesh_topology.h"
#include "internal/topology/topology_refiner_impl.h"
#include "opensubdiv_converter_capi.h"
namespace blender {
@ -234,67 +235,6 @@ bool checkGeometryMatches(const TopologyRefinerImpl *topology_refiner_impl,
////////////////////////////////////////////////////////////////////////////////
// Compare attributes which affects on topology.
// TODO(sergey): Make this function usable by factory as well.
float getEffectiveEdgeSharpness(const OpenSubdiv_Converter *converter, const int edge_index)
{
if (converter->getEdgeSharpness != nullptr) {
return converter->getEdgeSharpness(converter, edge_index);
}
return 0.0f;
}
bool checkEdgeTagsMatch(const TopologyRefinerImpl *topology_refiner_impl,
const OpenSubdiv_Converter *converter)
{
const MeshTopology &base_mesh_topology = topology_refiner_impl->base_mesh_topology;
const int num_edges = base_mesh_topology.getNumEdges();
for (int edge_index = 0; edge_index < num_edges; ++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;
}
// TODO(sergey): Make this function usable by factory as well.
float getEffectiveVertexSharpness(const OpenSubdiv_Converter *converter, const int vertex_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);
}
return 0.0f;
}
bool checkVertexSharpnessMatch(const TopologyRefinerImpl *topology_refiner_impl,
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_mesh_topology.getVertexSharpness(vertex_index);
const float requested_sharpness = getEffectiveVertexSharpness(converter, vertex_index);
if (current_sharpness != requested_sharpness) {
return false;
}
}
return true;
}
bool checkSingleUVLayerMatch(const OpenSubdiv::Far::TopologyLevel &base_level,
const OpenSubdiv_Converter *converter,
const int layer_index)
@ -339,9 +279,10 @@ bool checkUVLayersMatch(const TopologyRefinerImpl *topology_refiner_impl,
bool checkTopologyAttributesMatch(const TopologyRefinerImpl *topology_refiner_impl,
const OpenSubdiv_Converter *converter)
{
return checkEdgeTagsMatch(topology_refiner_impl, converter) &&
checkVertexSharpnessMatch(topology_refiner_impl, converter) &&
checkUVLayersMatch(topology_refiner_impl, converter);
if (!topology_refiner_impl->base_mesh_topology.isEqualToConverter(converter)) {
return false;
}
return checkUVLayersMatch(topology_refiner_impl, converter);
}
} // namespace