/* * Copyright (C) 2021 Christopher J. Howard * * This file is part of Antkeeper source code. * * Antkeeper source code is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Antkeeper source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Antkeeper source code. If not, see . */ #include "animation/ease.hpp" #include "animation/screen-transition.hpp" #include "configuration.hpp" #include "debug/logger.hpp" #include "entity/archetype.hpp" #include "entity/components/cavity.hpp" #include "entity/components/copy-transform.hpp" #include "entity/components/copy-translation.hpp" #include "entity/components/model.hpp" #include "entity/components/genome.hpp" #include "entity/components/snap.hpp" #include "entity/components/terrain.hpp" #include "entity/components/tool.hpp" #include "entity/components/transform.hpp" #include "entity/components/camera-follow.hpp" #include "entity/components/orbit.hpp" #include "entity/components/blackbody.hpp" #include "entity/components/celestial-body.hpp" #include "entity/components/atmosphere.hpp" #include "entity/components/light.hpp" #include "entity/components/observer.hpp" #include "entity/commands.hpp" #include "game/game-context.hpp" #include "game/states/game-states.hpp" #include "math/math.hpp" #include "nest.hpp" #include "renderer/material.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-filter.hpp" #include "gl/texture-wrapping.hpp" #include "renderer/model.hpp" #include "renderer/passes/sky-pass.hpp" #include "renderer/passes/shadow-map-pass.hpp" #include "resources/resource-manager.hpp" #include "scene/model-instance.hpp" #include "scene/collection.hpp" #include "scene/camera.hpp" #include "scene/ambient-light.hpp" #include "scene/directional-light.hpp" #include "entity/systems/control.hpp" #include "entity/systems/camera.hpp" #include "entity/systems/render.hpp" #include "entity/systems/tool.hpp" #include "entity/systems/orbit.hpp" #include "entity/systems/astronomy.hpp" #include "game/biome.hpp" #include "utility/fundamental-types.hpp" #include "utility/bit-math.hpp" #include "genetics/genetics.hpp" #include "math/random.hpp" #include #include #include void play_state_enter(game_context* ctx) { debug::logger* logger = ctx->logger; logger->push_task("Entering play state"); resource_manager* resource_manager = ctx->resource_manager; entt::registry& entity_registry = *ctx->entity_registry; // Load biome if (ctx->option_biome.has_value()) { ctx->biome = resource_manager->load(ctx->option_biome.value() + ".bio"); } else { ctx->biome = resource_manager->load("forest.bio"); } // Apply biome parameters to scene sky_pass* sky_pass = ctx->overworld_sky_pass; sky_pass->set_enabled(true); sky_pass->set_sky_model(ctx->resource_manager->load("sky-dome.mdl")); sky_pass->set_moon_model(ctx->resource_manager->load("moon.mdl")); // Create sun auto sun_entity = entity_registry.create(); { entity::component::celestial_body body; body.radius = 6.957e+8; body.axial_tilt = math::radians(0.0); body.axial_rotation = math::radians(0.0); body.angular_frequency = math::radians(0.0); entity::component::orbit orbit; orbit.elements.a = 0.0; orbit.elements.e = 0.0; orbit.elements.i = math::radians(0.0); orbit.elements.raan = math::radians(0.0); orbit.elements.w = math::radians(0.0); orbit.elements.ta = math::radians(0.0); entity::component::blackbody blackbody; blackbody.temperature = 5778.0; entity::component::transform transform; transform.local = math::identity_transform; transform.warp = true; entity_registry.assign(sun_entity, body); entity_registry.assign(sun_entity, orbit); entity_registry.assign(sun_entity, blackbody); entity_registry.assign(sun_entity, transform); } // Create Earth auto earth_entity = entity_registry.create(); { entity::component::celestial_body body; body.radius = 6.3781e6; body.axial_tilt = math::radians(23.4393); body.axial_rotation = math::radians(280.46061837504); body.angular_frequency = math::radians(360.9856122880876128); entity::component::orbit orbit; orbit.elements.a = 1.496e+11; orbit.elements.e = 0.01671123; orbit.elements.i = math::radians(-0.00001531); orbit.elements.raan = math::radians(0.0); const double longitude_periapsis = math::radians(102.93768193); orbit.elements.w = longitude_periapsis - orbit.elements.raan; orbit.elements.ta = math::radians(100.46457166) - longitude_periapsis; entity::component::terrain terrain; terrain.elevation = [](double, double) -> double { //return math::random(0.0, 1.0); return 0.0; }; terrain.max_lod = 18; terrain.patch_material = resource_manager->load("desert-terrain.mtl"); entity::component::atmosphere atmosphere; atmosphere.exosphere_altitude = 65e3; atmosphere.index_of_refraction = 1.000293; atmosphere.rayleigh_density = 2.545e25; atmosphere.rayleigh_scale_height = 8000.0; atmosphere.mie_density = 14.8875; atmosphere.mie_scale_height = 1200.0; atmosphere.mie_anisotropy = 0.8; entity::component::transform transform; transform.local = math::identity_transform; transform.warp = true; entity_registry.assign(earth_entity, body); entity_registry.assign(earth_entity, orbit); entity_registry.assign(earth_entity, atmosphere); entity_registry.assign(earth_entity, terrain); entity_registry.assign(earth_entity, transform); } // Create observer auto observer_eid = entity_registry.create(); { entity::component::observer observer; observer.reference_body_eid = earth_entity; observer.elevation = 0.0; observer.latitude = 0.0; observer.longitude = 0.0; observer.camera = ctx->overworld_camera; entity_registry.assign(observer_eid, observer); } scene::ambient_light* ambient = new scene::ambient_light(); ambient->set_color({1, 1, 1}); ambient->set_intensity(0.0f); ambient->update_tweens(); ctx->overworld_scene->add_object(ambient); scene::directional_light* sun = new scene::directional_light(); //sun->set_intensity(1000.0f); //sun->set_light_texture(resource_manager->load("forest-gobo.tex")); //sun->set_light_texture_scale({2000, 2000}); //sun->set_light_texture_opacity(0.925f); //sun->look_at({2, 1, 0}, {0, 0, 0}, {0, 0, 1}); //sun->update_tweens(); ctx->overworld_scene->add_object(sun); ctx->overworld_shadow_map_pass->set_light(sun); // Set universal time const double universal_time = 0.0; ctx->astronomy_system->set_universal_time(universal_time); ctx->orbit_system->set_universal_time(universal_time); // Set astronomy system observation parameters ctx->astronomy_system->set_reference_body(earth_entity); ctx->astronomy_system->set_observer_location(double3{0.0, math::radians(0.0f), math::radians(0.0f)}); ctx->astronomy_system->set_sun_light(sun); ctx->astronomy_system->set_sky_pass(ctx->overworld_sky_pass); // Load entity archetypes entity::archetype* ant_hill_archetype = resource_manager->load("ant-hill.ent"); entity::archetype* nest_archetype = resource_manager->load("harvester-nest.ent"); entity::archetype* redwood_archetype = resource_manager->load("redwood.ent"); entity::archetype* forceps_archetype = resource_manager->load("forceps.ent"); entity::archetype* lens_archetype = resource_manager->load("lens.ent"); entity::archetype* brush_archetype = resource_manager->load("brush.ent"); entity::archetype* marker_archetype = resource_manager->load("marker.ent"); entity::archetype* container_archetype = resource_manager->load("container.ent"); entity::archetype* twig_archetype = resource_manager->load("twig.ent"); entity::archetype* larva_archetype = resource_manager->load("ant-larva.ent"); entity::archetype* flashlight_archetype = resource_manager->load("flashlight.ent"); entity::archetype* flashlight_light_cone_archetype = resource_manager->load("flashlight-light-cone.ent"); entity::archetype* lens_light_cone_archetype = resource_manager->load("lens-light-cone.ent"); entity::archetype* cube_archetype = resource_manager->load("unit-cube.ent"); entity::archetype* color_checker_archetype = resource_manager->load("color-checker.ent"); // Create tools /* forceps_archetype->assign(entity_registry, ctx->forceps_entity); lens_archetype->assign(entity_registry, ctx->lens_entity); brush_archetype->assign(entity_registry, ctx->brush_entity); marker_archetype->assign(entity_registry, ctx->marker_entity); container_archetype->assign(entity_registry, ctx->container_entity); twig_archetype->assign(entity_registry, ctx->twig_entity); */ // Create flashlight and light cone, set light cone parent to flashlight, and move both to underworld scene /* flashlight_archetype->assign(entity_registry, ctx->flashlight_entity); auto flashlight_light_cone = flashlight_light_cone_archetype->create(entity_registry); entity::command::parent(entity_registry, flashlight_light_cone, ctx->flashlight_entity); entity::command::assign_render_layers(entity_registry, ctx->flashlight_entity, 2); entity::command::assign_render_layers(entity_registry, flashlight_light_cone, 2); */ // Make lens tool's model instance unculled, so its shadow is always visible. //scene::model_instance* lens_model_instance = ctx->render_system->get_model_instance(ctx->lens_entity); //if (lens_model_instance) //{ //lens_model_instance->set_culling_mask(&ctx->no_cull); //} // Create lens light cone and set its parent to lens //auto lens_light_cone = lens_light_cone_archetype->create(entity_registry); //entity::command::bind_transform(entity_registry, lens_light_cone, ctx->lens_entity); //entity::command::parent(entity_registry, lens_light_cone, ctx->lens_entity); // Hide inactive tools /* entity::command::assign_render_layers(entity_registry, ctx->forceps_entity, 0); entity::command::assign_render_layers(entity_registry, ctx->brush_entity, 0); entity::command::assign_render_layers(entity_registry, ctx->lens_entity, 0); entity::command::assign_render_layers(entity_registry, ctx->marker_entity, 0); entity::command::assign_render_layers(entity_registry, ctx->container_entity, 0); entity::command::assign_render_layers(entity_registry, ctx->twig_entity, 0); */ // Activate brush tool //ctx->tool_system->set_active_tool(ctx->brush_entity); // Create ant-hill //auto ant_hill_entity = ant_hill_archetype->create(entity_registry); //entity::command::place(entity_registry, ant_hill_entity, earth_entity, 0.0, 0.0, 0.0); // Create color checker /* auto color_checker = color_checker_archetype->create(entity_registry); entity::command::place(entity_registry, color_checker, {-10, -10}); auto& cc_transform = entity_registry.get(color_checker); cc_transform.local.scale *= 10.0f; cc_transform.local.rotation = math::angle_axis(math::radians(-90.0f), {1, 0, 0}); */ // Setup camera focal point entity::component::transform focal_point_transform; focal_point_transform.local = math::identity_transform; //focal_point_transform.local.translation = {0, 6.3781e6, 0}; focal_point_transform.warp = true; entity::component::camera_follow focal_point_follow; entity::component::snap focal_point_snap; focal_point_snap.ray = {float3{0, 10000, 0}, float3{0, -1, 0}}; focal_point_snap.warp = false; focal_point_snap.relative = true; focal_point_snap.autoremove = false; entity_registry.assign_or_replace(ctx->focal_point_entity, focal_point_transform); entity_registry.assign_or_replace(ctx->focal_point_entity, focal_point_follow); //entity_registry.assign_or_replace(ctx->focal_point_entity, focal_point_snap); // Setup camera ctx->overworld_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0}); ctx->overworld_camera->set_exposure(-14.5f); ctx->camera_system->set_camera(ctx->overworld_camera); ctx->overworld_scene->update_tweens(); // Allocate a nest nest* nest = new ::nest(); // Setup initial nest parameters float tunnel_radius = 1.15f; nest->set_tunnel_radius(tunnel_radius); nest::shaft* central_shaft = nest->get_central_shaft(); central_shaft->chirality = 1.0f; central_shaft->rotation = math::radians(0.0f); central_shaft->depth = {0.0f, 200.0f}; central_shaft->radius = {15.0f, 15.0f}; central_shaft->pitch = {40.0f, 40.0f}; central_shaft->translation = {{{0.0f, 0.0f}, {0.0f, 0.0f}}}; central_shaft->current_depth = 0.0f; for (std::size_t i = 0; i < 4; ++i) { nest::chamber chamber; chamber.shaft = central_shaft; chamber.depth = (i + 1) * 50.0f; chamber.rotation = math::radians(0.0f); chamber.inner_radius = 4.0f; chamber.outer_radius = 10.0f; central_shaft->chambers.push_back(chamber); } // Dig nest shafts float shift = 0.1f; for (int i = 0; i < 800; ++i) { entity::component::cavity cavity; cavity.position = nest->extend_shaft(*nest->get_central_shaft()); cavity.position += float3{math::random(-shift, shift), math::random(-shift, shift), math::random(-shift, shift)}; cavity.radius = tunnel_radius * math::random(1.0f, 1.1f); entity_registry.assign(entity_registry.create(), cavity); } // Dig nest chambers /* for (int i = 0; i < central_shaft->chambers.size(); ++i) { for (int j = 0; j < 150; ++j) { entity::component::cavity cavity; cavity.position = nest->expand_chamber(central_shaft->chambers[i]); cavity.position += float3{math::random(-shift, shift), math::random(-shift, shift), math::random(-shift, shift)}; cavity.radius = tunnel_radius * math::random(1.0f, 1.1f); entity_registry.assign(entity_registry.create(), cavity); } } */ // Place larva in chamber { auto larva_eid = larva_archetype->create(entity_registry); entity::command::assign_render_layers(entity_registry, larva_eid, 1); entity::command::warp_to(entity_registry, larva_eid, {50, 0.1935f, 0}); //auto& transform = entity_registry.get(larva_entity); //transform.transform = math::identity_transform; //transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]); //transform.transform.translation.y -= 1.0f; // Construct larva genome entity::component::genome genome; genome.ploidy = 2; const std::string antp = "ATGACCATGAGCACCAACAACTGCGAAAGCATGACCAGCTATTTTACCAACAGCTATATGGGCGCGGATATGCATCATGGCCATTATCCGGGCAACGGCGTGACCGATCTGGATGCGCAGCAGATGCATCATTATAGCCAGAACGCGAACCATCAGGGCAACATGCCGTATCCGCGCTTTCCGCCGTATGATCGCATGCCGTATTATAACGGCCAGGGCATGGATCAGCAGCAGCAGCATCAGGTGTATAGCCGCCCGGATAGCCCGAGCAGCCAGGTGGGCGGCGTGATGCCGCAGGCGCAGACCAACGGCCAGCTGGGCGTGCCGCAGCAGCAGCAGCAGCAGCAGCAGCAGCCGAGCCAGAACCAGCAGCAGCAGCAGGCGCAGCAGGCGCCGCAGCAGCTGCAGCAGCAGCTGCCGCAGGTGACCCAGCAGGTGACCCATCCGCAGCAGCAGCAGCAGCAGCCGGTGGTGTATGCGAGCTGCAAACTGCAGGCGGCGGTGGGCGGCCTGGGCATGGTGCCGGAAGGCGGCAGCCCGCCGCTGGTGGATCAGATGAGCGGCCATCATATGAACGCGCAGATGACCCTGCCGCATCATATGGGCCATCCGCAGGCGCAGGTGCATCAGAACCATCATAACATGGGCATGTATCAGCAGCAGAGCGGCGTGCCGCCGGTGGGCGCGCCGCCGCAGGGCATGATGCATCAGGGCCAGGGCCCGCCGCAGATGCATCAGGGCCATCCGGGCCAGCATACCCCGCCGAGCCAGAACCCGAACAGCCAGAGCAGCGGCATGCCGAGCCCGCTGTATCCGTGGATGCGCAGCCAGTTTGAACGCAAACGCGGCCGCCAGACCTATACCCGCTATCAGACCCTGGAACTGGAAAAAGAATTTCATTTTAACCGCTATCTGACCCGCCGCCGCCGCATTGAAATTGCGCATGCGCTGTGCCTGACCGAACGCCAGATTAAAATTTGGTTTCAGAACCGCCGCATGAAATGGAAAAAAGAAAACAAAACCAAAGGCGAACCGGGCAGCGGCGGCGAAGGCGATGAAATTACCCCGCCGAACAGCCCGCAGTAG"; genome.chromosomes.push_back(antp); entity_registry.assign(larva_eid, genome); } entity::system::control* control_system = ctx->control_system; control_system->update(0.0, 0.0); control_system->set_nest(nest); // Start fade in ctx->fade_transition->transition(1.0f, true, ease::in_quad); logger->pop_task(EXIT_SUCCESS); std::string biome_name = (*ctx->strings)[ctx->biome->name]; logger->log("Entered biome \"" + biome_name + "\""); } void play_state_exit(game_context* ctx) { debug::logger* logger = ctx->logger; logger->push_task("Exiting play state"); logger->pop_task(EXIT_SUCCESS); }