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

513 lines
15 KiB

  1. /*
  2. * Copyright (C) 2021 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 "subterrain.hpp"
  20. #include "entity/components/model.hpp"
  21. #include "entity/components/cavity.hpp"
  22. #include "entity/id.hpp"
  23. #include "render/model.hpp"
  24. #include "render/material.hpp"
  25. #include "geom/mesh-functions.hpp"
  26. #include "render/vertex-attribute.hpp"
  27. #include "gl/vertex-attribute.hpp"
  28. #include "gl/drawing-mode.hpp"
  29. #include "gl/vertex-buffer.hpp"
  30. #include "resources/resource-manager.hpp"
  31. #include "geom/marching-cubes.hpp"
  32. #include "geom/intersection.hpp"
  33. #include "utility/fundamental-types.hpp"
  34. #include <array>
  35. #include <limits>
  36. namespace entity {
  37. namespace system {
  38. /**
  39. * An octree containing cubes for the marching cubes algorithm.
  40. */
  41. struct cube_tree
  42. {
  43. public:
  44. cube_tree(const geom::aabb<float>& bounds, int max_depth);
  45. ~cube_tree();
  46. const bool is_leaf() const;
  47. const geom::aabb<float>& get_bounds() const;
  48. /// Subdivides all nodes intersecting with a region to the max depth.
  49. void subdivide_max(const geom::aabb<float>& region);
  50. /// Fills a list with all leaf nodes that intersect with a region.
  51. void query_leaves(std::list<cube_tree*>& nodes, const geom::aabb<float>& region);
  52. void visit_leaves(const geom::aabb<float>& region, const std::function<void(cube_tree&)>& f);
  53. /// Counts then number of nodes in the octree.
  54. std::size_t size() const;
  55. cube_tree* children[8];
  56. float3 corners[8];
  57. float distances[8];
  58. const int max_depth;
  59. const int depth;
  60. const geom::aabb<float> bounds;
  61. private:
  62. cube_tree(const geom::aabb<float>& bounds, int max_depth, int depth);
  63. void subdivide();
  64. };
  65. cube_tree::cube_tree(const geom::aabb<float>& bounds, int max_depth):
  66. cube_tree(bounds, max_depth, 0)
  67. {}
  68. cube_tree::cube_tree(const geom::aabb<float>& bounds, int max_depth, int depth):
  69. bounds(bounds),
  70. max_depth(max_depth),
  71. depth(depth)
  72. {
  73. corners[0] = {bounds.min_point.x, bounds.min_point.y, bounds.min_point.z};
  74. corners[1] = {bounds.max_point.x, bounds.min_point.y, bounds.min_point.z};
  75. corners[2] = {bounds.max_point.x, bounds.max_point.y, bounds.min_point.z};
  76. corners[3] = {bounds.min_point.x, bounds.max_point.y, bounds.min_point.z};
  77. corners[4] = {bounds.min_point.x, bounds.min_point.y, bounds.max_point.z};
  78. corners[5] = {bounds.max_point.x, bounds.min_point.y, bounds.max_point.z};
  79. corners[6] = {bounds.max_point.x, bounds.max_point.y, bounds.max_point.z};
  80. corners[7] = {bounds.min_point.x, bounds.max_point.y, bounds.max_point.z};
  81. for (int i = 0; i < 8; ++i)
  82. {
  83. children[i] = nullptr;
  84. distances[i] = -std::numeric_limits<float>::infinity();
  85. // For outside normals
  86. //distances[i] = std::numeric_limits<float>::infinity();
  87. }
  88. }
  89. cube_tree::~cube_tree()
  90. {
  91. for (cube_tree* child: children)
  92. delete child;
  93. }
  94. void cube_tree::subdivide_max(const geom::aabb<float>& region)
  95. {
  96. if (depth != max_depth && aabb_aabb_intersection(bounds, region))
  97. {
  98. if (is_leaf())
  99. subdivide();
  100. for (cube_tree* child: children)
  101. child->subdivide_max(region);
  102. }
  103. }
  104. void cube_tree::query_leaves(std::list<cube_tree*>& nodes, const geom::aabb<float>& region)
  105. {
  106. if (aabb_aabb_intersection(bounds, region))
  107. {
  108. if (is_leaf())
  109. {
  110. nodes.push_back(this);
  111. }
  112. else
  113. {
  114. for (cube_tree* child: children)
  115. child->query_leaves(nodes, region);
  116. }
  117. }
  118. }
  119. void cube_tree::visit_leaves(const geom::aabb<float>& region, const std::function<void(cube_tree&)>& f)
  120. {
  121. if (aabb_aabb_intersection(bounds, region))
  122. {
  123. if (is_leaf())
  124. {
  125. f(*this);
  126. }
  127. else
  128. {
  129. for (cube_tree* child: children)
  130. child->visit_leaves(region, f);
  131. }
  132. }
  133. }
  134. std::size_t cube_tree::size() const
  135. {
  136. std::size_t node_count = 1;
  137. if (!is_leaf())
  138. {
  139. for (cube_tree* child: children)
  140. node_count += child->size();
  141. }
  142. return node_count;
  143. }
  144. inline const bool cube_tree::is_leaf() const
  145. {
  146. return (children[0] == nullptr);
  147. }
  148. inline const geom::aabb<float>& cube_tree::get_bounds() const
  149. {
  150. return bounds;
  151. }
  152. void cube_tree::subdivide()
  153. {
  154. const float3 center = (bounds.min_point + bounds.max_point) * 0.5f;
  155. for (int i = 0; i < 8; ++i)
  156. {
  157. geom::aabb<float> child_bounds;
  158. for (int j = 0; j < 3; ++j)
  159. {
  160. child_bounds.min_point[j] = std::min<float>(corners[i][j], center[j]);
  161. child_bounds.max_point[j] = std::max<float>(corners[i][j], center[j]);
  162. }
  163. children[i] = new cube_tree(child_bounds, max_depth, depth + 1);
  164. }
  165. }
  166. subterrain::subterrain(entity::registry& registry, ::resource_manager* resource_manager):
  167. updatable(registry),
  168. resource_manager(resource_manager)
  169. {
  170. // Load subterrain materials
  171. subterrain_inside_material = resource_manager->load<::render::material>("subterrain-inside.mtl");
  172. subterrain_inside_material = resource_manager->load<::render::material>("subterrain-outside.mtl");
  173. // Allocate subterrain model
  174. subterrain_model = new ::render::model();
  175. // Create inside model group
  176. subterrain_inside_group = subterrain_model->add_group("inside");
  177. subterrain_inside_group->set_material(resource_manager->load<::render::material>("subterrain-inside.mtl"));
  178. subterrain_inside_group->set_drawing_mode(gl::drawing_mode::triangles);
  179. subterrain_inside_group->set_start_index(0);
  180. subterrain_inside_group->set_index_count(0);
  181. // Create outside model group
  182. subterrain_outside_group = subterrain_model->add_group("outside");
  183. subterrain_outside_group->set_material(resource_manager->load<::render::material>("subterrain-outside.mtl"));
  184. subterrain_outside_group->set_drawing_mode(gl::drawing_mode::triangles);
  185. subterrain_outside_group->set_start_index(0);
  186. subterrain_outside_group->set_index_count(0);
  187. // Determine vertex size (position, normal, barycentric)
  188. subterrain_model_vertex_size = 3 + 3 + 3;
  189. subterrain_model_vertex_stride = subterrain_model_vertex_size * sizeof(float);
  190. // Get model VBO and VAO
  191. gl::vertex_buffer* vbo = subterrain_model->get_vertex_buffer();
  192. gl::vertex_array* vao = subterrain_model->get_vertex_array();
  193. std::size_t attribute_offset = 0;
  194. // Define position vertex attribute
  195. gl::vertex_attribute position_attribute;
  196. position_attribute.buffer = vbo;
  197. position_attribute.offset = attribute_offset;
  198. position_attribute.stride = subterrain_model_vertex_stride;
  199. position_attribute.type = gl::vertex_attribute_type::float_32;
  200. position_attribute.components = 3;
  201. attribute_offset += position_attribute.components * sizeof(float);
  202. // Define normal vertex attribute
  203. gl::vertex_attribute normal_attribute;
  204. normal_attribute.buffer = vbo;
  205. normal_attribute.offset = attribute_offset;
  206. normal_attribute.stride = subterrain_model_vertex_stride;
  207. normal_attribute.type = gl::vertex_attribute_type::float_32;
  208. normal_attribute.components = 3;
  209. attribute_offset += normal_attribute.components * sizeof(float);
  210. // Define barycentric vertex attribute
  211. gl::vertex_attribute barycentric_attribute;
  212. barycentric_attribute.buffer = vbo;
  213. barycentric_attribute.offset = attribute_offset;
  214. barycentric_attribute.stride = subterrain_model_vertex_stride;
  215. barycentric_attribute.type = gl::vertex_attribute_type::float_32;
  216. barycentric_attribute.components = 3;
  217. attribute_offset += barycentric_attribute.components * sizeof(float);
  218. // Bind vertex attributes to VAO
  219. vao->bind(::render::vertex_attribute::position, position_attribute);
  220. vao->bind(::render::vertex_attribute::normal, normal_attribute);
  221. vao->bind(::render::vertex_attribute::barycentric, barycentric_attribute);
  222. // Calculate adjusted bounds to fit isosurface resolution
  223. //isosurface_resolution = 0.325f;
  224. isosurface_resolution = 0.5f;
  225. float ideal_volume_size = 200.0f;
  226. int octree_depth = std::floor(std::log(ideal_volume_size / isosurface_resolution) / std::log(2)) + 1;
  227. float adjusted_volume_size = std::pow(2.0f, octree_depth) * isosurface_resolution;
  228. // Set subterrain bounds
  229. subterrain_bounds.min_point = float3{-0.5f, -1.0f, -0.5f} * adjusted_volume_size;
  230. subterrain_bounds.max_point = float3{ 0.5f, 0.0f, 0.5f} * adjusted_volume_size;
  231. // Set subterrain model bounds
  232. subterrain_model->set_bounds(subterrain_bounds);
  233. // Allocate cube tree
  234. cube_tree = new entity::system::cube_tree(subterrain_bounds, octree_depth);
  235. // Allocate mesh
  236. subterrain_mesh = new geom::mesh();
  237. first_run = true;
  238. }
  239. subterrain::~subterrain()
  240. {
  241. delete subterrain_model;
  242. delete subterrain_mesh;
  243. }
  244. void subterrain::update(double t, double dt)
  245. {
  246. if (first_run)
  247. {
  248. first_run = false;
  249. //auto subterrain_entity = registry.create();
  250. //registry.assign<component::model>(subterrain_entity, subterrain_model);
  251. subterrain_model_instance = new scene::model_instance(subterrain_model);
  252. collection->add_object(subterrain_model_instance);
  253. }
  254. bool digging = false;
  255. registry.view<component::cavity>().each(
  256. [this, &digging](entity::id entity_id, auto& cavity)
  257. {
  258. this->dig(cavity.position, cavity.radius);
  259. this->registry.destroy(entity_id);
  260. digging = true;
  261. });
  262. if (digging)
  263. {
  264. //std::cout << "regenerating subterrain mesh...\n";
  265. regenerate_subterrain_mesh();
  266. //std::cout << "regenerating subterrain mesh... done\n";
  267. //std::cout << "regenerating subterrain model...\n";
  268. regenerate_subterrain_model();
  269. //std::cout << "regenerating subterrain model... done\n";
  270. }
  271. }
  272. void subterrain::set_scene(scene::collection* collection)
  273. {
  274. this->collection = collection;
  275. }
  276. void subterrain::regenerate_subterrain_mesh()
  277. {
  278. delete subterrain_mesh;
  279. subterrain_mesh = new geom::mesh();
  280. subterrain_vertices.clear();
  281. subterrain_triangles.clear();
  282. subterrain_vertex_map.clear();
  283. //std::cout << "marching...\n";
  284. merged = 0;
  285. march(cube_tree);
  286. //std::cout << "merged " << merged << " vertices\n";
  287. //std::cout << "marching...done\n";
  288. //std::cout << "vertex count: " << subterrain_vertices.size() << std::endl;
  289. //std::cout << "triangle count: " << subterrain_triangles.size() << std::endl;
  290. //std::cout << "creating mesh...\n";
  291. create_triangle_mesh(*subterrain_mesh, subterrain_vertices, subterrain_triangles);
  292. //std::cout << "creating mesh... done\n";
  293. }
  294. void subterrain::march(entity::system::cube_tree* node)
  295. {
  296. if (!node->is_leaf())
  297. {
  298. for (entity::system::cube_tree* child: node->children)
  299. march(child);
  300. return;
  301. }
  302. else if (node->depth != node->max_depth)
  303. {
  304. return;
  305. }
  306. // Get node bounds
  307. const geom::aabb<float>& bounds = node->get_bounds();
  308. // Polygonize cube
  309. float vertex_buffer[12 * 3];
  310. std::uint_fast8_t vertex_count;
  311. std::int_fast8_t triangle_buffer[5 * 3];
  312. std::uint_fast8_t triangle_count;
  313. const float* corners = &node->corners[0][0];
  314. const float* distances = &node->distances[0];
  315. geom::mc::polygonize(vertex_buffer, &vertex_count, triangle_buffer, &triangle_count, corners, distances);
  316. // Remap local vertex buffer indices (0-11) to mesh vertex indices
  317. std::uint_fast32_t vertex_remap[12];
  318. for (int i = 0; i < vertex_count; ++i)
  319. {
  320. const float3& vertex = reinterpret_cast<const float3&>(vertex_buffer[i * 3]);
  321. if (auto it = subterrain_vertex_map.find(vertex); it != subterrain_vertex_map.end())
  322. {
  323. vertex_remap[i] = it->second;
  324. ++merged;
  325. }
  326. else
  327. {
  328. vertex_remap[i] = subterrain_vertices.size();
  329. subterrain_vertex_map[vertex] = subterrain_vertices.size();
  330. subterrain_vertices.push_back(vertex);
  331. }
  332. }
  333. // Add triangles
  334. for (std::uint_fast32_t i = 0; i < triangle_count; ++i)
  335. {
  336. subterrain_triangles.push_back(
  337. {
  338. vertex_remap[triangle_buffer[i * 3]],
  339. vertex_remap[triangle_buffer[i * 3 + 1]],
  340. vertex_remap[triangle_buffer[i * 3 + 2]]
  341. });
  342. }
  343. }
  344. void subterrain::regenerate_subterrain_model()
  345. {
  346. float3* face_normals = new float3[subterrain_mesh->get_faces().size()];
  347. calculate_face_normals(face_normals, *subterrain_mesh);
  348. static const float3 barycentric_coords[3] =
  349. {
  350. float3{1, 0, 0},
  351. float3{0, 1, 0},
  352. float3{0, 0, 1}
  353. };
  354. float* vertex_data = new float[subterrain_model_vertex_size * subterrain_mesh->get_faces().size() * 3];
  355. float* v = vertex_data;
  356. for (std::size_t i = 0; i < subterrain_mesh->get_faces().size(); ++i)
  357. {
  358. geom::mesh::face* face = subterrain_mesh->get_faces()[i];
  359. geom::mesh::edge* ab = face->edge;
  360. geom::mesh::edge* bc = face->edge->next;
  361. geom::mesh::edge* ca = face->edge->previous;
  362. geom::mesh::vertex* a = ab->vertex;
  363. geom::mesh::vertex* b = bc->vertex;
  364. geom::mesh::vertex* c = ca->vertex;
  365. geom::mesh::vertex* vertices[3] = {a, b, c};
  366. for (std::size_t j = 0; j < 3; ++j)
  367. {
  368. geom::mesh::vertex* vertex = vertices[j];
  369. float3 n = {0, 0, 0};
  370. geom::mesh::edge* start = vertex->edge;
  371. geom::mesh::edge* edge = start;
  372. do
  373. {
  374. if (edge->face)
  375. {
  376. n += face_normals[edge->face->index];
  377. }
  378. edge = edge->previous->symmetric;
  379. }
  380. while (edge != start);
  381. n = math::normalize(n);
  382. //float3 n = reinterpret_cast<const float3&>(face_normals[i * 3]);
  383. *(v++) = vertex->position[0];
  384. *(v++) = vertex->position[1];
  385. *(v++) = vertex->position[2];
  386. *(v++) = n[0];
  387. *(v++) = n[1];
  388. *(v++) = n[2];
  389. *(v++) = barycentric_coords[j][0];
  390. *(v++) = barycentric_coords[j][1];
  391. *(v++) = barycentric_coords[j][2];
  392. }
  393. }
  394. // Resized VBO and upload vertex data
  395. gl::vertex_buffer* vbo = subterrain_model->get_vertex_buffer();
  396. vbo->resize(subterrain_mesh->get_faces().size() * 3 * subterrain_model_vertex_stride, vertex_data);
  397. // Deallocate vertex data
  398. delete[] face_normals;
  399. delete[] vertex_data;
  400. // Update model groups
  401. subterrain_inside_group->set_index_count(subterrain_mesh->get_faces().size() * 3);
  402. subterrain_outside_group->set_index_count(subterrain_mesh->get_faces().size() * 3);
  403. }
  404. void subterrain::dig(const float3& position, float radius)
  405. {
  406. // Construct region containing the cavity sphere
  407. geom::aabb<float> region = {position, position};
  408. for (int i = 0; i < 3; ++i)
  409. {
  410. region.min_point[i] -= radius + isosurface_resolution;
  411. region.max_point[i] += radius + isosurface_resolution;
  412. }
  413. // Subdivide the octree to the maximum depth within the region
  414. cube_tree->subdivide_max(region);
  415. // Query all octree leaf nodes within the region
  416. std::list<entity::system::cube_tree*> nodes;
  417. cube_tree->visit_leaves(region,
  418. [&position, radius](entity::system::cube_tree& node)
  419. {
  420. for (int i = 0; i < 8; ++i)
  421. {
  422. // For outside normals (also set node initial distance to +infinity)
  423. //float distance = math::length(node->corners[i] - position) - radius;
  424. // if (distance < node->distances[i])
  425. float distance = radius - math::length(node.corners[i] - position);
  426. if (distance > node.distances[i])
  427. node.distances[i] = distance;
  428. }
  429. });
  430. }
  431. } // namespace system
  432. } // namespace entity