💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

436 lines
8.2 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <engine/geom/mesh.hpp>
  20. #include <stdexcept>
  21. namespace geom {
  22. mesh::mesh(const mesh& other)
  23. {
  24. *this = other;
  25. }
  26. mesh::~mesh()
  27. {
  28. clear();
  29. }
  30. mesh& mesh::operator=(const mesh& other)
  31. {
  32. // Clear the mesh
  33. clear();
  34. // Resize vertices, edges, and faces
  35. vertices.resize(other.vertices.size());
  36. edges.resize(other.edges.size());
  37. faces.resize(other.faces.size());
  38. // Allocate vertices
  39. for (std::size_t i = 0; i < vertices.size(); ++i)
  40. vertices[i] = new vertex();
  41. // Allocate edges
  42. for (std::size_t i = 0; i < edges.size(); ++i)
  43. {
  44. edges[i] = new edge();
  45. edges[i]->symmetric = new edge();
  46. edges[i]->symmetric->symmetric = edges[i];
  47. }
  48. // Allocate faces
  49. for (std::size_t i = 0; i < faces.size(); ++i)
  50. faces[i] = new face();
  51. // Copy vertices
  52. for (std::size_t i = 0; i < vertices.size(); ++i)
  53. {
  54. vertex* va = vertices[i];
  55. const vertex* vb = other.vertices[i];
  56. va->index = vb->index;
  57. va->position = vb->position;
  58. va->edge = nullptr;
  59. if (vb->edge)
  60. {
  61. va->edge = edges[vb->edge->index];
  62. if (vb->edge != other.edges[vb->edge->index])
  63. va->edge = va->edge->symmetric;
  64. }
  65. }
  66. // Copy edges
  67. for (std::size_t i = 0; i < edges.size(); ++i)
  68. {
  69. edge* ea = edges[i];
  70. const edge* eb = other.edges[i];
  71. for (std::size_t j = 0; j < 2; ++j)
  72. {
  73. ea->index = eb->index;
  74. ea->vertex = vertices[eb->vertex->index];
  75. ea->face = nullptr;
  76. if (eb->face)
  77. ea->face = faces[eb->face->index];
  78. ea->previous = edges[eb->previous->index];
  79. if (eb->previous != other.edges[eb->previous->index])
  80. ea->previous = ea->previous->symmetric;
  81. ea->next = edges[eb->next->index];
  82. if (eb->next != other.edges[eb->next->index])
  83. ea->next = ea->next->symmetric;
  84. ea = ea->symmetric;
  85. eb = eb->symmetric;
  86. }
  87. }
  88. // Copy faces
  89. for (std::size_t i = 0; i < faces.size(); ++i)
  90. {
  91. face* fa = faces[i];
  92. const face* fb = other.faces[i];
  93. fa->index = fb->index;
  94. fa->edge = edges[fb->edge->index];
  95. if (fb->edge != other.edges[fb->edge->index])
  96. fa->edge = fa->edge->symmetric;
  97. }
  98. return *this;
  99. }
  100. void mesh::clear() noexcept
  101. {
  102. // Deallocate vertices
  103. for (mesh::vertex* vertex: vertices)
  104. delete vertex;
  105. // Deallocate edges
  106. for (mesh::edge* edge: edges)
  107. {
  108. delete edge->symmetric;
  109. delete edge;
  110. }
  111. // Deallocate faces
  112. for (mesh::face* face: faces)
  113. delete face;
  114. vertices.clear();
  115. edges.clear();
  116. faces.clear();
  117. }
  118. mesh::vertex* mesh::add_vertex(const float3& position)
  119. {
  120. mesh::vertex* vertex = new mesh::vertex
  121. {
  122. vertices.size(),
  123. nullptr,
  124. position
  125. };
  126. vertices.push_back(vertex);
  127. return vertex;
  128. }
  129. mesh::edge* mesh::add_edge(mesh::vertex* a, mesh::vertex* b)
  130. {
  131. mesh::edge* ab = new mesh::edge();
  132. mesh::edge* ba = new mesh::edge();
  133. ab->index = edges.size();
  134. ab->vertex = a;
  135. ab->face = nullptr;
  136. ab->previous = ba;
  137. ab->next = ba;
  138. ab->symmetric = ba;
  139. ba->index = edges.size();
  140. ba->vertex = b;
  141. ba->face = nullptr;
  142. ba->previous = ab;
  143. ba->next = ab;
  144. ba->symmetric = ab;
  145. if (!a->edge)
  146. {
  147. a->edge = ab;
  148. }
  149. else
  150. {
  151. mesh::edge* a_in = find_free_incident(a);
  152. mesh::edge* a_out = a_in->next;
  153. a_in->next = ab;
  154. ab->previous = a_in;
  155. ba->next = a_out;
  156. a_out->previous = ba;
  157. }
  158. if (!b->edge)
  159. {
  160. b->edge = ba;
  161. }
  162. else
  163. {
  164. mesh::edge* b_in = find_free_incident(b);
  165. mesh::edge* b_out = b_in->next;
  166. b_in->next = ba;
  167. ba->previous = b_in;
  168. ab->next = b_out;
  169. b_out->previous = ab;
  170. }
  171. // Add edge
  172. edges.push_back(ab);
  173. return ab;
  174. }
  175. mesh::face* mesh::add_face(const loop& loop)
  176. {
  177. if (loop.empty())
  178. {
  179. throw std::runtime_error("Empty edge loop");
  180. }
  181. // Validate edge loop
  182. for (std::size_t i = 0; i < loop.size(); ++i)
  183. {
  184. mesh::edge* current = loop[i];
  185. mesh::edge* next = loop[(i + 1) % loop.size()];
  186. if (current->symmetric->vertex != next->vertex)
  187. {
  188. // Disconnected edge loop
  189. throw std::runtime_error("Disconnected edge loop");
  190. }
  191. if (current->face)
  192. {
  193. // This edge already has a face
  194. throw std::runtime_error("Non-manifold mesh 1");
  195. }
  196. }
  197. // Make edges adjacent
  198. for (std::size_t i = 0; i < loop.size(); ++i)
  199. {
  200. if (!make_adjacent(loop[i], loop[(i + 1) % loop.size()]))
  201. {
  202. throw std::runtime_error("Non-manifold mesh 2");
  203. }
  204. }
  205. // Create face
  206. mesh::face* face = new mesh::face();
  207. face->edge = loop[0];
  208. face->index = faces.size();
  209. // Add face
  210. faces.push_back(face);
  211. // Connect edges to the face
  212. for (mesh::edge* edge: loop)
  213. {
  214. edge->face = face;
  215. }
  216. return face;
  217. }
  218. void mesh::remove_face(mesh::face* face)
  219. {
  220. // Nullify pointers to this face
  221. mesh::edge* edge = face->edge;
  222. do
  223. {
  224. edge->face = nullptr;
  225. edge = edge->next;
  226. }
  227. while (edge != face->edge);
  228. // Adjust indices of faces after this face
  229. for (std::size_t i = face->index + 1; i < faces.size(); ++i)
  230. {
  231. --faces[i]->index;
  232. }
  233. // Remove face from the faces vector
  234. faces.erase(faces.begin() + face->index);
  235. // Deallocate face
  236. delete face;
  237. }
  238. void mesh::remove_edge(mesh::edge* edge)
  239. {
  240. mesh::edge* ab = edge;
  241. mesh::edge* ba = edge->symmetric;
  242. mesh::vertex* a = ab->vertex;
  243. mesh::edge* a_in = ab->previous;
  244. mesh::edge* a_out = ba->next;
  245. mesh::vertex* b = ba->vertex;
  246. mesh::edge* b_in = ba->previous;
  247. mesh::edge* b_out = ab->next;
  248. // Remove dependent faces
  249. if (ab->face)
  250. remove_face(ab->face);
  251. if (ba->face)
  252. remove_face(ba->face);
  253. // Re-link edges
  254. if (a->edge == ab)
  255. a->edge = (a_out == ab) ? nullptr : a_out;
  256. if (b->edge == ba)
  257. b->edge = (b_out == ba) ? nullptr : b_out;
  258. a_in->next = a_out;
  259. a_out->previous = a_in;
  260. b_in->next = b_out;
  261. b_out->previous = b_in;
  262. // Adjust indices of edges after this edge
  263. for (std::size_t i = edge->index + 1; i < edges.size(); ++i)
  264. {
  265. --edges[i]->index;
  266. --edges[i]->symmetric->index;
  267. }
  268. // Remove edge from the edges vector
  269. edges.erase(edges.begin() + edge->index);
  270. // Deallocate edge
  271. delete edge->symmetric;
  272. delete edge;
  273. }
  274. void mesh::remove_vertex(mesh::vertex* vertex)
  275. {
  276. // Remove connected edges
  277. if (vertex->edge)
  278. {
  279. mesh::edge* current = nullptr;
  280. mesh::edge* next = vertex->edge;
  281. do
  282. {
  283. current = next;
  284. next = next->symmetric->next;
  285. if (next == current)
  286. {
  287. next = next->symmetric->next;
  288. }
  289. remove_edge(current);
  290. }
  291. while (current != next);
  292. }
  293. // Adjust indices of vertices after this vertex
  294. for (std::size_t i = vertex->index + 1; i < vertices.size(); ++i)
  295. {
  296. --vertices[i]->index;
  297. }
  298. // Remove vertex from the vertices vector
  299. vertices.erase(vertices.begin() + vertex->index);
  300. // Deallocate vertex
  301. delete vertex;
  302. }
  303. mesh::edge* mesh::find_free_incident(mesh::vertex* vertex) const
  304. {
  305. mesh::edge* begin = vertex->edge->symmetric;
  306. mesh::edge* current = begin;
  307. do
  308. {
  309. if (!current->face)
  310. {
  311. return current;
  312. }
  313. current = current->next->symmetric;
  314. }
  315. while (current != begin);
  316. return nullptr;
  317. }
  318. mesh::edge* mesh::find_free_incident(mesh::edge* start_edge, mesh::edge* end_edge) const
  319. {
  320. if (start_edge == end_edge)
  321. {
  322. return nullptr;
  323. }
  324. mesh::edge* current = start_edge;
  325. do
  326. {
  327. if (!current->face)
  328. {
  329. return current;
  330. }
  331. current = current->next->symmetric;
  332. }
  333. while (current != end_edge);
  334. return nullptr;
  335. }
  336. bool mesh::make_adjacent(mesh::edge* in, mesh::edge* out)
  337. {
  338. if (in->next == out)
  339. {
  340. return true;
  341. }
  342. mesh::edge* b = in->next;
  343. mesh::edge* d = out->previous;
  344. mesh::edge* g = find_free_incident(out->symmetric, in);
  345. if (!g)
  346. {
  347. return false;
  348. }
  349. mesh::edge* h = g->next;
  350. in->next = out;
  351. out->previous = in;
  352. g->next = b;
  353. b->previous = g;
  354. d->next = h;
  355. h->previous = d;
  356. return true;
  357. }
  358. } // namespace geom