2020-05-19 11:39:07 +02:00
|
|
|
// 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 {
|
|
|
|
|
|
2020-05-19 16:19:40 +02:00
|
|
|
MeshTopology::MeshTopology() : num_vertices_(0), num_edges_(0), num_faces_(0)
|
2020-05-19 11:39:07 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MeshTopology::~MeshTopology()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-19 12:38:52 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Vertices.
|
|
|
|
|
|
2020-05-19 11:39:07 +02:00
|
|
|
void MeshTopology::setNumVertices(int num_vertices)
|
|
|
|
|
{
|
2020-05-19 12:38:52 +02:00
|
|
|
num_vertices_ = num_vertices;
|
2020-05-19 11:39:07 +02:00
|
|
|
}
|
2020-05-19 12:38:52 +02:00
|
|
|
|
2020-05-19 11:39:07 +02:00
|
|
|
int MeshTopology::getNumVertices() const
|
|
|
|
|
{
|
2020-05-19 12:38:52 +02:00
|
|
|
return num_vertices_;
|
2020-05-19 11:39:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshTopology::setVertexSharpness(int vertex_index, float sharpness)
|
|
|
|
|
{
|
|
|
|
|
assert(vertex_index >= 0);
|
2020-05-19 12:38:52 +02:00
|
|
|
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());
|
2020-05-19 11:39:07 +02:00
|
|
|
|
2020-05-19 12:38:52 +02:00
|
|
|
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_;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
void MeshTopology::setEdgeVertexIndices(int edge_index, int v1, int v2)
|
2020-05-19 12:38:52 +02:00
|
|
|
{
|
|
|
|
|
assert(edge_index >= 0);
|
2020-05-19 15:48:57 +02:00
|
|
|
assert(edge_index < getNumEdges());
|
|
|
|
|
|
|
|
|
|
assert(v1 >= 0);
|
|
|
|
|
assert(v1 < getNumVertices());
|
|
|
|
|
|
|
|
|
|
assert(v2 >= 0);
|
|
|
|
|
assert(v2 < getNumVertices());
|
2020-05-19 12:38:52 +02:00
|
|
|
|
|
|
|
|
ensureNumEdgesAtLeast(edge_index + 1);
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
Edge &edge = edges_[edge_index];
|
2020-05-19 15:48:57 +02:00
|
|
|
edge.v1 = v1;
|
|
|
|
|
edge.v2 = v2;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
void MeshTopology::getEdgeVertexIndices(int edge_index, int *v1, int *v2) const
|
2020-05-19 15:48:57 +02:00
|
|
|
{
|
2020-05-26 10:01:46 +02:00
|
|
|
assert(edge_index >= 0);
|
|
|
|
|
assert(edge_index < getNumEdges());
|
|
|
|
|
|
2020-05-26 12:42:13 +02:00
|
|
|
if (edge_index >= edges_.size()) {
|
|
|
|
|
*v1 = -1;
|
|
|
|
|
*v1 = -1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
const Edge &edge = edges_[edge_index];
|
|
|
|
|
*v1 = edge.v1;
|
|
|
|
|
*v2 = edge.v2;
|
2020-05-19 15:48:57 +02:00
|
|
|
}
|
2020-05-26 10:01:46 +02:00
|
|
|
|
|
|
|
|
bool MeshTopology::isEdgeEqual(int edge_index, int expected_v1, int expected_v2) const
|
2020-05-19 15:48:57 +02:00
|
|
|
{
|
|
|
|
|
assert(edge_index >= 0);
|
|
|
|
|
assert(edge_index < getNumEdges());
|
|
|
|
|
|
2020-05-26 12:42:13 +02:00
|
|
|
if (edge_index >= edges_.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
const Edge &edge = edges_[edge_index];
|
|
|
|
|
return edge.v1 == expected_v1 && edge.v2 == expected_v2;
|
2020-05-19 15:48:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshTopology::setEdgeSharpness(int edge_index, float sharpness)
|
|
|
|
|
{
|
|
|
|
|
assert(edge_index >= 0);
|
|
|
|
|
assert(edge_index < getNumEdges());
|
|
|
|
|
|
2020-05-19 12:38:52 +02:00
|
|
|
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)
|
|
|
|
|
{
|
2020-05-26 12:42:13 +02:00
|
|
|
if (edges_.size() < num_edges) {
|
|
|
|
|
edges_.resize(num_edges);
|
2020-05-19 12:38:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MeshTopology::ensureEdgeTagsSize(int num_edges)
|
|
|
|
|
{
|
|
|
|
|
if (edge_tags_.size() < num_edges) {
|
|
|
|
|
edge_tags_.resize(num_edges);
|
|
|
|
|
}
|
2020-05-19 11:39:07 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-19 16:19:40 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Faces.
|
|
|
|
|
|
|
|
|
|
void MeshTopology::setNumFaces(int num_faces)
|
|
|
|
|
{
|
|
|
|
|
num_faces_ = num_faces;
|
|
|
|
|
|
2020-05-26 10:54:46 +02:00
|
|
|
// 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);
|
2020-05-19 16:19:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int MeshTopology::getNumFaces() const
|
|
|
|
|
{
|
|
|
|
|
return num_faces_;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
void MeshTopology::setNumFaceVertices(int face_index, int num_face_vertices)
|
2020-05-19 16:19:40 +02:00
|
|
|
{
|
|
|
|
|
assert(face_index >= 0);
|
|
|
|
|
assert(face_index < getNumFaces());
|
|
|
|
|
|
2020-05-26 10:54:46 +02:00
|
|
|
faces_first_vertex_index_[face_index + 1] = faces_first_vertex_index_[face_index] +
|
|
|
|
|
num_face_vertices;
|
2020-05-19 16:19:40 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
int MeshTopology::getNumFaceVertices(int face_index) const
|
2020-05-19 16:19:40 +02:00
|
|
|
{
|
2020-05-26 10:01:46 +02:00
|
|
|
assert(face_index >= 0);
|
|
|
|
|
assert(face_index < getNumFaces());
|
|
|
|
|
|
2020-05-26 10:54:46 +02:00
|
|
|
return faces_first_vertex_index_[face_index + 1] - faces_first_vertex_index_[face_index];
|
2020-05-19 16:19:40 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:54:46 +02:00
|
|
|
void MeshTopology::setFaceVertexIndices(int face_index,
|
|
|
|
|
int num_face_vertex_indices,
|
|
|
|
|
const int *face_vertex_indices)
|
2020-05-19 16:19:40 +02:00
|
|
|
{
|
2020-05-26 10:01:46 +02:00
|
|
|
assert(face_index >= 0);
|
|
|
|
|
assert(face_index < getNumFaces());
|
2020-05-26 10:54:46 +02:00
|
|
|
assert(num_face_vertex_indices == getNumFaceVertices(face_index));
|
2020-05-26 10:01:46 +02:00
|
|
|
|
2020-05-26 10:54:46 +02:00
|
|
|
int *face_vertex_indices_storage = getFaceVertexIndicesStorage(face_index);
|
|
|
|
|
memcpy(face_vertex_indices_storage, face_vertex_indices, sizeof(int) * num_face_vertex_indices);
|
2020-05-19 16:19:40 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-26 10:01:46 +02:00
|
|
|
bool MeshTopology::isFaceVertexIndicesEqual(int face_index,
|
2020-05-26 10:54:46 +02:00
|
|
|
int num_expected_face_vertex_indices,
|
|
|
|
|
const int *expected_face_vertex_indices) const
|
2020-05-26 10:01:46 +02:00
|
|
|
{
|
|
|
|
|
assert(face_index >= 0);
|
|
|
|
|
assert(face_index < getNumFaces());
|
|
|
|
|
|
2020-05-26 10:54:46 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2020-05-26 10:01:46 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-19 11:39:07 +02:00
|
|
|
} // namespace opensubdiv
|
|
|
|
|
} // namespace blender
|