OpenSubdiv: Hide individual topology elements

Move all API to happen via MeshTopology.

This is a preparation for an upcoming memory optimization.
This commit is contained in:
Sergey Sharybin 2020-05-26 10:01:46 +02:00
parent 15bcfc5b19
commit 38b50fe393
4 changed files with 111 additions and 96 deletions

View File

@ -89,7 +89,7 @@ int MeshTopology::getNumEdges() const
return num_edges_;
}
void MeshTopology::setEdgevertexIndices(int edge_index, int v1, int v2)
void MeshTopology::setEdgeVertexIndices(int edge_index, int v1, int v2)
{
assert(edge_index >= 0);
assert(edge_index < getNumEdges());
@ -102,7 +102,7 @@ void MeshTopology::setEdgevertexIndices(int edge_index, int v1, int v2)
ensureNumEdgesAtLeast(edge_index + 1);
EdgeTopology &edge = getEdge(edge_index);
Edge &edge = edges_[edge_index];
// Prevent attempts to override edges.
// This is currently not supposed to happen.
@ -112,17 +112,23 @@ void MeshTopology::setEdgevertexIndices(int edge_index, int v1, int v2)
edge.v2 = v2;
}
EdgeTopology &MeshTopology::getEdge(int edge_index)
{
const MeshTopology *const_this = this;
return const_cast<EdgeTopology &>(const_this->getEdge(edge_index));
}
const EdgeTopology &MeshTopology::getEdge(int edge_index) const
void MeshTopology::getEdgeVertexIndices(int edge_index, int *v1, int *v2) const
{
assert(edge_index >= 0);
assert(edge_index < getNumEdges());
return edges_[edge_index];
const Edge &edge = edges_[edge_index];
*v1 = edge.v1;
*v2 = edge.v2;
}
bool MeshTopology::isEdgeEqual(int edge_index, int expected_v1, int expected_v2) const
{
assert(edge_index >= 0);
assert(edge_index < getNumEdges());
const Edge &edge = edges_[edge_index];
return edge.v1 == expected_v1 && edge.v2 == expected_v2;
}
void MeshTopology::setEdgeSharpness(int edge_index, float sharpness)
@ -130,7 +136,8 @@ void MeshTopology::setEdgeSharpness(int edge_index, float sharpness)
assert(edge_index >= 0);
assert(edge_index < getNumEdges());
assert(getEdge(edge_index).isValid());
Edge &edge = edges_[edge_index];
assert(edge.isValid());
if (sharpness < 1e-6f) {
return;
@ -183,30 +190,42 @@ int MeshTopology::getNumFaces() const
return num_faces_;
}
FaceTopology &MeshTopology::getFace(int face_index)
{
const MeshTopology *const_this = this;
return const_cast<FaceTopology &>(const_this->getFace(face_index));
}
const FaceTopology &MeshTopology::getFace(int face_index) const
void MeshTopology::setNumFaceVertices(int face_index, int num_face_vertices)
{
assert(face_index >= 0);
assert(face_index < getNumFaces());
return faces_[face_index];
Face &face = faces_[face_index];
face.setNumVertices(num_face_vertices);
}
void MeshTopology::setNumFaceVertices(int face_index, int num_face_vertices)
int MeshTopology::getNumFaceVertices(int face_index) const
{
FaceTopology &face = getFace(face_index);
face.setNumVertices(num_face_vertices);
assert(face_index >= 0);
assert(face_index < getNumFaces());
const Face &face = faces_[face_index];
return face.getNumVertices();
}
void MeshTopology::setFaceVertexIndices(int face_index, int *face_vertex_indices)
{
FaceTopology &face = getFace(face_index);
assert(face_index >= 0);
assert(face_index < getNumFaces());
Face &face = faces_[face_index];
face.setVertexIndices(face_vertex_indices);
}
bool MeshTopology::isFaceVertexIndicesEqual(int face_index,
const vector<int> &expected_vertices_of_face) const
{
assert(face_index >= 0);
assert(face_index < getNumFaces());
const Face &face = faces_[face_index];
return face.vertex_indices == expected_vertices_of_face;
}
} // namespace opensubdiv
} // namespace blender

View File

