💿🐜 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.

222 lines
6.4 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-functions.hpp>
  20. #include <engine/utility/fundamental-types.hpp>
  21. #include <unordered_map>
  22. #include <vector>
  23. namespace geom {
  24. struct edge_hasher
  25. {
  26. std::size_t operator()(const std::array<std::size_t, 2>& v) const noexcept
  27. {
  28. std::size_t hash = std::hash<std::size_t>()(v[0]);
  29. return hash ^ (std::hash<std::size_t>()(v[1]) + 0x9e3779b9 + (hash << 6) + (hash >> 2));
  30. }
  31. };
  32. void create_triangle_mesh(mesh& mesh, const std::vector<float3>& vertices, const std::vector<std::array<std::uint_fast32_t, 3>>& triangles)
  33. {
  34. for (const auto& vertex: vertices)
  35. mesh.add_vertex(vertex);
  36. std::unordered_map<std::array<std::size_t, 2>, geom::mesh::edge*, edge_hasher> edge_map;
  37. const std::vector<mesh::vertex*>& mesh_vertices = mesh.get_vertices();
  38. std::vector<geom::mesh::edge*> loop(3);
  39. for (const auto& triangle: triangles)
  40. {
  41. geom::mesh::vertex* triangle_vertices[3] =
  42. {
  43. mesh_vertices[triangle[0]],
  44. mesh_vertices[triangle[1]],
  45. mesh_vertices[triangle[2]]
  46. };
  47. for (int j = 0; j < 3; ++j)
  48. {
  49. geom::mesh::vertex* start = triangle_vertices[j];
  50. geom::mesh::vertex* end = triangle_vertices[(j + 1) % 3];
  51. if (auto it = edge_map.find({start->index, end->index}); it != edge_map.end())
  52. {
  53. loop[j] = it->second;
  54. }
  55. else
  56. {
  57. loop[j] = mesh.add_edge(start, end);
  58. edge_map[{start->index, end->index}] = loop[j];
  59. edge_map[{end->index, start->index}] = loop[j]->symmetric;
  60. }
  61. }
  62. mesh.add_face(loop);
  63. }
  64. }
  65. void calculate_face_normals(float3* normals, const mesh& mesh)
  66. {
  67. const std::vector<mesh::face*>& faces = mesh.get_faces();
  68. for (std::size_t i = 0; i < faces.size(); ++i)
  69. {
  70. const mesh::face& face = *(faces[i]);
  71. const float3& a = face.edge->vertex->position;
  72. const float3& b = face.edge->next->vertex->position;
  73. const float3& c = face.edge->previous->vertex->position;
  74. normals[i] = math::normalize(math::cross(b - a, c - a));
  75. }
  76. }
  77. float3 calculate_face_normal(const mesh::face& face)
  78. {
  79. const float3& a = face.edge->vertex->position;
  80. const float3& b = face.edge->next->vertex->position;
  81. const float3& c = face.edge->previous->vertex->position;
  82. return math::normalize(math::cross(b - a, c - a));
  83. }
  84. void calculate_vertex_tangents(float4* tangents, const float2* texcoords, const float3* normals, const mesh& mesh)
  85. {
  86. const std::vector<mesh::face*>& faces = mesh.get_faces();
  87. const std::vector<mesh::vertex*>& vertices = mesh.get_vertices();
  88. // Allocate tangent and bitangent buffers
  89. std::vector<float3> tangent_buffer(vertices.size(), float3{0.0f, 0.0f, 0.0f});
  90. std::vector<float3> bitangent_buffer(vertices.size(), float3{0.0f, 0.0f, 0.0f});
  91. // Accumulate tangents and bitangents
  92. for (std::size_t i = 0; i < faces.size(); ++i)
  93. {
  94. const mesh::face& face = *(faces[i]);
  95. std::size_t ia = face.edge->vertex->index;
  96. std::size_t ib = face.edge->next->vertex->index;
  97. std::size_t ic = face.edge->previous->vertex->index;
  98. const float3& a = vertices[ia]->position;
  99. const float3& b = vertices[ib]->position;
  100. const float3& c = vertices[ic]->position;
  101. const float2& uva = texcoords[ia];
  102. const float2& uvb = texcoords[ib];
  103. const float2& uvc = texcoords[ic];
  104. float3 ba = b - a;
  105. float3 ca = c - a;
  106. float2 uvba = uvb - uva;
  107. float2 uvca = uvc - uva;
  108. float f = 1.0f / (uvba.x() * uvca.y() - uvca.x() * uvba.y());
  109. float3 tangent = (ba * uvca.y() - ca * uvba.y()) * f;
  110. float3 bitangent = (ba * -uvca.x() + ca * uvba.x()) * f;
  111. tangent_buffer[ia] += tangent;
  112. tangent_buffer[ib] += tangent;
  113. tangent_buffer[ic] += tangent;
  114. bitangent_buffer[ia] += bitangent;
  115. bitangent_buffer[ib] += bitangent;
  116. bitangent_buffer[ic] += bitangent;
  117. }
  118. // Orthogonalize tangents
  119. for (std::size_t i = 0; i < vertices.size(); ++i)
  120. {
  121. const float3& n = normals[i];
  122. const float3& t = tangent_buffer[i];
  123. const float3& b = bitangent_buffer[i];
  124. // Gram-Schmidt orthogonalize tangent
  125. float3 tangent = math::normalize(t - n * math::dot(n, t));
  126. // Calculate bitangent sign
  127. float bitangent_sign = (math::dot(math::cross(n, t), b) < 0.0f) ? -1.0f : 1.0f;
  128. tangents[i] = {tangent.x(), tangent.y(), tangent.z(), bitangent_sign};
  129. }
  130. }
  131. box<float> calculate_bounds(const mesh& mesh)
  132. {
  133. box<float> bounds;
  134. for (int i = 0; i < 3; ++i)
  135. {
  136. bounds.min[i] = std::numeric_limits<float>::infinity();
  137. bounds.max[i] = -std::numeric_limits<float>::infinity();
  138. }
  139. for (const mesh::vertex* vertex: mesh.get_vertices())
  140. {
  141. const auto& position = vertex->position;
  142. bounds.extend(position);
  143. }
  144. return bounds;
  145. }
  146. mesh::vertex* poke_face(mesh& mesh, std::size_t index)
  147. {
  148. mesh::face* face = mesh.get_faces()[index];
  149. // Collect face edges and sum edge vertex positions
  150. mesh::loop loop = {face->edge};
  151. float3 sum_positions = face->edge->vertex->position;
  152. for (mesh::edge* edge = face->edge->next; edge != face->edge; edge = edge->next)
  153. {
  154. loop.push_back(edge);
  155. sum_positions += edge->vertex->position;
  156. }
  157. if (loop.size() <= 2)
  158. return nullptr;
  159. // Remove face
  160. mesh.remove_face(face);
  161. // Add vertex in center
  162. mesh::vertex* center = mesh.add_vertex(sum_positions / static_cast<float>(loop.size()));
  163. // Create first triangle
  164. geom::mesh::edge* ab = loop[0];
  165. geom::mesh::edge* bc = mesh.add_edge(ab->next->vertex, center);
  166. geom::mesh::edge* ca = mesh.add_edge(center, ab->vertex);
  167. mesh.add_face({ab, bc, ca});
  168. // Save first triangle CA edge
  169. geom::mesh::edge* first_triangle_ca = ca;
  170. // Create remaining triangles
  171. for (std::size_t i = 1; i < loop.size(); ++i)
  172. {
  173. ab = loop[i];
  174. ca = bc->symmetric;
  175. if (i == loop.size() - 1)
  176. bc = first_triangle_ca->symmetric;
  177. else
  178. bc = mesh.add_edge(ab->next->vertex, center);
  179. mesh.add_face({ab, bc, ca});
  180. }
  181. return center;
  182. }
  183. } // namespace geom