From f95819628d20e23f9df31a0d085d5de5e2f0eeed Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 20 Aug 2020 03:43:54 -0700 Subject: [PATCH] Make orbit cam spring oscillation frequencie tunable, add hz<->rads conversion functions, and fix relative mouse movement cursor visibility bug --- src/animation/orbit-cam.cpp | 57 +++++++++++++++++++++--------- src/animation/orbit-cam.hpp | 5 +++ src/animation/spring.hpp | 30 ++++++++++++++++ src/application.cpp | 12 ++++--- src/application.hpp | 1 + src/game/bootloader.cpp | 11 +++--- src/game/systems/camera-system.cpp | 9 ++++- src/game/systems/tool-system.cpp | 5 +++ src/game/systems/tool-system.hpp | 6 ++-- src/game/systems/ui-system.cpp | 5 +++ src/game/systems/ui-system.hpp | 6 ++-- 11 files changed, 117 insertions(+), 30 deletions(-) diff --git a/src/animation/orbit-cam.cpp b/src/animation/orbit-cam.cpp index fd5c058..8ca3ee6 100644 --- a/src/animation/orbit-cam.cpp +++ b/src/animation/orbit-cam.cpp @@ -33,25 +33,24 @@ orbit_cam::orbit_cam(): clip_near_limits({-std::numeric_limits::infinity(), std::numeric_limits::infinity()}), clip_far_limits({-std::numeric_limits::infinity(), std::numeric_limits::infinity()}) { - // Init focal point spring - focal_point_spring.v = {0.0f, 0.0f, 0.0f}; + // Make all springs critically-damped focal_point_spring.z = 1.0f; - focal_point_spring.w = 2.0f * math::two_pi; - - // Init azimuth spring - azimuth_spring.v = 0.0f; azimuth_spring.z = 1.0f; - azimuth_spring.w = 2.0f * math::two_pi; - - // Init elevation spring - elevation_spring.v = 0.0f; elevation_spring.z = 1.0f; - elevation_spring.w = 2.0f * math::two_pi; - - // Init zoom spring - zoom_spring.v = 0.0f; zoom_spring.z = 1.0f; - zoom_spring.w = 5.0f * math::two_pi; + + // Init spring oscillation frequencies to 1 rad/s + focal_point_spring.w = math::two_pi; + azimuth_spring.w = math::two_pi; + elevation_spring.w = math::two_pi; + zoom_spring.w = math::two_pi; + + // Zero spring values and velocities + focal_point_spring.x1 = {0.0f, 0.0f, 0.0f}; + azimuth_spring.x1 = 0.0f; + elevation_spring.x1 = 0.0f; + zoom_spring.x1 = 0.0f; + reset_springs(); } orbit_cam::~orbit_cam() @@ -91,7 +90,6 @@ void orbit_cam::update(float dt) update_transform(transform); // Update camera projection - float zoom_factor = 0.0f; update_projection(fov, aspect_ratio, clip_near, clip_far); } @@ -117,10 +115,17 @@ void orbit_cam::zoom(float factor) void orbit_cam::reset_springs() { + // Reset values focal_point_spring.x0 = focal_point_spring.x1; azimuth_spring.x0 = azimuth_spring.x1; elevation_spring.x0 = elevation_spring.x1; zoom_spring.x0 = zoom_spring.x1; + + // Reset velocities + focal_point_spring.v = {0.0f, 0.0f, 0.0f}; + azimuth_spring.v = 0.0f; + elevation_spring.v = 0.0f; + zoom_spring.v = 0.0f; } void orbit_cam::set_aspect_ratio(float ratio) @@ -197,3 +202,23 @@ void orbit_cam::set_clip_far_limits(const std::array& limits) { clip_far_limits = limits; } + +void orbit_cam::set_focal_point_oscillation(float frequency) +{ + focal_point_spring.w = frequency; +} + +void orbit_cam::set_azimuth_oscillation(float frequency) +{ + azimuth_spring.w = frequency; +} + +void orbit_cam::set_elevation_oscillation(float frequency) +{ + elevation_spring.w = frequency; +} + +void orbit_cam::set_zoom_oscillation(float frequency) +{ + zoom_spring.w = frequency; +} diff --git a/src/animation/orbit-cam.hpp b/src/animation/orbit-cam.hpp index e53d74c..6c767b0 100644 --- a/src/animation/orbit-cam.hpp +++ b/src/animation/orbit-cam.hpp @@ -61,6 +61,11 @@ public: void set_clip_near_limits(const std::array& limits); void set_clip_far_limits(const std::array& limits); + void set_focal_point_oscillation(float frequency); + void set_azimuth_oscillation(float frequency); + void set_elevation_oscillation(float frequency); + void set_zoom_oscillation(float frequency); + const float3& get_focal_point() const; float get_azimuth() const; float get_elevation() const; diff --git a/src/animation/spring.hpp b/src/animation/spring.hpp index 53e9690..1b55b94 100644 --- a/src/animation/spring.hpp +++ b/src/animation/spring.hpp @@ -66,6 +66,24 @@ void spring(T& x0, T& v, const T& x1, S z, S w, S dt); template void solve_numeric_spring(numeric_spring& ns, S dt); +/** + * Converts a frequency from hertz to radians per second. + * + * @param hz Frequency in hertz. + * @return Frequency in radians per second. + */ +template +T hz_to_rads(T hz); + +/** + * Converts a frequency from radians per second to hertz. + * + * @param rads Frequency in radians per second. + * @return Frequency in hertz. + */ +template +T rads_to_hz(T rads); + template void spring(T& x0, T& v, const T& x1, S z, S w, S dt) { @@ -86,4 +104,16 @@ void solve_numeric_spring(numeric_spring& ns, S dt) spring(ns.x0, ns.v, ns.x1, ns.z, ns.w, dt); } +template +inline T hz_to_rads(T hz) +{ + return hz * math::two_pi; +} + +template +inline T rads_to_hz(T rads) +{ + return rads / math::two_pi; +} + #endif // ANTKEEPER_SPRING_HPP diff --git a/src/application.cpp b/src/application.cpp index 682b36d..0c125d7 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -47,6 +47,7 @@ application::application(): render_callback(nullptr), fullscreen(true), vsync(true), + cursor_visible(true), display_dimensions({0, 0}), window_dimensions({0, 0}), viewport_dimensions({0, 0}), @@ -358,6 +359,7 @@ void application::set_title(const std::string& title) void application::set_cursor_visible(bool visible) { SDL_ShowCursor((visible) ? SDL_ENABLE : SDL_DISABLE); + cursor_visible = visible; } void application::set_relative_mouse_mode(bool enabled) @@ -365,13 +367,15 @@ void application::set_relative_mouse_mode(bool enabled) if (enabled) { SDL_GetMouseState(&mouse_position[0], &mouse_position[1]); + SDL_ShowCursor(SDL_DISABLE); + SDL_SetRelativeMouseMode(SDL_TRUE); } - - SDL_SetRelativeMouseMode((enabled) ? SDL_TRUE : SDL_FALSE); - - if (!enabled) + else { + SDL_SetRelativeMouseMode(SDL_FALSE); SDL_WarpMouseInWindow(sdl_window, mouse_position[0], mouse_position[1]); + if (cursor_visible) + SDL_ShowCursor(SDL_ENABLE); } } diff --git a/src/application.hpp b/src/application.hpp index eb4a545..b4356b0 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -205,6 +205,7 @@ private: render_callback_type render_callback; bool fullscreen; bool vsync; + bool cursor_visible; std::array display_dimensions; std::array window_dimensions; std::array viewport_dimensions; diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index 722b526..73561c5 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -838,9 +838,6 @@ void setup_systems(game_context* ctx) ctx->ui_system->set_scene(ctx->ui_scene); ctx->ui_system->set_viewport(viewport); ctx->ui_system->set_tool_menu_control(ctx->control_system->get_tool_menu_control()); - - - ctx->app->get_event_dispatcher()->subscribe(ctx->ui_system); } void setup_controls(game_context* ctx) @@ -999,10 +996,14 @@ void setup_controls(game_context* ctx) ctx->input_event_router->add_mapping(game_controller_axis_mapping(ctx->control_system->get_zoom_in_control(), nullptr, game_controller_axis::trigger_right, false)); event_dispatcher->subscribe(ctx->control_system); - event_dispatcher->subscribe(ctx->control_system); event_dispatcher->subscribe(ctx->camera_system); - event_dispatcher->subscribe(ctx->camera_system); event_dispatcher->subscribe(ctx->tool_system); + event_dispatcher->subscribe(ctx->ui_system); + + event_dispatcher->subscribe(ctx->control_system); + event_dispatcher->subscribe(ctx->camera_system); + event_dispatcher->subscribe(ctx->tool_system); + event_dispatcher->subscribe(ctx->ui_system); } void setup_cli(game_context* ctx) diff --git a/src/game/systems/camera-system.cpp b/src/game/systems/camera-system.cpp index 4f946c3..a62e8a3 100644 --- a/src/game/systems/camera-system.cpp +++ b/src/game/systems/camera-system.cpp @@ -45,8 +45,12 @@ camera_system::camera_system(entt::registry& registry): orbit_cam.set_target_elevation(math::radians(45.0f)); orbit_cam.set_target_zoom(0.0f); + orbit_cam.set_focal_point_oscillation(hz_to_rads(8.0f)); + orbit_cam.set_azimuth_oscillation(hz_to_rads(2.0f)); + orbit_cam.set_elevation_oscillation(hz_to_rads(2.0f)); + orbit_cam.set_zoom_oscillation(hz_to_rads(5.0f)); + orbit_cam.reset_springs(); - } void camera_system::update(double t, double dt) @@ -66,8 +70,11 @@ void camera_system::update(double t, double dt) if (subject_count > 1) target_focal_point /= static_cast(subject_count); + // Focus at ant's head height off the ground. target_focal_point.y += 0.2f; + // Check for collision with environment + //... orbit_cam.set_target_focal_point(target_focal_point); orbit_cam.update(static_cast(dt)); diff --git a/src/game/systems/tool-system.cpp b/src/game/systems/tool-system.cpp index 1794041..9dba5e0 100644 --- a/src/game/systems/tool-system.cpp +++ b/src/game/systems/tool-system.cpp @@ -145,3 +145,8 @@ void tool_system::handle_event(const mouse_moved_event& event) mouse_position[1] = event.y; } } + +void tool_system::handle_event(const window_resized_event& event) +{ + set_viewport({0.0f, 0.0f, static_cast(event.w), static_cast(event.h)}); +} diff --git a/src/game/systems/tool-system.hpp b/src/game/systems/tool-system.hpp index 2b384b8..6062d59 100644 --- a/src/game/systems/tool-system.hpp +++ b/src/game/systems/tool-system.hpp @@ -23,6 +23,7 @@ #include "entity-system.hpp" #include "event/event-handler.hpp" #include "event/input-events.hpp" +#include "event/window-events.hpp" #include "utility/fundamental-types.hpp" class camera; @@ -30,7 +31,8 @@ class orbit_cam; class tool_system: public entity_system, - public event_handler + public event_handler, + public event_handler { public: tool_system(entt::registry& registry); @@ -43,6 +45,7 @@ public: private: virtual void handle_event(const mouse_moved_event& event); + virtual void handle_event(const window_resized_event& event); const camera* camera; const orbit_cam* orbit_cam; @@ -53,4 +56,3 @@ private: }; #endif // ANTKEEPER_TOOL_SYSTEM_HPP - diff --git a/src/game/systems/ui-system.cpp b/src/game/systems/ui-system.cpp index f085741..45d8b75 100644 --- a/src/game/systems/ui-system.cpp +++ b/src/game/systems/ui-system.cpp @@ -153,6 +153,11 @@ void ui_system::handle_event(const mouse_moved_event& event) mouse_position[1] = event.y; } +void ui_system::handle_event(const window_resized_event& event) +{ + set_viewport({0.0f, 0.0f, static_cast(event.w), static_cast(event.h)}); +} + void ui_system::update_projection() { if (camera) diff --git a/src/game/systems/ui-system.hpp b/src/game/systems/ui-system.hpp index d70da15..3f9e4bd 100644 --- a/src/game/systems/ui-system.hpp +++ b/src/game/systems/ui-system.hpp @@ -22,6 +22,7 @@ #include "event/event-handler.hpp" #include "event/input-events.hpp" +#include "event/window-events.hpp" #include "scene/scene.hpp" #include "scene/camera.hpp" #include "scene/directional-light.hpp" @@ -36,7 +37,8 @@ class scene; class resource_manager; class ui_system: - public event_handler + public event_handler, + public event_handler { public: ui_system(::resource_manager* resource_manager); @@ -51,6 +53,7 @@ public: private: virtual void handle_event(const mouse_moved_event& event); + virtual void handle_event(const window_resized_event& event); void update_projection(); @@ -82,4 +85,3 @@ private: }; #endif // ANTKEEPER_UI_SYSTEM_HPP -