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

297 lines
9.8 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/world.hpp"
  20. #include "scene/text.hpp"
  21. #include "physics/light/vmag.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 "geom/spherical.hpp"
  34. #include "gl/drawing-mode.hpp"
  35. #include "gl/vertex-array.hpp"
  36. #include "gl/vertex-attribute.hpp"
  37. #include "gl/vertex-buffer.hpp"
  38. #include "physics/light/photometry.hpp"
  39. #include "physics/orbit/orbit.hpp"
  40. #include "physics/orbit/ephemeris.hpp"
  41. #include "render/material.hpp"
  42. #include "render/model.hpp"
  43. #include "render/passes/shadow-map-pass.hpp"
  44. #include "render/vertex-attribute.hpp"
  45. #include "resources/resource-manager.hpp"
  46. #include "scene/ambient-light.hpp"
  47. #include "scene/directional-light.hpp"
  48. #include "gl/texture-wrapping.hpp"
  49. #include "gl/texture-filter.hpp"
  50. #include "render/material-flags.hpp"
  51. #include "config.hpp"
  52. #include <iostream>
  53. namespace game {
  54. namespace world {
  55. void load_ephemeris(game::context& ctx)
  56. {
  57. // Load ephemeris
  58. ctx.orbit_system->set_ephemeris(ctx.resource_manager->load<physics::orbit::ephemeris<double>>("de421.eph"));
  59. }
  60. void create_stars(game::context& ctx)
  61. {
  62. // Load star catalog
  63. string_table* star_catalog = ctx.resource_manager->load<string_table>("stars.csv");
  64. // Allocate star catalog vertex data
  65. std::size_t star_count = 0;
  66. if (star_catalog->size() > 0)
  67. star_count = star_catalog->size() - 1;
  68. std::size_t star_vertex_size = 7;
  69. std::size_t star_vertex_stride = star_vertex_size * sizeof(float);
  70. float* star_vertex_data = new float[star_count * star_vertex_size];
  71. float* star_vertex = star_vertex_data;
  72. // Init starlight illuminance
  73. double starlight_illuminance = 0.0;
  74. // Build star catalog vertex data
  75. for (std::size_t i = 1; i < star_catalog->size(); ++i)
  76. {
  77. const string_table_row& catalog_row = (*star_catalog)[i];
  78. double ra = 0.0;
  79. double dec = 0.0;
  80. double vmag = 0.0;
  81. double bv_color = 0.0;
  82. // Parse star catalog entry
  83. try
  84. {
  85. ra = std::stod(catalog_row[1]);
  86. dec = std::stod(catalog_row[2]);
  87. vmag = std::stod(catalog_row[3]);
  88. bv_color = std::stod(catalog_row[4]);
  89. }
  90. catch (const std::exception&)
  91. {
  92. continue;
  93. }
  94. // Convert right ascension and declination from degrees to radians
  95. ra = math::wrap_radians(math::radians(ra));
  96. dec = math::wrap_radians(math::radians(dec));
  97. // Convert ICRF coordinates from spherical to Cartesian
  98. double3 position = physics::orbit::frame::bci::cartesian(double3{1.0, dec, ra});
  99. // Convert apparent magnitude to brightness factor relative to a 0th magnitude star
  100. double brightness = physics::light::vmag::to_brightness(vmag);
  101. // Convert color index to color temperature
  102. double cct = color::index::bv_to_cct(bv_color);
  103. // Calculate XYZ color from color temperature
  104. double3 color_xyz = color::cct::to_xyz(cct);
  105. // Transform XYZ color to ACEScg colorspace
  106. double3 color_acescg = color::xyz::to_acescg(color_xyz);
  107. // Scale color by relative brightness
  108. color_acescg *= brightness;
  109. // Build vertex
  110. *(star_vertex++) = static_cast<float>(position.x);
  111. *(star_vertex++) = static_cast<float>(position.y);
  112. *(star_vertex++) = static_cast<float>(position.z);
  113. *(star_vertex++) = static_cast<float>(color_acescg.x);
  114. *(star_vertex++) = static_cast<float>(color_acescg.y);
  115. *(star_vertex++) = static_cast<float>(color_acescg.z);
  116. *(star_vertex++) = static_cast<float>(brightness);
  117. // Convert apparent magnitude to illuminance and add to total starlight
  118. starlight_illuminance += physics::light::vmag::to_illuminance(vmag);
  119. }
  120. // Unload star catalog
  121. ctx.resource_manager->unload("stars.csv");
  122. // Allocate stars model
  123. render::model* stars_model = new render::model();
  124. // Get model VBO and VAO
  125. gl::vertex_buffer* vbo = stars_model->get_vertex_buffer();
  126. gl::vertex_array* vao = stars_model->get_vertex_array();
  127. // Resize model VBO and upload vertex data
  128. vbo->resize(star_count * star_vertex_stride, star_vertex_data);
  129. // Free star catalog vertex data
  130. delete[] star_vertex_data;
  131. std::size_t attribute_offset = 0;
  132. // Define position vertex attribute
  133. gl::vertex_attribute position_attribute;
  134. position_attribute.buffer = vbo;
  135. position_attribute.offset = attribute_offset;
  136. position_attribute.stride = star_vertex_stride;
  137. position_attribute.type = gl::vertex_attribute_type::float_32;
  138. position_attribute.components = 3;
  139. attribute_offset += position_attribute.components * sizeof(float);
  140. // Define color vertex attribute
  141. gl::vertex_attribute color_attribute;
  142. color_attribute.buffer = vbo;
  143. color_attribute.offset = attribute_offset;
  144. color_attribute.stride = star_vertex_stride;
  145. color_attribute.type = gl::vertex_attribute_type::float_32;
  146. color_attribute.components = 4;
  147. attribute_offset += color_attribute.components * sizeof(float);
  148. // Bind vertex attributes to VAO
  149. vao->bind(render::vertex_attribute::position, position_attribute);
  150. vao->bind(render::vertex_attribute::color, color_attribute);
  151. // Load star material
  152. render::material* star_material = ctx.resource_manager->load<render::material>("fixed-star.mtl");
  153. // Create model group
  154. render::model_group* stars_model_group = stars_model->add_group("stars");
  155. stars_model_group->set_material(star_material);
  156. stars_model_group->set_drawing_mode(gl::drawing_mode::points);
  157. stars_model_group->set_start_index(0);
  158. stars_model_group->set_index_count(star_count);
  159. // Pass stars model to sky pass
  160. ctx.sky_pass->set_stars_model(stars_model);
  161. // Pass starlight illuminance to astronomy system
  162. ctx.astronomy_system->set_starlight_illuminance(starlight_illuminance);
  163. }
  164. void create_sun(game::context& ctx)
  165. {
  166. // Create sun entity
  167. entity::archetype* sun_archetype = ctx.resource_manager->load<entity::archetype>("sun.ent");
  168. entity::id sun_eid = sun_archetype->create(*ctx.entity_registry);
  169. ctx.entities["sun"] = sun_eid;
  170. // Create sun directional light scene object
  171. scene::directional_light* sun_light = new scene::directional_light();
  172. sun_light->set_color({0, 0, 0});
  173. sun_light->update_tweens();
  174. // Create sky ambient light scene object
  175. scene::ambient_light* sky_light = new scene::ambient_light();
  176. sky_light->set_color({0, 0, 0});
  177. sky_light->update_tweens();
  178. // Add sun light scene objects to surface scene
  179. ctx.surface_scene->add_object(sun_light);
  180. ctx.surface_scene->add_object(sky_light);
  181. // Pass direct sun light scene object to shadow map pass and astronomy system
  182. ctx.surface_shadow_map_pass->set_light(sun_light);
  183. ctx.astronomy_system->set_sun_light(sun_light);
  184. ctx.astronomy_system->set_sky_light(sky_light);
  185. }
  186. void create_em_bary(game::context& ctx)
  187. {
  188. // Create earth-moon barycenter entity
  189. entity::archetype* em_bary_archetype = ctx.resource_manager->load<entity::archetype>("em-bary.ent");
  190. entity::id em_bary_eid = em_bary_archetype->create(*ctx.entity_registry);
  191. ctx.entities["em_bary"] = em_bary_eid;
  192. }
  193. void create_earth(game::context& ctx)
  194. {
  195. // Create earth entity
  196. entity::archetype* earth_archetype = ctx.resource_manager->load<entity::archetype>("earth.ent");
  197. entity::id earth_eid = earth_archetype->create(*ctx.entity_registry);
  198. ctx.entities["earth"] = earth_eid;
  199. // Assign orbital parent
  200. ctx.entity_registry->get<entity::component::orbit>(earth_eid).parent = ctx.entities["em_bary"];
  201. // Assign earth terrain component
  202. entity::component::terrain terrain;
  203. terrain.elevation = [](double, double) -> double
  204. {
  205. //return math::random<double>(0.0, 1.0);
  206. return 0.0;
  207. };
  208. terrain.max_lod = 0;
  209. terrain.patch_material = nullptr;
  210. //ctx.entity_registry->assign<entity::component::terrain>(earth_eid, terrain);
  211. // Pass earth to astronomy system as reference body
  212. ctx.astronomy_system->set_reference_body(earth_eid);
  213. }
  214. void create_moon(game::context& ctx)
  215. {
  216. // Create lunar entity
  217. entity::archetype* moon_archetype = ctx.resource_manager->load<entity::archetype>("moon.ent");
  218. entity::id moon_eid = moon_archetype->create(*ctx.entity_registry);
  219. ctx.entities["moon"] = moon_eid;
  220. // Assign orbital parent
  221. ctx.entity_registry->get<entity::component::orbit>(moon_eid).parent = ctx.entities["em_bary"];
  222. // Pass moon model to sky pass
  223. ctx.sky_pass->set_moon_model(ctx.resource_manager->load<render::model>("moon.mdl"));
  224. // Create moon directional light scene object
  225. scene::directional_light* moon_light = new scene::directional_light();
  226. moon_light->set_color({0, 0, 0});
  227. moon_light->update_tweens();
  228. // Add moon light scene objects to surface scene
  229. ctx.surface_scene->add_object(moon_light);
  230. // Pass moon light scene object to astronomy system
  231. ctx.astronomy_system->set_moon_light(moon_light);
  232. }
  233. void set_time(game::context& ctx, double t)
  234. {
  235. ctx.astronomy_system->set_time(t);
  236. ctx.orbit_system->set_time(t);
  237. }
  238. void set_time_scale(game::context& ctx, double scale)
  239. {
  240. static constexpr double seconds_per_day = 24.0 * 60.0 * 60.0;
  241. scale /= seconds_per_day;
  242. ctx.orbit_system->set_time_scale(scale);
  243. ctx.astronomy_system->set_time_scale(scale);
  244. }
  245. } // namespace world
  246. } // namespace game