diff options
Diffstat (limited to 'intern/opensubdiv/internal/topology/mesh_topology.cc')
-rw-r--r-- | intern/opensubdiv/internal/topology/mesh_topology.cc | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/intern/opensubdiv/internal/topology/mesh_topology.cc b/intern/opensubdiv/internal/topology/mesh_topology.cc new file mode 100644 index 00000000000..9197a5c1b54 --- /dev/null +++ b/intern/opensubdiv/internal/topology/mesh_topology.cc @@ -0,0 +1,273 @@ +// 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> + +namespace blender { +namespace opensubdiv { + +MeshTopology::MeshTopology() : num_vertices_(0), num_edges_(0), num_faces_(0) +{ +} + +MeshTopology::~MeshTopology() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// Vertices. + +void MeshTopology::setNumVertices(int num_vertices) +{ + num_vertices_ = num_vertices; +} + +int MeshTopology::getNumVertices() const +{ + return num_vertices_; +} + +void MeshTopology::setVertexSharpness(int vertex_index, float sharpness) +{ + assert(vertex_index >= 0); + assert(vertex_index < getNumVertices()); + + ensureVertexTagsSize(vertex_index + 1); + + vertex_tags_[vertex_index].sharpness = sharpness; +} + +float MeshTopology::getVertexSharpness(int vertex_index) const +{ + assert(vertex_index >= 0); + assert(vertex_index < getNumVertices()); + + if (vertex_index >= vertex_tags_.size()) { + // Sharpness for the vertex was never provided. + return 0.0f; + } + + return vertex_tags_[vertex_index].sharpness; +} + +void MeshTopology::ensureVertexTagsSize(int num_vertices) +{ + if (vertex_tags_.size() < num_vertices) { + vertex_tags_.resize(num_vertices); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Edges. + +void MeshTopology::setNumEdges(int num_edges) +{ + num_edges_ = num_edges; +} + +int MeshTopology::getNumEdges() const +{ + return num_edges_; +} + +void MeshTopology::setEdgeVertexIndices(int edge_index, int v1, int v2) +{ + assert(edge_index >= 0); + assert(edge_index < getNumEdges()); + + assert(v1 >= 0); + assert(v1 < getNumVertices()); + + assert(v2 >= 0); + assert(v2 < getNumVertices()); + + ensureNumEdgesAtLeast(edge_index + 1); + + Edge &edge = edges_[edge_index]; + edge.v1 = v1; + edge.v2 = v2; +} + +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; +} + +bool MeshTopology::isEdgeEqual(int edge_index, int expected_v1, int expected_v2) const +{ + 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; +} + +void MeshTopology::setEdgeSharpness(int edge_index, float sharpness) +{ + assert(edge_index >= 0); + assert(edge_index < getNumEdges()); + + if (sharpness < 1e-6f) { + return; + } + + ensureEdgeTagsSize(edge_index + 1); + + edge_tags_[edge_index].sharpness = sharpness; +} + +float MeshTopology::getEdgeSharpness(int edge_index) const +{ + assert(edge_index >= 0); + + if (edge_index >= edge_tags_.size()) { + // NOTE: It's possible that full topology is not known and that there was + // never sharpness assigned to any of the edges. + return 0.0f; + } + + return edge_tags_[edge_index].sharpness; +} + +void MeshTopology::ensureNumEdgesAtLeast(int num_edges) +{ + if (edges_.size() < num_edges) { + edges_.resize(num_edges); + } +} + +void MeshTopology::ensureEdgeTagsSize(int num_edges) +{ + if (edge_tags_.size() < num_edges) { + edge_tags_.resize(num_edges); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Faces. + +void MeshTopology::setNumFaces(int num_faces) +{ + num_faces_ = num_faces; + + // NOTE: Extra element to store fake face past the last real one to make it + // possible to calculate number of verticies in the last face. + faces_first_vertex_index_.resize(num_faces + 1, 0); +} + +int MeshTopology::getNumFaces() const +{ + return num_faces_; +} + +void MeshTopology::setNumFaceVertices(int face_index, int num_face_vertices) +{ + assert(face_index >= 0); + assert(face_index < getNumFaces()); + + faces_first_vertex_index_[face_index + 1] = faces_first_vertex_index_[face_index] + + num_face_vertices; +} + +int MeshTopology::getNumFaceVertices(int face_index) const +{ + assert(face_index >= 0); + assert(face_index < getNumFaces()); + + return faces_first_vertex_index_[face_index + 1] - faces_first_vertex_index_[face_index]; +} + +void MeshTopology::setFaceVertexIndices(int face_index, + int num_face_vertex_indices, + const int *face_vertex_indices) +{ + assert(face_index >= 0); + assert(face_index < getNumFaces()); + assert(num_face_vertex_indices == getNumFaceVertices(face_index)); + + int *face_vertex_indices_storage = getFaceVertexIndicesStorage(face_index); + memcpy(face_vertex_indices_storage, face_vertex_indices, sizeof(int) * num_face_vertex_indices); +} + +bool MeshTopology::isFaceVertexIndicesEqual(int face_index, + int num_expected_face_vertex_indices, + const int *expected_face_vertex_indices) const +{ + assert(face_index >= 0); + assert(face_index < getNumFaces()); + + if (getNumFaceVertices(face_index) != num_expected_face_vertex_indices) { + return false; + } + + const int *face_vertex_indices_storage = getFaceVertexIndicesStorage(face_index); + return memcmp(face_vertex_indices_storage, + expected_face_vertex_indices, + sizeof(int) * num_expected_face_vertex_indices) == 0; +} + +bool MeshTopology::isFaceVertexIndicesEqual(int face_index, + const vector<int> &expected_face_vertex_indices) const +{ + return isFaceVertexIndicesEqual( + face_index, expected_face_vertex_indices.size(), expected_face_vertex_indices.data()); +} + +int *MeshTopology::getFaceVertexIndicesStorage(int face_index) +{ + const MeshTopology *const_this = this; + return const_cast<int *>(const_this->getFaceVertexIndicesStorage(face_index)); +} +const int *MeshTopology::getFaceVertexIndicesStorage(int face_index) const +{ + assert(face_index >= 0); + assert(face_index < getNumFaces()); + + const int offset = faces_first_vertex_index_[face_index]; + return face_vertex_indices_.data() + offset; +} + +//////////////////////////////////////////////////////////////////////////////// +// Pipeline related. + +void MeshTopology::finishResizeTopology() +{ + if (!faces_first_vertex_index_.empty()) { + face_vertex_indices_.resize(faces_first_vertex_index_.back()); + } +} + +} // namespace opensubdiv +} // namespace blender |