From d2188eb6403000b238596e53b9ef5ab9074374ce Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Tue, 28 Sep 2021 01:00:30 +0800 Subject: [PATCH] Add new camera control scheme to forage state --- src/game/states/forage.cpp | 292 +++++++++++++++++++++++++++++++++++- src/game/states/loading.cpp | 7 +- 2 files changed, 289 insertions(+), 10 deletions(-) diff --git a/src/game/states/forage.cpp b/src/game/states/forage.cpp index a82d673..c11592f 100644 --- a/src/game/states/forage.cpp +++ b/src/game/states/forage.cpp @@ -27,16 +27,23 @@ #include "animation/screen-transition.hpp" #include "animation/ease.hpp" #include "resources/resource-manager.hpp" +#include "entity/components/camera.hpp" +#include "entity/components/constraints/spring-to.hpp" +#include "entity/components/constraints/three-dof.hpp" +#include "entity/components/constraint-stack.hpp" +#include "application.hpp" namespace game { namespace state { namespace forage { +static void setup_camera(game::context* ctx); +static void setup_controls(game::context* ctx); + void enter(game::context* ctx) { - // Switch to surface camera - ctx->underground_camera->set_active(false); - ctx->surface_camera->set_active(true); + setup_camera(ctx); + setup_controls(ctx); // Find planet EID by name entity::id planet_eid = ctx->entities["planet"]; @@ -69,10 +76,6 @@ void enter(game::context* ctx) ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude}); } - // Setup camera - ctx->surface_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0}); - ctx->surface_camera->set_exposure(-14.5f); - // Create larva { entity::archetype* larva_archetype = ctx->resource_manager->load("ant-larva.ent"); @@ -98,6 +101,281 @@ void enter(game::context* ctx) void exit(game::context* ctx) {} +void setup_camera(game::context* ctx) +{ + // Switch to surface camera + ctx->underground_camera->set_active(false); + ctx->surface_camera->set_active(true); + + // Create surface camera entity + if (!ctx->entities.count("surface_cam")) + { + // Create camera target entity + entity::id target_eid = ctx->entity_registry->create(); + ctx->entities["surface_cam_target"] = target_eid; + { + // Transform + entity::component::transform target_transform; + target_transform.local = math::identity_transform; + target_transform.world = target_transform.local; + target_transform.warp = true; + ctx->entity_registry->assign(target_eid, target_transform); + } + + // Create camera entity + entity::id camera_eid = ctx->entity_registry->create(); + ctx->entities["surface_cam"] = camera_eid; + + // Create camera transform component + entity::component::transform transform; + transform.local = math::identity_transform; + transform.world = transform.local; + transform.warp = true; + ctx->entity_registry->assign(camera_eid, transform); + + // Create camera camera component + entity::component::camera camera; + camera.object = ctx->surface_camera; + ctx->entity_registry->assign(camera_eid, camera); + + // Create camera 3DOF constraint entity + entity::id three_dof_constraint_eid = ctx->entity_registry->create(); + ctx->entities["surface_cam_3dof"] = three_dof_constraint_eid; + { + // Create 3DOF to constraint + entity::component::constraint::three_dof three_dof; + three_dof.yaw = 0.0f; + three_dof.pitch = 0.0f; + three_dof.roll = 0.0f; + ctx->entity_registry->assign(three_dof_constraint_eid, three_dof); + + // Create constraint stack node component + entity::component::constraint_stack_node node; + node.active = true; + node.weight = 1.0f; + node.next = entt::null; + ctx->entity_registry->assign(three_dof_constraint_eid, node); + } + + // Create camera spring to constraint entity + entity::id spring_constraint_eid = ctx->entity_registry->create(); + { + // Create spring to constraint + entity::component::constraint::spring_to spring; + spring.target = target_eid; + spring.translation = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 1.0f, math::two_pi}; + spring.translation.w = hz_to_rads(8.0f); + + spring.spring_translation = true; + spring.spring_rotation = false; + ctx->entity_registry->assign(spring_constraint_eid, spring); + + // Create constraint stack node component + entity::component::constraint_stack_node node; + node.active = true; + node.weight = 1.0f; + node.next = three_dof_constraint_eid; + ctx->entity_registry->assign(spring_constraint_eid, node); + } + + // Create camera constraint stack component + entity::component::constraint_stack constraint_stack; + constraint_stack.head = spring_constraint_eid; + ctx->entity_registry->assign(camera_eid, constraint_stack); + } + + ctx->surface_camera->set_exposure(-14.5f); +} + +void setup_controls(game::context* ctx) +{ + // Get underground camera entity + entity::id camera_eid = ctx->entities["surface_cam"]; + entity::id target_eid = ctx->entities["surface_cam_target"]; + entity::id three_dof_eid = ctx->entities["surface_cam_3dof"]; + + const float dolly_speed = 20.0f; + const float truck_speed = dolly_speed; + const float pedestal_speed = 30.0f; + const float pan_speed = math::radians(8.0f); + const float tilt_speed = pan_speed; + + const input::control* move_slow = ctx->controls["move_slow"]; + const input::control* move_fast = ctx->controls["move_fast"]; + const input::control* mouse_rotate = ctx->controls["mouse_rotate"]; + + ctx->controls["dolly_forward"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) + { + if (move_slow->is_active()) + value *= 0.5f; + if (move_fast->is_active()) + value *= 2.0f; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Dolly backward + ctx->controls["dolly_backward"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) + { + if (move_slow->is_active()) + value *= 0.5f; + if (move_fast->is_active()) + value *= 2.0f; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Truck right + ctx->controls["truck_right"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) + { + if (move_slow->is_active()) + value *= 0.5f; + if (move_fast->is_active()) + value *= 2.0f; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Truck left + ctx->controls["truck_left"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) + { + if (move_slow->is_active()) + value *= 0.5f; + if (move_fast->is_active()) + value *= 2.0f; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Pedestal up + ctx->controls["pedestal_up"]->set_active_callback + ( + [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) + { + if (move_slow->is_active()) + value *= 0.5f; + if (move_fast->is_active()) + value *= 2.0f; + + const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, movement); + } + ); + + // Pedestal down + ctx->controls["pedestal_down"]->set_active_callback + ( + [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) + { + if (move_slow->is_active()) + value *= 0.5f; + if (move_fast->is_active()) + value *= 2.0f; + + const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, movement); + } + ); + + // Mouse rotate + ctx->controls["mouse_rotate"]->set_activated_callback + ( + [ctx]() + { + ctx->app->set_relative_mouse_mode(true); + } + ); + ctx->controls["mouse_rotate"]->set_deactivated_callback + ( + [ctx]() + { + ctx->app->set_relative_mouse_mode(false); + } + ); + + // Pan left + ctx->controls["mouse_left"]->set_active_callback + ( + [ctx, three_dof_eid, pan_speed, mouse_rotate](float value) + { + if (!mouse_rotate->is_active()) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.yaw += pan_speed * value * (1.0f / 60.0f); + } + ); + + // Pan right + ctx->controls["mouse_right"]->set_active_callback + ( + [ctx, three_dof_eid, pan_speed, mouse_rotate](float value) + { + if (!mouse_rotate->is_active()) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.yaw -= pan_speed * value * (1.0f / 60.0f); + } + ); + + // Tilt up + ctx->controls["mouse_up"]->set_active_callback + ( + [ctx, three_dof_eid, tilt_speed, mouse_rotate](float value) + { + if (!mouse_rotate->is_active()) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.pitch -= tilt_speed * value * (1.0f / 60.0f); + three_dof.pitch = std::max(math::radians(-90.0f), three_dof.pitch); + } + ); + + // Tilt down + ctx->controls["mouse_down"]->set_active_callback + ( + [ctx, three_dof_eid, tilt_speed, mouse_rotate](float value) + { + if (!mouse_rotate->is_active()) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.pitch += tilt_speed * value * (1.0f / 60.0f); + three_dof.pitch = std::min(math::radians(90.0f), three_dof.pitch); + } + ); +} + } // namespace forage } // namespace state } // namespace game diff --git a/src/game/states/loading.cpp b/src/game/states/loading.cpp index 87e69ae..131d0cc 100644 --- a/src/game/states/loading.cpp +++ b/src/game/states/loading.cpp @@ -32,6 +32,7 @@ #include "entity/commands.hpp" #include "game/states/nuptial-flight.hpp" #include "game/states/splash.hpp" +#include "game/states/forage.hpp" #include "geom/spherical.hpp" #include "gl/drawing-mode.hpp" #include "gl/vertex-array.hpp" @@ -105,9 +106,9 @@ void enter(game::context* ctx) application::state next_state; if (ctx->option_quick_start.has_value()) { - next_state.name = "nuptial flight"; - next_state.enter = std::bind(game::state::nuptial_flight::enter, ctx); - next_state.exit = std::bind(game::state::nuptial_flight::exit, ctx); + next_state.name = "forage"; + next_state.enter = std::bind(game::state::forage::enter, ctx); + next_state.exit = std::bind(game::state::forage::exit, ctx); } else {