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

282 lines
7.7 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 "game/load.hpp"
  20. #include "game/world.hpp"
  21. #include "application.hpp"
  22. #include "debug/logger.hpp"
  23. #include "resources/json.hpp"
  24. #include "resources/resource-manager.hpp"
  25. #include "render/model.hpp"
  26. #include "render/material.hpp"
  27. #include "render/passes/sky-pass.hpp"
  28. #include "render/passes/ground-pass.hpp"
  29. #include "game/system/astronomy.hpp"
  30. #include "game/system/terrain.hpp"
  31. #include "math/random.hpp"
  32. #include "math/noise/noise.hpp"
  33. #include "math/hash/hash.hpp"
  34. #include <fstream>
  35. #include <iostream>
  36. #include <stb/stb_image_write.h>
  37. #include "resources/image.hpp"
  38. #include <algorithm>
  39. #include <execution>
  40. namespace game {
  41. namespace load {
  42. void biome(game::context& ctx, const std::filesystem::path& path)
  43. {
  44. ctx.logger->push_task("Loading biome from \"" + path.string() + "\"");
  45. /*
  46. image img;
  47. img.format(1, 1);
  48. img.resize(1024, 1024);
  49. float frequency = 10.0f;
  50. std::size_t octaves = 4;
  51. float lacunarity = 2.0f;
  52. float gain = 0.5f;
  53. auto hash = static_cast<math::vector<std::uint32_t, 2>(*)(const math::vector<float, 2>&)>(math::hash::pcg);
  54. auto noise = static_cast<float(*)(const math::vector<float, 2>&, decltype(hash))>(math::noise::simplex);
  55. auto fbm = [&](const float2& x)
  56. {
  57. return math::noise::fbm
  58. (
  59. x,
  60. octaves,
  61. lacunarity,
  62. gain,
  63. noise,
  64. hash
  65. );
  66. };
  67. auto width = img.get_width();
  68. auto height = img.get_height();
  69. unsigned char* pixels = (unsigned char*)img.data();
  70. float scale_x = 1.0f / static_cast<float>(width - 1) * frequency;
  71. float scale_y = 1.0f / static_cast<float>(height - 1) * frequency;
  72. std::for_each
  73. (
  74. std::execution::par_unseq,
  75. img.begin<unsigned char>(),
  76. img.end<unsigned char>(),
  77. [pixels, width, height, scale_x, scale_y, &fbm](auto& pixel)
  78. {
  79. std::size_t i = &pixel - pixels;
  80. std::size_t y = i / width;
  81. std::size_t x = i % width;
  82. float2 position =
  83. {
  84. static_cast<float>(x) * scale_x,
  85. static_cast<float>(y) * scale_y
  86. };
  87. //float n = math::noise::simplex<float, 2>(position, &math::noise::hash::pcg3d_1);
  88. //float n = fbm(position);
  89. // auto [sqr_center_distance, displacement, id, sqr_edge_distance] = math::noise::voronoi::f1_edge<float, std::uint32_t>(position, 1.0f, &math::noise::hash::pcg3d_3);
  90. // float center_distance = std::sqrt(sqr_center_distance);
  91. // float edge_distance = std::sqrt(sqr_edge_distance);
  92. auto
  93. [
  94. f1_sqr_distance,
  95. f1_displacement,
  96. f1_id,
  97. // f2_sqr_distance,
  98. // f2_displacement,
  99. // f2_id
  100. edge_sqr_distance(
  101. ] = math::noise::voronoi::f1_edge<float, 2>(position);
  102. float f1_distance = std::sqrt(f1_sqr_distance();
  103. //float f2_distance = std::sqrt(f2_sqr_distance();
  104. float edge_distance = std::sqrt(edge_sqr_distance();
  105. pixel = static_cast<unsigned char>(std::min(255.0f, f1_distance * 255.0f));
  106. //pixel = static_cast<unsigned char>(id % 255);
  107. }
  108. );
  109. stbi_flip_vertically_on_write(1);
  110. stbi_write_png((ctx.config_path / "gallery" / "noise.png").string().c_str(), img.get_width(), img.get_height(), img.get_channel_count(), img.data(), img.get_width() * img.get_channel_count());
  111. */
  112. try
  113. {
  114. json* data = ctx.resource_manager->load<json>(path);
  115. // Load location
  116. if (auto location = data->find("location"); location != data->end())
  117. {
  118. double elevation = 0.0;
  119. double latitude = 0.0;
  120. double longitude = 0.0;
  121. if (auto location_ele = location->find("elevation"); location_ele != location->end())
  122. elevation = location_ele->get<double>();
  123. else
  124. ctx.logger->warning("Biome elevation undefined");
  125. if (auto location_lat = location->find("latitude"); location_lat != location->end())
  126. latitude = math::radians<double>(location_lat->get<double>());
  127. else
  128. ctx.logger->warning("Biome latitude undefined");
  129. if (auto location_lon = location->find("longitude"); location_lon != location->end())
  130. longitude = math::radians<double>(location_lon->get<double>());
  131. else
  132. ctx.logger->warning("Biome longitude undefined");
  133. // Set location
  134. game::world::set_location(ctx, elevation, latitude, longitude);
  135. }
  136. else
  137. {
  138. ctx.logger->warning("Biome location undefined");
  139. }
  140. // Setup sky
  141. ctx.sky_pass->set_sky_model(ctx.resource_manager->load<render::model>("celestial-hemisphere.mdl"));
  142. // Load terrain
  143. if (auto terrain = data->find("terrain"); terrain != data->end())
  144. {
  145. if (auto material = terrain->find("material"); material != terrain->end())
  146. {
  147. render::material* terrain_material = ctx.resource_manager->load<render::material>(material->get<std::string>());
  148. ctx.terrain_system->set_patch_material(terrain_material);
  149. }
  150. else
  151. {
  152. ctx.logger->warning("Biome terrain material undefined");
  153. }
  154. if (auto material = terrain->find("horizon_material"); material != terrain->end())
  155. {
  156. render::model* terrestrial_hemisphere_model = ctx.resource_manager->load<render::model>("terrestrial-hemisphere.mdl");
  157. (*terrestrial_hemisphere_model->get_groups())[0]->set_material(ctx.resource_manager->load<render::material>(material->get<std::string>()));
  158. ctx.ground_pass->set_ground_model(terrestrial_hemisphere_model);
  159. }
  160. else
  161. {
  162. ctx.logger->warning("Biome terrain horizon material undefined");
  163. }
  164. // Terrain elevation function
  165. ctx.terrain_system->set_elevation_function
  166. (
  167. [](float x, float z) -> float
  168. {
  169. /*
  170. float frequency = 0.01f;
  171. std::size_t octaves = 4;
  172. float lacunarity = 3.0f;
  173. float gain = 0.5f;
  174. float2 position = float2{x, z} * frequency;
  175. float fbm = math::noise::fbm
  176. (
  177. position,
  178. octaves,
  179. lacunarity,
  180. gain
  181. );
  182. auto
  183. [
  184. f1_sqr_distance,
  185. f1_displacement,
  186. f1_id
  187. ] = math::noise::voronoi::f1(position);
  188. float f1_distance = std::sqrt(f1_sqr_distance();
  189. float y = f1_distance * 5.0f + fbm * 0.5f;
  190. */
  191. float2 position = float2{x, z} * 0.05f;
  192. auto
  193. [
  194. f1_sqr_distance,
  195. f1_displacement,
  196. f1_id
  197. ] = math::noise::voronoi::f1(position);
  198. float f1_distance = std::sqrt(f1_sqr_distance);
  199. float y = f1_distance * 3.0f;
  200. return y;
  201. }
  202. );
  203. // Setup lighting
  204. double3 terrain_albedo = {0, 0, 0};
  205. if (terrain->contains("albedo"))
  206. {
  207. const auto& albedo_element = (*terrain)["albedo"];
  208. terrain_albedo[0] = albedo_element[0].get<double>();
  209. terrain_albedo[1]= albedo_element[1].get<double>();
  210. terrain_albedo[2] = albedo_element[2].get<double>();
  211. }
  212. ctx.astronomy_system->set_bounce_albedo(terrain_albedo);
  213. }
  214. else
  215. {
  216. ctx.logger->warning("Biome terrain undefined");
  217. }
  218. }
  219. catch (...)
  220. {
  221. ctx.logger->pop_task(EXIT_FAILURE);
  222. }
  223. ctx.logger->pop_task(EXIT_SUCCESS);
  224. }
  225. void colony(game::context& ctx, const std::filesystem::path& path)
  226. {
  227. ctx.logger->push_task("Loading colony from \"" + path.string() + "\"");
  228. try
  229. {
  230. json* data = ctx.resource_manager->load<json>(path);
  231. }
  232. catch (...)
  233. {
  234. ctx.logger->pop_task(EXIT_FAILURE);
  235. }
  236. ctx.logger->pop_task(EXIT_SUCCESS);
  237. }
  238. } // namespace load
  239. } // namespace game