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

102 lines
3.0 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/meshes/grid.hpp>
  20. #include <array>
  21. #include <cmath>
  22. #include <map>
  23. namespace geom {
  24. namespace meshes {
  25. std::unique_ptr<geom::mesh> grid_xy(float length, std::size_t subdivisions_x, std::size_t subdivisions_y)
  26. {
  27. // Allocate new mesh
  28. std::unique_ptr<geom::mesh> mesh = std::make_unique<geom::mesh>();
  29. // Determine vertex count and placement
  30. std::size_t columns = subdivisions_x + 1;
  31. std::size_t rows = subdivisions_y + 1;
  32. float column_length = length / static_cast<float>(columns);
  33. float row_length = length / static_cast<float>(rows);
  34. // Generate mesh vertices
  35. float3 position;
  36. position.z() = 0.0f;
  37. position.y() = -length * 0.5f;
  38. for (std::size_t i = 0; i <= rows; ++i)
  39. {
  40. position.x() = -length * 0.5f;
  41. for (std::size_t j = 0; j <= columns; ++j)
  42. {
  43. mesh->add_vertex(position);
  44. position.x() += column_length;
  45. }
  46. position.y() += row_length;
  47. }
  48. // Function to eliminate duplicate edges
  49. std::map<std::array<std::size_t, 2>, geom::mesh::edge*> edge_map;
  50. auto add_or_find_edge = [&](geom::mesh::vertex* start, geom::mesh::vertex* end) -> geom::mesh::edge*
  51. {
  52. geom::mesh::edge* edge;
  53. if (auto it = edge_map.find({start->index, end->index}); it != edge_map.end())
  54. {
  55. edge = it->second;
  56. }
  57. else
  58. {
  59. edge = mesh->add_edge(start, end);
  60. edge_map[{start->index, end->index}] = edge;
  61. edge_map[{end->index, start->index}] = edge->symmetric;
  62. }
  63. return edge;
  64. };
  65. // Connect vertices with edges and faces
  66. const std::vector<geom::mesh::vertex*>& vertices = mesh->get_vertices();
  67. for (std::size_t i = 0; i < rows; ++i)
  68. {
  69. for (std::size_t j = 0; j < columns; ++j)
  70. {
  71. geom::mesh::vertex* a = vertices[i * (columns + 1) + j];
  72. geom::mesh::vertex* b = vertices[(i + 1) * (columns + 1) + j];
  73. geom::mesh::vertex* c = vertices[i * (columns + 1) + j + 1];
  74. geom::mesh::vertex* d = vertices[(i + 1) * (columns + 1) + j + 1];
  75. // a---c
  76. // | |
  77. // b---d
  78. geom::mesh::edge* ab = add_or_find_edge(a, b);
  79. geom::mesh::edge* bd = add_or_find_edge(b, d);
  80. geom::mesh::edge* dc = add_or_find_edge(d, c);
  81. geom::mesh::edge* ca = add_or_find_edge(c, a);
  82. mesh->add_face({ab, bd, dc, ca});
  83. }
  84. }
  85. return mesh;
  86. }
  87. } // namespace meshes
  88. } // namespace geom