Browse Source

OpenSubdiv: Only store edges topology for non-smooth edges

This change makes it so vertices of edge are only stored when edge
has non-zero crease. This allows to lower memory footprint of 1.5M
faces from 78 MiB to 54 MiB in the case all creases are zero.

Meshes with crease are more hard to predict due to array-based
storage, so it all depends on index of edge with crease. Worst case
(all edges are creased) still stays at 78 MiB.
master
Sergey Sharybin 2 years ago
parent
commit
efa4ae17f0
  1. 16
      intern/opensubdiv/internal/topology/mesh_topology.cc
  2. 4
      intern/opensubdiv/internal/topology/mesh_topology.h
  3. 29
      intern/opensubdiv/internal/topology/mesh_topology_compare.cc
  4. 30
      intern/opensubdiv/internal/topology/topology_refiner_factory.cc

16
intern/opensubdiv/internal/topology/mesh_topology.cc

@ -80,8 +80,6 @@ void MeshTopology::ensureVertexTagsSize(int num_vertices)
void MeshTopology::setNumEdges(int num_edges)
{
num_edges_ = num_edges;
edges_.resize(num_edges_);
}
int MeshTopology::getNumEdges() const
@ -112,6 +110,12 @@ void MeshTopology::getEdgeVertexIndices(int edge_index, int *v1, int *v2) const
assert(edge_index >= 0);
assert(edge_index < getNumEdges());
if (edge_index >= edges_.size()) {
*v1 = -1;
*v1 = -1;
return;
}
const Edge &edge = edges_[edge_index];
*v1 = edge.v1;
*v2 = edge.v2;
@ -122,6 +126,10 @@ bool MeshTopology::isEdgeEqual(int edge_index, int expected_v1, int expected_v2)
assert(edge_index >= 0);
assert(edge_index < getNumEdges());
if (edge_index >= edges_.size()) {
return false;
}
const Edge &edge = edges_[edge_index];
return edge.v1 == expected_v1 && edge.v2 == expected_v2;
}
@ -155,8 +163,8 @@ float MeshTopology::getEdgeSharpness(int edge_index) const
void MeshTopology::ensureNumEdgesAtLeast(int num_edges)
{
if (getNumEdges() < num_edges) {
setNumEdges(num_edges);
if (edges_.size() < num_edges) {
edges_.resize(num_edges);
}
}

4
intern/opensubdiv/internal/topology/mesh_topology.h

@ -125,8 +125,8 @@ class MeshTopology {
bool isEqualToConverter(const OpenSubdiv_Converter *converter) const;
protected:
// Unless full topology was specified the number of edges is not know ahead
// of a time.
// Edges are allowed to be stored sparsly, to save memory used by
// non-semi-sharp edges.
void ensureNumEdgesAtLeast(int num_edges);
// Geometry tags are stored sparsly.

29
intern/opensubdiv/internal/topology/mesh_topology_compare.cc

@ -71,16 +71,14 @@ bool isEqualGeometryEdge(const MeshTopology &mesh_topology, const OpenSubdiv_Con
return false;
}
for (int edge_index = 0; edge_index < num_requested_edges; ++edge_index) {
int requested_edge_vertices[2];
converter->getEdgeVertices(converter, edge_index, requested_edge_vertices);
if (!mesh_topology.isEdgeEqual(
edge_index, requested_edge_vertices[0], requested_edge_vertices[1])) {
printf("edge mismatch\n");
return false;
}
}
// NOTE: Ignoring the sharpness we don't really care of the content of the
// edges, they should be in the consistent state with faces and face-vertices.
// If that's not the case the mesh is invalid and comparison can not happen
// reliably.
//
// For sharpness it is important to know that edges are connecting same pair
// of vertices. But since sharpness is stored sparesly the connectivity will
// be checked when comparing edge sharpness.
return true;
}
@ -183,6 +181,17 @@ bool isEqualEdgeTags(const MeshTopology &mesh_topology, const OpenSubdiv_Convert
if (current_sharpness != requested_sharpness) {
return false;
}
if (current_sharpness < 1e-6f) {
continue;
}
int requested_edge_vertices[2];
converter->getEdgeVertices(converter, edge_index, requested_edge_vertices);
if (!mesh_topology.isEdgeEqual(
edge_index, requested_edge_vertices[0], requested_edge_vertices[1])) {
return false;
}
}
return true;

30
intern/opensubdiv/internal/topology/topology_refiner_factory.cc

@ -130,21 +130,6 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology
const bool full_topology_specified = converter->specifiesFullTopology(converter);
// Vertices of an edge.
//
// NOTE: Only specify for base mesh topology on our side.
// They will be provided to the topology refiner only if the full topology is
// specified.
if (converter->getNumEdges != nullptr) {
const int num_edges = converter->getNumEdges(converter);
for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
int edge_vertices[2];
converter->getEdgeVertices(converter, edge_index, edge_vertices);
base_mesh_topology->setEdgeVertexIndices(edge_index, edge_vertices[0], edge_vertices[1]);
}
}
// Vertices of face.
const int num_faces = converter->getNumFaces(converter);
for (int face_index = 0; face_index < num_faces; ++face_index) {
@ -186,12 +171,8 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology
const int num_edges = converter->getNumEdges(converter);
for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
// Vertices this edge connects.
int v1, v2;
base_mesh_topology->getEdgeVertexIndices(edge_index, &v1, &v2);
IndexArray dst_edge_vertices = getBaseEdgeVertices(refiner, edge_index);
dst_edge_vertices[0] = v1;
dst_edge_vertices[1] = v2;
converter->getEdgeVertices(converter, edge_index, &dst_edge_vertices[0]);
// Faces adjacent to this edge.
IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge_index);
@ -224,20 +205,21 @@ 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;
}
int edge_vertices[2];
converter->getEdgeVertices(converter, edge_index, edge_vertices);
base_mesh_topology->setEdgeVertexIndices(edge_index, edge_vertices[0], edge_vertices[1]);
base_mesh_topology->setEdgeSharpness(edge_index, sharpness);
if (full_topology_specified) {
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]);
if (base_edge_index == OpenSubdiv::Far::INDEX_INVALID) {
printf("OpenSubdiv Error: failed to find reconstructed edge\n");

Loading…
Cancel
Save