@ -29,58 +29,6 @@ struct OpenSubdiv_Converter;
namespace blender {
namespace opensubdiv {
class VertexTopologyTag {
public:
float sharpness = 0.0f;
};
class EdgeTopology {
public:
bool isValid() const
{
return v1 >= 0 && v2 >= 0;
}
int v1 = -1;
int v2 = -1;
};
class FaceTopology {
public:
void setNumVertices(int num_vertices)
{
vertex_indices.resize(num_vertices, -1);
}
void setVertexIndices(int *face_vertex_indices)
{
memcpy(vertex_indices.data(), face_vertex_indices, sizeof(int) * vertex_indices.size());
}
bool isValid() const
{
for (int vertex_index : vertex_indices) {
if (vertex_index < 0) {
return false;
}
}
return true;
}
int getNumVertices() const
{
return vertex_indices.size();
}
vector<int> vertex_indices;
};
class EdgeTopologyTag {
public:
float sharpness = 0.0f;
};
// Simplified representation of mesh topology.
// Only includes parts of actual mesh topology which is needed to perform
// comparison between Application side and OpenSubddiv side.
@ -112,10 +60,10 @@ class MeshTopology {
// on last edge index for which topology tag was specified.
int getNumEdges() const;
void setEdgevertexIndices(int edge_index, int v1, int v2);
void setEdgeVertexIndices(int edge_index, int v1, int v2);
void getEdgeVertexIndices(int edge_index, int *v1, int *v2) const;
EdgeTopology &getEdge(int edge_index);
const EdgeTopology &getEdge(int edge_index) const;
bool isEdgeEqual(int edge_index, int expected_v1, int expected_v2) const;
void setEdgeSharpness(int edge_index, float sharpness);
float getEdgeSharpness(int edge_index) const;
@ -127,12 +75,14 @@ class MeshTopology {
int getNumFaces() const;
FaceTopology &getFace(int face_index);
const FaceTopology &getFace(int face_index) const;
void setNumFaceVertices(int face_index, int num_face_vertices);
int getNumFaceVertices(int face_index) const;
void setFaceVertexIndices(int face_index, int *face_vertex_indices);
bool isFaceVertexIndicesEqual(int face_index,
const vector<int> &expected_vertices_of_face) const;
//////////////////////////////////////////////////////////////////////////////
// Comparison.
@ -152,15 +102,63 @@ class MeshTopology {
void ensureVertexTagsSize(int num_vertices);
void ensureEdgeTagsSize(int num_edges);
struct VertexTag {
float sharpness = 0.0f;
};
struct Edge {
bool isValid() const
{
return v1 >= 0 && v2 >= 0;
}
int v1 = -1;
int v2 = -1;
};
struct EdgeTag {
float sharpness = 0.0f;
};
struct Face {
void setNumVertices(int num_vertices)
{
vertex_indices.resize(num_vertices, -1);
}
void setVertexIndices(int *face_vertex_indices)
{
memcpy(vertex_indices.data(), face_vertex_indices, sizeof(int) * vertex_indices.size());
}
bool isValid() const
{
for (int vertex_index : vertex_indices) {
if (vertex_index < 0) {
return false;
}
}
return true;
}
int getNumVertices() const
{
return vertex_indices.size();
}
vector<int> vertex_indices;
};
int num_vertices_;
vector<VertexTopologyTag> vertex_tags_;
vector<VertexTag> vertex_tags_;
int num_edges_;
vector<EdgeTopology> edges_;
vector<EdgeTopologyTag> edge_tags_;
vector<Edge> edges_;
vector<EdgeTag> edge_tags_;
int num_faces_;
vector<FaceTopology> faces_;
vector<Face> faces_;
MEM_CXX_CLASS_ALLOC_FUNCS("MeshTopology");
};

View File

@ -75,9 +75,9 @@ bool isEqualGeometryEdge(const MeshTopology &mesh_topology, const OpenSubdiv_Con
int requested_edge_vertices[2];
converter->getEdgeVertices(converter, edge_index, requested_edge_vertices);
const EdgeTopology &current_edge = mesh_topology.getEdge(edge_index);
if (current_edge.v1 != requested_edge_vertices[0] ||
current_edge.v2 != requested_edge_vertices[1]) {
if (!mesh_topology.isEdgeEqual(
edge_index, requested_edge_vertices[0], requested_edge_vertices[1])) {
printf("edge mismatch\n");
return false;
}
}
@ -96,17 +96,15 @@ bool isEqualGeometryFace(const MeshTopology &mesh_topology, const OpenSubdiv_Con
vector<int> vertices_of_face;
for (int face_index = 0; face_index < num_requested_faces; ++face_index) {
const FaceTopology &current_face = mesh_topology.getFace(face_index);
int num_face_vertices = converter->getNumFaceVertices(converter, face_index);
if (current_face.getNumVertices() != num_face_vertices) {
if (mesh_topology.getNumFaceVertices(face_index) != num_face_vertices) {
return false;
}
vertices_of_face.resize(num_face_vertices);
converter->getFaceVertices(converter, face_index, vertices_of_face.data());
if (current_face.vertex_indices != vertices_of_face) {
if (!mesh_topology.isFaceVertexIndicesEqual(face_index, vertices_of_face)) {
return false;
}
}

View File

@ -52,7 +52,6 @@ template<>
inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology(
TopologyRefiner &refiner, const TopologyRefinerData &cb_data)
{
using blender::opensubdiv::FaceTopology;
using blender::opensubdiv::MeshTopology;
const OpenSubdiv_Converter *converter = cb_data.converter;
@ -121,7 +120,6 @@ template<>
inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology(
TopologyRefiner &refiner, const TopologyRefinerData &cb_data)
{
using blender::opensubdiv::EdgeTopology;
using blender::opensubdiv::MeshTopology;
using Far::IndexArray;
@ -141,7 +139,7 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology
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->setEdgeVertexIndices(edge_index, edge_vertices[0], edge_vertices[1]);
}
}
@ -185,10 +183,12 @@ 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.
const EdgeTopology &edge = base_mesh_topology->getEdge(edge_index);
int v1, v2;
base_mesh_topology->getEdgeVertexIndices(edge_index, &v1, &v2);
IndexArray dst_edge_vertices = getBaseEdgeVertices(refiner, edge_index);
dst_edge_vertices[0] = edge.v1;
dst_edge_vertices[1] = edge.v2;
dst_edge_vertices[0] = v1;
dst_edge_vertices[1] = v2;
// Faces adjacent to this edge.
IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge_index);