Blender  V3.3
mesh_topology_compare.cc
Go to the documentation of this file.
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 
20 
21 #include <cassert>
22 #include <cstring>
23 #include <opensubdiv/sdc/crease.h>
24 
25 #include "internal/base/type.h"
26 
28 
29 namespace blender {
30 namespace opensubdiv {
31 
32 namespace {
33 
35 // Quick preliminary checks.
36 
37 int getEffectiveNumEdges(const OpenSubdiv_Converter *converter)
38 {
39  if (converter->getNumEdges == nullptr) {
40  return 0;
41  }
42 
43  return converter->getNumEdges(converter);
44 }
45 
46 bool isEqualGeometryCounters(const MeshTopology &mesh_topology,
47  const OpenSubdiv_Converter *converter)
48 {
49  if (converter->getNumVertices(converter) != mesh_topology.getNumVertices()) {
50  return false;
51  }
52  if (converter->getNumFaces(converter) != mesh_topology.getNumFaces()) {
53  return false;
54  }
55  if (getEffectiveNumEdges(converter) != mesh_topology.getNumEdges()) {
56  return false;
57  }
58 
59  return true;
60 }
61 
63 // Geometry.
64 
65 // Edges.
66 
67 bool isEqualGeometryEdge(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
68 {
69  const int num_requested_edges = getEffectiveNumEdges(converter);
70  if (num_requested_edges != mesh_topology.getNumEdges()) {
71  return false;
72  }
73 
74  // NOTE: Ignoring the sharpness we don't really care of the content of the
75  // edges, they should be in the consistent state with faces and face-vertices.
76  // If that's not the case the mesh is invalid and comparison can not happen
77  // reliably.
78  //
79  // For sharpness it is important to know that edges are connecting same pair
80  // of vertices. But since sharpness is stored sparesly the connectivity will
81  // be checked when comparing edge sharpness.
82 
83  return true;
84 }
85 
86 // Faces.
87 
88 bool isEqualGeometryFace(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
89 {
90  const int num_requested_faces = converter->getNumFaces(converter);
91  if (num_requested_faces != mesh_topology.getNumFaces()) {
92  return false;
93  }
94 
95  vector<int> vertices_of_face;
96  for (int face_index = 0; face_index < num_requested_faces; ++face_index) {
97  int num_face_vertices = converter->getNumFaceVertices(converter, face_index);
98  if (mesh_topology.getNumFaceVertices(face_index) != num_face_vertices) {
99  return false;
100  }
101 
102  vertices_of_face.resize(num_face_vertices);
103  converter->getFaceVertices(converter, face_index, vertices_of_face.data());
104 
105  if (!mesh_topology.isFaceVertexIndicesEqual(face_index, vertices_of_face)) {
106  return false;
107  }
108  }
109 
110  return true;
111 }
112 
113 // Geometry comparison entry point.
114 
115 bool isEqualGeometry(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
116 {
117  if (!isEqualGeometryEdge(mesh_topology, converter)) {
118  return false;
119  }
120  if (!isEqualGeometryFace(mesh_topology, converter)) {
121  return false;
122  }
123 
124  return true;
125 }
126 
128 // Geometry tags.
129 
130 // Vertices.
131 
132 // TODO(sergey): Make this function usable by factory as well.
133 float getEffectiveVertexSharpness(const OpenSubdiv_Converter *converter, const int vertex_index)
134 {
135  if (converter->isInfiniteSharpVertex != nullptr &&
136  converter->isInfiniteSharpVertex(converter, vertex_index)) {
137  return OpenSubdiv::Sdc::Crease::SHARPNESS_INFINITE;
138  }
139 
140  if (converter->getVertexSharpness != nullptr) {
141  return converter->getVertexSharpness(converter, vertex_index);
142  }
143 
144  return 0.0f;
145 }
146 
147 bool isEqualVertexTags(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
148 {
149  const int num_vertices = mesh_topology.getNumVertices();
150  for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) {
151  const float current_sharpness = mesh_topology.getVertexSharpness(vertex_index);
152  const float requested_sharpness = getEffectiveVertexSharpness(converter, vertex_index);
153 
154  if (current_sharpness != requested_sharpness) {
155  return false;
156  }
157  }
158 
159  return true;
160 }
161 
162 // Edges.
163 
164 // TODO(sergey): Make this function usable by factory as well.
165 float getEffectiveEdgeSharpness(const OpenSubdiv_Converter *converter, const int edge_index)
166 {
167  if (converter->getEdgeSharpness != nullptr) {
168  return converter->getEdgeSharpness(converter, edge_index);
169  }
170 
171  return 0.0f;
172 }
173 
174 bool isEqualEdgeTags(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
175 {
176  const int num_edges = mesh_topology.getNumEdges();
177  for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
178  const float current_sharpness = mesh_topology.getEdgeSharpness(edge_index);
179  const float requested_sharpness = getEffectiveEdgeSharpness(converter, edge_index);
180 
181  if (current_sharpness != requested_sharpness) {
182  return false;
183  }
184 
185  if (current_sharpness < 1e-6f) {
186  continue;
187  }
188 
189  int requested_edge_vertices[2];
190  converter->getEdgeVertices(converter, edge_index, requested_edge_vertices);
191  if (!mesh_topology.isEdgeEqual(
192  edge_index, requested_edge_vertices[0], requested_edge_vertices[1])) {
193  return false;
194  }
195  }
196 
197  return true;
198 }
199 
200 // Tags comparison entry point.
201 
202 bool isEqualTags(const MeshTopology &mesh_topology, const OpenSubdiv_Converter *converter)
203 {
204  if (!isEqualVertexTags(mesh_topology, converter)) {
205  return false;
206  }
207  if (!isEqualEdgeTags(mesh_topology, converter)) {
208  return false;
209  }
210 
211  return true;
212 }
213 
214 } // namespace
215 
217 // Entry point.
218 
220 {
221  // Preliminary checks.
222  if (!isEqualGeometryCounters(*this, converter)) {
223  return false;
224  }
225 
226  // Geometry.
227  if (!isEqualGeometry(*this, converter)) {
228  return false;
229  }
230 
231  // Tags.
232  if (!isEqualTags(*this, converter)) {
233  return false;
234  }
235 
236  return true;
237 }
238 
239 } // namespace opensubdiv
240 } // namespace blender
bool isEqualToConverter(const OpenSubdiv_Converter *converter) const
void(* getFaceVertices)(const struct OpenSubdiv_Converter *converter, const int face_index, int *face_vertices)
float(* getVertexSharpness)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
void(* getEdgeVertices)(const struct OpenSubdiv_Converter *converter, const int edge_index, int edge_vertices[2])
bool(* isInfiniteSharpVertex)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
int(* getNumVertices)(const struct OpenSubdiv_Converter *converter)
float(* getEdgeSharpness)(const struct OpenSubdiv_Converter *converter, const int edge_index)
int(* getNumEdges)(const struct OpenSubdiv_Converter *converter)
int(* getNumFaces)(const struct OpenSubdiv_Converter *converter)
int(* getNumFaceVertices)(const struct OpenSubdiv_Converter *converter, const int face_index)