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

486 lines
14 KiB

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