1 // Copyright 2020 Blender Foundation. All rights reserved.
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software Foundation,
15 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 //
17 // Author: Sergey Sharybin
18 
19 #include "internal/topology/mesh_topology.h"
20 
21 #include <cassert>
22 
23 namespace blender {
24 namespace opensubdiv {
25 
MeshTopology()26 MeshTopology::MeshTopology() : num_vertices_(0), num_edges_(0), num_faces_(0)
27 {
28 }
29 
~MeshTopology()30 MeshTopology::~MeshTopology()
31 {
32 }
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 // Vertices.
36 
setNumVertices(int num_vertices)37 void MeshTopology::setNumVertices(int num_vertices)
38 {
39   num_vertices_ = num_vertices;
40 }
41 
getNumVertices() const42 int MeshTopology::getNumVertices() const
43 {
44   return num_vertices_;
45 }
46 
setVertexSharpness(int vertex_index,float sharpness)47 void MeshTopology::setVertexSharpness(int vertex_index, float sharpness)
48 {
49   assert(vertex_index >= 0);
50   assert(vertex_index < getNumVertices());
51 
52   ensureVertexTagsSize(vertex_index + 1);
53 
54   vertex_tags_[vertex_index].sharpness = sharpness;
55 }
56 
getVertexSharpness(int vertex_index) const57 float MeshTopology::getVertexSharpness(int vertex_index) const
58 {
59   assert(vertex_index >= 0);
60   assert(vertex_index < getNumVertices());
61 
62   if (vertex_index >= vertex_tags_.size()) {
63     // Sharpness for the vertex was never provided.
64     return 0.0f;
65   }
66 
67   return vertex_tags_[vertex_index].sharpness;
68 }
69 
ensureVertexTagsSize(int num_vertices)70 void MeshTopology::ensureVertexTagsSize(int num_vertices)
71 {
72   if (vertex_tags_.size() < num_vertices) {
73     vertex_tags_.resize(num_vertices);
74   }
75 }
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 // Edges.
79 
setNumEdges(int num_edges)80 void MeshTopology::setNumEdges(int num_edges)
81 {
82   num_edges_ = num_edges;
83 }
84 
getNumEdges() const85 int MeshTopology::getNumEdges() const
86 {
87   return num_edges_;
88 }
89 
setEdgeVertexIndices(int edge_index,int v1,int v2)90 void MeshTopology::setEdgeVertexIndices(int edge_index, int v1, int v2)
91 {
92   assert(edge_index >= 0);
93   assert(edge_index < getNumEdges());
94 
95   assert(v1 >= 0);
96   assert(v1 < getNumVertices());
97 
98   assert(v2 >= 0);
99   assert(v2 < getNumVertices());
100 
101   ensureNumEdgesAtLeast(edge_index + 1);
102 
103   Edge &edge = edges_[edge_index];
104   edge.v1 = v1;
105   edge.v2 = v2;
106 }
107 
getEdgeVertexIndices(int edge_index,int * v1,int * v2) const108 void MeshTopology::getEdgeVertexIndices(int edge_index, int *v1, int *v2) const
109 {
110   assert(edge_index >= 0);
111   assert(edge_index < getNumEdges());
112 
113   if (edge_index >= edges_.size()) {
114     *v1 = -1;
115     *v1 = -1;
116     return;
117   }
118 
119   const Edge &edge = edges_[edge_index];
120   *v1 = edge.v1;
121   *v2 = edge.v2;
122 }
123 
isEdgeEqual(int edge_index,int expected_v1,int expected_v2) const124 bool MeshTopology::isEdgeEqual(int edge_index, int expected_v1, int expected_v2) const
125 {
126   assert(edge_index >= 0);
127   assert(edge_index < getNumEdges());
128 
129   if (edge_index >= edges_.size()) {
130     return false;
131   }
132 
133   const Edge &edge = edges_[edge_index];
134   return edge.v1 == expected_v1 && edge.v2 == expected_v2;
135 }
136 
setEdgeSharpness(int edge_index,float sharpness)137 void MeshTopology::setEdgeSharpness(int edge_index, float sharpness)
138 {
139   assert(edge_index >= 0);
140   assert(edge_index < getNumEdges());
141 
142   if (sharpness < 1e-6f) {
143     return;
144   }
145 
146   ensureEdgeTagsSize(edge_index + 1);
147 
148   edge_tags_[edge_index].sharpness = sharpness;
149 }
150 
getEdgeSharpness(int edge_index) const151 float MeshTopology::getEdgeSharpness(int edge_index) const
152 {
153   assert(edge_index >= 0);
154 
155   if (edge_index >= edge_tags_.size()) {
156     // NOTE: It's possible that full topology is not known and that there was
157     // never sharpness assigned to any of the edges.
158     return 0.0f;
159   }
160 
161   return edge_tags_[edge_index].sharpness;
162 }
163 
ensureNumEdgesAtLeast(int num_edges)164 void MeshTopology::ensureNumEdgesAtLeast(int num_edges)
165 {
166   if (edges_.size() < num_edges) {
167     edges_.resize(num_edges);
168   }
169 }
170 
ensureEdgeTagsSize(int num_edges)171 void MeshTopology::ensureEdgeTagsSize(int num_edges)
172 {
173   if (edge_tags_.size() < num_edges) {
174     edge_tags_.resize(num_edges);
175   }
176 }
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 // Faces.
180 
setNumFaces(int num_faces)181 void MeshTopology::setNumFaces(int num_faces)
182 {
183   num_faces_ = num_faces;
184 
185   // NOTE: Extra element to store fake face past the last real one to make it
186   // possible to calculate number of verticies in the last face.
187   faces_first_vertex_index_.resize(num_faces + 1, 0);
188 }
189 
getNumFaces() const190 int MeshTopology::getNumFaces() const
191 {
192   return num_faces_;
193 }
194 
setNumFaceVertices(int face_index,int num_face_vertices)195 void MeshTopology::setNumFaceVertices(int face_index, int num_face_vertices)
196 {
197   assert(face_index >= 0);
198   assert(face_index < getNumFaces());
199 
200   faces_first_vertex_index_[face_index + 1] = faces_first_vertex_index_[face_index] +
201                                               num_face_vertices;
202 }
203 
getNumFaceVertices(int face_index) const204 int MeshTopology::getNumFaceVertices(int face_index) const
205 {
206   assert(face_index >= 0);
207   assert(face_index < getNumFaces());
208 
209   return faces_first_vertex_index_[face_index + 1] - faces_first_vertex_index_[face_index];
210 }
211 
setFaceVertexIndices(int face_index,int num_face_vertex_indices,const int * face_vertex_indices)212 void MeshTopology::setFaceVertexIndices(int face_index,
213                                         int num_face_vertex_indices,
214                                         const int *face_vertex_indices)
215 {
216   assert(face_index >= 0);
217   assert(face_index < getNumFaces());
218   assert(num_face_vertex_indices == getNumFaceVertices(face_index));
219 
220   int *face_vertex_indices_storage = getFaceVertexIndicesStorage(face_index);
221   memcpy(face_vertex_indices_storage, face_vertex_indices, sizeof(int) * num_face_vertex_indices);
222 }
223 
isFaceVertexIndicesEqual(int face_index,int num_expected_face_vertex_indices,const int * expected_face_vertex_indices) const224 bool MeshTopology::isFaceVertexIndicesEqual(int face_index,
225                                             int num_expected_face_vertex_indices,
226                                             const int *expected_face_vertex_indices) const
227 {
228   assert(face_index >= 0);
229   assert(face_index < getNumFaces());
230 
231   if (getNumFaceVertices(face_index) != num_expected_face_vertex_indices) {
232     return false;
233   }
234 
235   const int *face_vertex_indices_storage = getFaceVertexIndicesStorage(face_index);
236   return memcmp(face_vertex_indices_storage,
237                 expected_face_vertex_indices,
238                 sizeof(int) * num_expected_face_vertex_indices) == 0;
239 }
240 
isFaceVertexIndicesEqual(int face_index,const vector<int> & expected_face_vertex_indices) const241 bool MeshTopology::isFaceVertexIndicesEqual(int face_index,
242                                             const vector<int> &expected_face_vertex_indices) const
243 {
244   return isFaceVertexIndicesEqual(
245       face_index, expected_face_vertex_indices.size(), expected_face_vertex_indices.data());
246 }
247 
getFaceVertexIndicesStorage(int face_index)248 int *MeshTopology::getFaceVertexIndicesStorage(int face_index)
249 {
250   const MeshTopology *const_this = this;
251   return const_cast<int *>(const_this->getFaceVertexIndicesStorage(face_index));
252 }
getFaceVertexIndicesStorage(int face_index) const253 const int *MeshTopology::getFaceVertexIndicesStorage(int face_index) const
254 {
255   assert(face_index >= 0);
256   assert(face_index < getNumFaces());
257 
258   const int offset = faces_first_vertex_index_[face_index];
259   return face_vertex_indices_.data() + offset;
260 }
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 // Pipeline related.
264 
finishResizeTopology()265 void MeshTopology::finishResizeTopology()
266 {
267   if (!faces_first_vertex_index_.empty()) {
268     face_vertex_indices_.resize(faces_first_vertex_index_.back());
269   }
270 }
271 
272 }  // namespace opensubdiv
273 }  // namespace blender
274