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