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

497 lines
14 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/states/loading.hpp"
  20. #include "application.hpp"
  21. #include "astro/illuminance.hpp"
  22. #include "color/color.hpp"
  23. #include "entity/components/atmosphere.hpp"
  24. #include "entity/components/blackbody.hpp"
  25. #include "entity/components/celestial-body.hpp"
  26. #include "entity/components/orbit.hpp"
  27. #include "entity/components/terrain.hpp"
  28. #include "entity/components/transform.hpp"
  29. #include "entity/systems/astronomy.hpp"
  30. #include "entity/systems/orbit.hpp"
  31. #include "entity/commands.hpp"
  32. #include "entity/archetype.hpp"
  33. #include "game/states/nuptial-flight.hpp"
  34. #include "game/states/splash.hpp"
  35. #include "game/states/main-menu.hpp"
  36. #include "game/controls.hpp"
  37. #include "geom/spherical.hpp"
  38. #include "gl/drawing-mode.hpp"
  39. #include "gl/vertex-array.hpp"
  40. #include "gl/vertex-attribute.hpp"
  41. #include "gl/vertex-buffer.hpp"
  42. #include "physics/light/photometry.hpp"
  43. #include "physics/orbit/orbit.hpp"
  44. #include "render/material.hpp"
  45. #include "render/model.hpp"
  46. #include "render/passes/shadow-map-pass.hpp"
  47. #include "render/vertex-attribute.hpp"
  48. #include "resources/resource-manager.hpp"
  49. #include "scene/ambient-light.hpp"
  50. #include "scene/directional-light.hpp"
  51. #include "utility/timestamp.hpp"
  52. #include "configuration.hpp"
  53. #include <unordered_set>
  54. #include "gl/texture-wrapping.hpp"
  55. #include "gl/texture-filter.hpp"
  56. #include "render/material-flags.hpp"
  57. #include "game/fonts.hpp"
  58. namespace game {
  59. namespace state {
  60. namespace loading {
  61. /// Loads control profile and calibrates gamepads
  62. static void load_controls(game::context* ctx);
  63. /// Creates the universe and solar system.
  64. static void cosmogenesis(game::context* ctx);
  65. /// Creates a sun.
  66. static void heliogenesis(game::context* ctx);
  67. /// Creates a planet.
  68. static void planetogenesis(game::context* ctx);
  69. /// Creates a moon.
  70. static void selenogenesis(game::context* ctx);
  71. /// Creates fixed stars.
  72. static void extrasolar_heliogenesis(game::context* ctx);
  73. /// Creates an ant colony
  74. static void colonigenesis(game::context* ctx);
  75. void enter(game::context* ctx)
  76. {
  77. // Load controls
  78. ctx->logger->push_task("Loading controls");
  79. try
  80. {
  81. load_controls(ctx);
  82. }
  83. catch (...)
  84. {
  85. ctx->logger->pop_task(EXIT_FAILURE);
  86. }
  87. ctx->logger->pop_task(EXIT_SUCCESS);
  88. // Load fonts
  89. ctx->logger->push_task("Loading fonts");
  90. try
  91. {
  92. game::load_fonts(ctx);
  93. }
  94. catch (...)
  95. {
  96. ctx->logger->pop_task(EXIT_FAILURE);
  97. }
  98. ctx->logger->pop_task(EXIT_SUCCESS);
  99. /*
  100. // Create universe
  101. ctx->logger->push_task("Creating the universe");
  102. try
  103. {
  104. cosmogenesis(ctx);
  105. }
  106. catch (...)
  107. {
  108. ctx->logger->pop_task(EXIT_FAILURE);
  109. throw;
  110. }
  111. ctx->logger->pop_task(EXIT_SUCCESS);
  112. */
  113. // Determine next game state
  114. application::state next_state;
  115. if (ctx->option_quick_start.has_value())
  116. {
  117. next_state.name = "main_menu";
  118. next_state.enter = std::bind(game::state::main_menu::enter, ctx, 0);
  119. next_state.exit = std::bind(game::state::main_menu::exit, ctx);
  120. }
  121. else
  122. {
  123. next_state.name = "splash";
  124. next_state.enter = std::bind(game::state::splash::enter, ctx);
  125. next_state.exit = std::bind(game::state::splash::exit, ctx);
  126. }
  127. // Queue next game state
  128. ctx->app->queue_state(next_state);
  129. }
  130. void exit(game::context* ctx)
  131. {}
  132. void load_controls(game::context* ctx)
  133. {
  134. // If a control profile is set in the config file
  135. if (ctx->config->contains("control_profile"))
  136. {
  137. // Load control profile
  138. json* profile = ctx->resource_manager->load<json>((*ctx->config)["control_profile"].get<std::string>());
  139. // Apply control profile
  140. if (profile)
  141. {
  142. game::apply_control_profile(ctx, *profile);
  143. }
  144. }
  145. // Calibrate gamepads
  146. for (input::gamepad* gamepad: ctx->app->get_gamepads())
  147. {
  148. ctx->logger->push_task("Loading calibration for gamepad " + gamepad->get_guid());
  149. json* calibration = game::load_gamepad_calibration(ctx, gamepad);
  150. if (!calibration)
  151. {
  152. ctx->logger->pop_task(EXIT_FAILURE);
  153. ctx->logger->push_task("Generating default calibration for gamepad " + gamepad->get_guid());
  154. json default_calibration = game::default_gamepad_calibration();
  155. apply_gamepad_calibration(gamepad, default_calibration);
  156. if (!save_gamepad_calibration(ctx, gamepad, default_calibration))
  157. ctx->logger->pop_task(EXIT_FAILURE);
  158. else
  159. ctx->logger->pop_task(EXIT_SUCCESS);
  160. }
  161. else
  162. {
  163. ctx->logger->pop_task(EXIT_SUCCESS);
  164. apply_gamepad_calibration(gamepad, *calibration);
  165. }
  166. }
  167. // Toggle fullscreen
  168. ctx->controls["toggle_fullscreen"]->set_activated_callback
  169. (
  170. [ctx]()
  171. {
  172. bool fullscreen = !ctx->app->is_fullscreen();
  173. ctx->app->set_fullscreen(fullscreen);
  174. if (!fullscreen)
  175. {
  176. int2 resolution;
  177. resolution.x = (*ctx->config)["windowed_resolution"][0].get<int>();
  178. resolution.y = (*ctx->config)["windowed_resolution"][1].get<int>();
  179. ctx->app->resize_window(resolution.x, resolution.y);
  180. }
  181. (*ctx->config)["fullscreen"] = fullscreen;
  182. }
  183. );
  184. // Screenshot
  185. ctx->controls["screenshot"]->set_activated_callback
  186. (
  187. [ctx]()
  188. {
  189. std::string path = ctx->screenshots_path + "antkeeper-" + timestamp() + ".png";
  190. ctx->app->save_frame(path);
  191. }
  192. );
  193. // Set activation threshold for menu navigation controls to mitigate drifting gamepad axes
  194. const float menu_activation_threshold = 0.1f;
  195. ctx->controls["menu_up"]->set_activation_threshold(menu_activation_threshold);
  196. ctx->controls["menu_down"]->set_activation_threshold(menu_activation_threshold);
  197. ctx->controls["menu_left"]->set_activation_threshold(menu_activation_threshold);
  198. ctx->controls["menu_right"]->set_activation_threshold(menu_activation_threshold);
  199. }
  200. void cosmogenesis(game::context* ctx)
  201. {
  202. // Init time
  203. const double time = 0.0;
  204. ctx->astronomy_system->set_universal_time(time);
  205. ctx->orbit_system->set_universal_time(time);
  206. // Create sun
  207. ctx->logger->push_task("Creating the sun");
  208. try
  209. {
  210. heliogenesis(ctx);
  211. }
  212. catch (...)
  213. {
  214. ctx->logger->pop_task(EXIT_FAILURE);
  215. throw;
  216. }
  217. ctx->logger->pop_task(EXIT_SUCCESS);
  218. // Create planet
  219. ctx->logger->push_task("Creating the planet");
  220. try
  221. {
  222. planetogenesis(ctx);
  223. }
  224. catch (...)
  225. {
  226. ctx->logger->pop_task(EXIT_FAILURE);
  227. throw;
  228. }
  229. ctx->logger->pop_task(EXIT_SUCCESS);
  230. // Create moon
  231. ctx->logger->push_task("Creating the moon");
  232. try
  233. {
  234. selenogenesis(ctx);
  235. }
  236. catch (...)
  237. {
  238. ctx->logger->pop_task(EXIT_FAILURE);
  239. throw;
  240. }
  241. ctx->logger->pop_task(EXIT_SUCCESS);
  242. // Create fixed stars
  243. ctx->logger->push_task("Creating fixed stars");
  244. try
  245. {
  246. extrasolar_heliogenesis(ctx);
  247. }
  248. catch (...)
  249. {
  250. ctx->logger->pop_task(EXIT_FAILURE);
  251. throw;
  252. }
  253. ctx->logger->pop_task(EXIT_SUCCESS);
  254. // Create ant colony
  255. ctx->logger->push_task("Creating ant colony");
  256. try
  257. {
  258. colonigenesis(ctx);
  259. }
  260. catch (...)
  261. {
  262. ctx->logger->pop_task(EXIT_FAILURE);
  263. throw;
  264. }
  265. ctx->logger->pop_task(EXIT_SUCCESS);
  266. }
  267. void heliogenesis(game::context* ctx)
  268. {
  269. // Create solar entity
  270. entity::archetype* sun_archetype = ctx->resource_manager->load<entity::archetype>("sun.ent");
  271. entity::id sun_eid = sun_archetype->create(*ctx->entity_registry);
  272. ctx->entities["sun"] = sun_eid;
  273. // Create direct sun light scene object
  274. scene::directional_light* sun_direct = new scene::directional_light();
  275. // Create ambient sun light scene object
  276. scene::ambient_light* sun_ambient = new scene::ambient_light();
  277. sun_ambient->set_color({1, 1, 1});
  278. sun_ambient->set_intensity(0.0f);
  279. sun_ambient->update_tweens();
  280. // Add sun light scene objects to surface scene
  281. ctx->surface_scene->add_object(sun_direct);
  282. ctx->surface_scene->add_object(sun_ambient);
  283. // Pass direct sun light scene object to shadow map pass and astronomy system
  284. ctx->surface_shadow_map_pass->set_light(sun_direct);
  285. ctx->astronomy_system->set_sun_light(sun_direct);
  286. }
  287. void planetogenesis(game::context* ctx)
  288. {
  289. // Create planetary entity
  290. entity::archetype* planet_archetype = ctx->resource_manager->load<entity::archetype>("planet.ent");
  291. entity::id planet_eid = planet_archetype->create(*ctx->entity_registry);
  292. ctx->entities["planet"] = planet_eid;
  293. // Assign planetary terrain component
  294. entity::component::terrain terrain;
  295. terrain.elevation = [](double, double) -> double
  296. {
  297. //return math::random<double>(0.0, 1.0);
  298. return 0.0;
  299. };
  300. terrain.max_lod = 0;
  301. terrain.patch_material = nullptr;
  302. ctx->entity_registry->assign<entity::component::terrain>(planet_eid, terrain);
  303. // Pass planet to astronomy system as reference body
  304. ctx->astronomy_system->set_reference_body(planet_eid);
  305. // Load sky model
  306. ctx->surface_sky_pass->set_sky_model(ctx->resource_manager->load<render::model>("sky-dome.mdl"));
  307. }
  308. void selenogenesis(game::context* ctx)
  309. {
  310. // Create lunar entity
  311. entity::id moon_eid = ctx->entity_registry->create();
  312. ctx->entities["moon"] = moon_eid;
  313. // Pass moon model to sky pass
  314. ctx->surface_sky_pass->set_moon_model(ctx->resource_manager->load<render::model>("moon.mdl"));
  315. }
  316. void extrasolar_heliogenesis(game::context* ctx)
  317. {
  318. // Load star catalog
  319. string_table* star_catalog = ctx->resource_manager->load<string_table>("stars.csv");
  320. // Allocate star catalog vertex data
  321. std::size_t star_count = 0;
  322. if (star_catalog->size() > 0)
  323. star_count = star_catalog->size() - 1;
  324. std::size_t star_vertex_size = 7;
  325. std::size_t star_vertex_stride = star_vertex_size * sizeof(float);
  326. float* star_vertex_data = new float[star_count * star_vertex_size];
  327. float* star_vertex = star_vertex_data;
  328. // Build star catalog vertex data
  329. for (std::size_t i = 1; i < star_catalog->size(); ++i)
  330. {
  331. const string_table_row& catalog_row = (*star_catalog)[i];
  332. double ra = 0.0;
  333. double dec = 0.0;
  334. double vmag = 0.0;
  335. double bv_color = 0.0;
  336. // Parse star catalog entry
  337. try
  338. {
  339. ra = std::stod(catalog_row[1]);
  340. dec = std::stod(catalog_row[2]);
  341. vmag = std::stod(catalog_row[3]);
  342. bv_color = std::stod(catalog_row[4]);
  343. }
  344. catch (const std::exception& e)
  345. {
  346. continue;
  347. }
  348. // Convert right ascension and declination from degrees to radians
  349. ra = math::wrap_radians(math::radians(ra));
  350. dec = math::wrap_radians(math::radians(dec));
  351. // Transform spherical equatorial coordinates to rectangular equatorial coordinates
  352. double3 position_bci = geom::spherical::to_cartesian(double3{1.0, dec, ra});
  353. // Transform coordinates from equatorial space to inertial space
  354. physics::frame<double> bci_to_inertial = physics::orbit::inertial::to_bci({0, 0, 0}, 0.0, math::radians(23.4393)).inverse();
  355. double3 position_inertial = bci_to_inertial * position_bci;
  356. // Convert color index to color temperature
  357. double cct = color::index::bv_to_cct(bv_color);
  358. // Calculate XYZ color from color temperature
  359. double3 color_xyz = color::cct::to_xyz(cct);
  360. // Transform XYZ color to ACEScg colorspace
  361. double3 color_acescg = color::xyz::to_acescg(color_xyz);
  362. // Convert apparent magnitude to irradiance (W/m^2)
  363. double vmag_irradiance = std::pow(10.0, 0.4 * (-vmag - 19.0 + 0.4));
  364. // Convert irradiance to illuminance
  365. double vmag_illuminance = vmag_irradiance * (683.0 * 0.14);
  366. // Scale color by illuminance
  367. double3 scaled_color = color_acescg * vmag_illuminance;
  368. // Build vertex
  369. *(star_vertex++) = static_cast<float>(position_inertial.x);
  370. *(star_vertex++) = static_cast<float>(position_inertial.y);
  371. *(star_vertex++) = static_cast<float>(position_inertial.z);
  372. *(star_vertex++) = static_cast<float>(scaled_color.x);
  373. *(star_vertex++) = static_cast<float>(scaled_color.y);
  374. *(star_vertex++) = static_cast<float>(scaled_color.z);
  375. *(star_vertex++) = static_cast<float>(vmag);
  376. }
  377. // Unload star catalog
  378. ctx->resource_manager->unload("stars.csv");
  379. // Allocate stars model
  380. render::model* stars_model = new render::model();
  381. // Get model VBO and VAO
  382. gl::vertex_buffer* vbo = stars_model->get_vertex_buffer();
  383. gl::vertex_array* vao = stars_model->get_vertex_array();
  384. // Resize model VBO and upload vertex data
  385. vbo->resize(star_count * star_vertex_stride, star_vertex_data);
  386. // Free star catalog vertex data
  387. delete[] star_vertex_data;
  388. std::size_t attribute_offset = 0;
  389. // Define position vertex attribute
  390. gl::vertex_attribute position_attribute;
  391. position_attribute.buffer = vbo;
  392. position_attribute.offset = attribute_offset;
  393. position_attribute.stride = star_vertex_stride;
  394. position_attribute.type = gl::vertex_attribute_type::float_32;
  395. position_attribute.components = 3;
  396. attribute_offset += position_attribute.components * sizeof(float);
  397. // Define color vertex attribute
  398. gl::vertex_attribute color_attribute;
  399. color_attribute.buffer = vbo;
  400. color_attribute.offset = attribute_offset;
  401. color_attribute.stride = star_vertex_stride;
  402. color_attribute.type = gl::vertex_attribute_type::float_32;
  403. color_attribute.components = 4;
  404. attribute_offset += color_attribute.components * sizeof(float);
  405. // Bind vertex attributes to VAO
  406. vao->bind(render::vertex_attribute::position, position_attribute);
  407. vao->bind(render::vertex_attribute::color, color_attribute);
  408. // Load star material
  409. render::material* star_material = ctx->resource_manager->load<render::material>("fixed-star.mtl");
  410. // Create model group
  411. render::model_group* stars_model_group = stars_model->add_group("stars");
  412. stars_model_group->set_material(star_material);
  413. stars_model_group->set_drawing_mode(gl::drawing_mode::points);
  414. stars_model_group->set_start_index(0);
  415. stars_model_group->set_index_count(star_count);
  416. // Pass stars model to sky pass
  417. ctx->surface_sky_pass->set_stars_model(stars_model);
  418. }
  419. void colonigenesis(game::context* ctx)
  420. {}
  421. } // namespace loading
  422. } // namespace state
  423. } // namespace game