diff --git a/src/animation/spring.hpp b/src/animation/spring.hpp index bb6bb95..eb27649 100644 --- a/src/animation/spring.hpp +++ b/src/animation/spring.hpp @@ -20,6 +20,24 @@ #ifndef ANTKEEPER_SPRING_HPP #define ANTKEEPER_SPRING_HPP +/** + * Contains the variables required for numeric springing. + * + * @tparam T Value type. + * @tparam S Scalar type. + * + * @see spring() + */ +template +struct spring_constraint +{ + T x0; ///< Start value + T x1; ///< End value + T v; ///< Velocity + S z; ///< Damping ratio, which can be undamped (z = 0), underdamped (z < 1), critically damped (z = 1), or overdamped (z > 1). + S w; ///< Angular frequency of the oscillation, in radians per second (2pi = 1Hz). +}; + /** * Performs numeric, damped springing on a value and velocity. * @@ -36,6 +54,15 @@ template void spring(T& x0, T& v, const T& x1, S z, S w, S dt); +/** + * Solves a spring constraint using the spring() function. + * + * @param[in,out] constraint Spring constraint to be sovled. + * @param dt Delta time, in seconds. + */ +template +void solve_spring_constraint(spring_constraint& constraint, S dt); + template void spring(T& x0, T& v, const T& x1, S z, S w, S dt) { @@ -50,4 +77,10 @@ void spring(T& x0, T& v, const T& x1, S z, S w, S dt) v = det_v * inv_det; } +template +void solve_spring_constraint(spring_constraint& constraint, S dt) +{ + spring(constraint.x0, constraint.v, constraint.x1, constraint.z, constraint.w, dt); +} + #endif // ANTKEEPER_SPRING_HPP diff --git a/src/application.cpp b/src/application.cpp index 7f2498e..682b36d 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -417,6 +417,11 @@ void application::set_vsync(bool vsync) } } +void application::set_window_opacity(float opacity) +{ + SDL_SetWindowOpacity(sdl_window, opacity); +} + void application::update(double t, double dt) { translate_sdl_events(); diff --git a/src/application.hpp b/src/application.hpp index 672a459..eb4a545 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -159,6 +159,8 @@ public: */ void set_vsync(bool vsync); + void set_window_opacity(float opacity); + /// Returns the dimensions of the current display. const std::array& get_display_dimensions() const; diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index a8b2977..a411532 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -66,7 +66,7 @@ #include "game/systems/control-system.hpp" #include "game/systems/locomotion-system.hpp" #include "game/systems/nest-system.hpp" -#include "game/systems/placement-system.hpp" +#include "game/systems/snapping-system.hpp" #include "game/systems/render-system.hpp" #include "game/systems/samara-system.hpp" #include "game/systems/subterrain-system.hpp" @@ -747,6 +747,7 @@ void setup_entities(game_context* ctx) ctx->flashlight_entity = ctx->ecs_registry->create(); ctx->forceps_entity = ctx->ecs_registry->create(); ctx->lens_entity = ctx->ecs_registry->create(); + ctx->focal_point_entity = ctx->ecs_registry->create(); } void setup_systems(game_context* ctx) @@ -792,8 +793,8 @@ void setup_systems(game_context* ctx) // Setup samara system ctx->samara_system = new samara_system(*ctx->ecs_registry); - // Setup placement system - ctx->placement_system = new placement_system(*ctx->ecs_registry); + // Setup snapping system + ctx->snapping_system = new snapping_system(*ctx->ecs_registry); // Setup behavior system ctx->behavior_system = new behavior_system(*ctx->ecs_registry); @@ -829,6 +830,8 @@ void setup_systems(game_context* ctx) ctx->control_system->get_adjust_camera_control()->set_activated_callback([ctx](){ ctx->app->set_relative_mouse_mode(true); ctx->tool_system->set_pick(false); }); ctx->control_system->get_adjust_camera_control()->set_deactivated_callback([ctx](){ ctx->app->set_relative_mouse_mode(false); ctx->tool_system->set_pick(true); }); ctx->control_system->set_flashlight(ctx->flashlight_entity); + ctx->control_system->set_camera_subject(ctx->focal_point_entity); + ctx->control_system->set_camera_system(ctx->camera_system); // Setup UI system ctx->ui_system = new ui_system(ctx->resource_manager); @@ -997,6 +1000,7 @@ 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); @@ -1032,10 +1036,10 @@ void setup_callbacks(game_context* ctx) ctx->timeline->advance(dt); - //ctx->control_system->update(t, dt); + ctx->control_system->update(t, dt); ctx->terrain_system->update(t, dt); ctx->vegetation_system->update(t, dt); - ctx->placement_system->update(t, dt); + ctx->snapping_system->update(t, dt); ctx->nest_system->update(t, dt); ctx->subterrain_system->update(t, dt); ctx->collision_system->update(t, dt); diff --git a/src/game/components/placement-component.hpp b/src/game/components/snap-component.hpp similarity index 81% rename from src/game/components/placement-component.hpp rename to src/game/components/snap-component.hpp index e694c79..aa57dbd 100644 --- a/src/game/components/placement-component.hpp +++ b/src/game/components/snap-component.hpp @@ -17,19 +17,22 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_ECS_PLACEMENT_COMPONENT_HPP -#define ANTKEEPER_ECS_PLACEMENT_COMPONENT_HPP +#ifndef ANTKEEPER_ECS_SNAP_COMPONENT_HPP +#define ANTKEEPER_ECS_SNAP_COMPONENT_HPP #include "geometry/ray.hpp" namespace ecs { -struct placement_component +struct snap_component { ::ray ray; + bool relative; + bool warp; + bool autoremove; }; } // namespace ecs -#endif // ANTKEEPER_ECS_PLACEMENT_COMPONENT_HPP +#endif // ANTKEEPER_ECS_SNAP_COMPONENT_HPP diff --git a/src/game/entity-commands.cpp b/src/game/entity-commands.cpp index 7c112f1..1448dac 100644 --- a/src/game/entity-commands.cpp +++ b/src/game/entity-commands.cpp @@ -26,6 +26,15 @@ namespace ec { using namespace ecs; +void translate(entt::registry& registry, entt::entity eid, const float3& translation) +{ + if (registry.has(eid)) + { + transform_component& transform = registry.get(eid); + transform.transform.translation += translation; + } +} + void move_to(entt::registry& registry, entt::entity eid, const float3& position) { if (registry.has(eid)) diff --git a/src/game/entity-commands.hpp b/src/game/entity-commands.hpp index 2faf99a..102fd95 100644 --- a/src/game/entity-commands.hpp +++ b/src/game/entity-commands.hpp @@ -26,6 +26,7 @@ namespace ec { +void translate(entt::registry& registry, entt::entity eid, const float3& translation); void move_to(entt::registry& registry, entt::entity eid, const float3& position); void warp_to(entt::registry& registry, entt::entity eid, const float3& position); void set_transform(entt::registry& registry, entt::entity eid, const math::transform& transform, bool warp = false); diff --git a/src/game/game-context.hpp b/src/game/game-context.hpp index 9a8ac91..c68eef0 100644 --- a/src/game/game-context.hpp +++ b/src/game/game-context.hpp @@ -54,7 +54,7 @@ class material_pass; class nest_system; class orbit_cam; class pheromone_matrix; -class placement_system; +class snapping_system; class point_light; class rasterizer; class render_system; @@ -204,6 +204,7 @@ struct game_context entt::entity flashlight_entity; entt::entity forceps_entity; entt::entity lens_entity; + entt::entity focal_point_entity; // Systems behavior_system* behavior_system; @@ -213,7 +214,7 @@ struct game_context control_system* control_system; locomotion_system* locomotion_system; nest_system* nest_system; - placement_system* placement_system; + snapping_system* snapping_system; render_system* render_system; samara_system* samara_system; subterrain_system* subterrain_system; diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 476277a..0f61725 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -26,11 +26,12 @@ #include "game/components/copy-transform-component.hpp" #include "game/components/copy-translation-component.hpp" #include "game/components/model-component.hpp" -#include "game/components/placement-component.hpp" +#include "game/components/snap-component.hpp" #include "game/components/samara-component.hpp" #include "game/components/terrain-component.hpp" #include "game/components/tool-component.hpp" #include "game/components/transform-component.hpp" +#include "game/components/camera-subject-component.hpp" #include "game/entity-commands.hpp" #include "game/game-context.hpp" #include "game/states/game-states.hpp" @@ -42,6 +43,7 @@ #include "resources/resource-manager.hpp" #include "scene/model-instance.hpp" #include "scene/scene.hpp" +#include "scene/camera.hpp" #include "game/systems/control-system.hpp" #include "game/systems/camera-system.hpp" #include "utility/fundamental-types.hpp" @@ -77,12 +79,15 @@ void play_state_enter(game_context* ctx) ec::assign_render_layers(ecs_registry, flashlight_light_cone, 2); - ecs::placement_component placement; + ecs::snap_component snap; + snap.warp = true; + snap.relative = false; + snap.autoremove = true; auto ant_hill_entity = ant_hill_archetype->create(ecs_registry); - placement.ray.origin = {0, 10000, 0}; - placement.ray.direction = {0, -1, 0}; - ecs_registry.assign(ant_hill_entity, placement); + snap.ray.origin = {0, 10000, 0}; + snap.ray.direction = {0, -1, 0}; + ecs_registry.assign(ant_hill_entity, snap); @@ -101,14 +106,14 @@ void play_state_enter(game_context* ctx) transform.transform.rotation = math::angle_axis(math::random(0.0f, math::two_pi), {0, 1, 0}); transform.transform.scale = float3{1, 1, 1} * math::random(0.75f, 1.25f); - placement.ray.origin = {x, 10000, z}; - ecs_registry.assign(pebble_entity, placement); + snap.ray.origin = {x, 10000, z}; + ecs_registry.assign(pebble_entity, snap); } auto maple_tree_entity = maple_tree_archetype->create(ecs_registry); - placement.ray.origin = {300, 10000, 200}; - placement.ray.direction = {0, -1, 0}; - ecs_registry.assign(maple_tree_entity, placement); + snap.ray.origin = {300, 10000, 200}; + snap.ray.direction = {0, -1, 0}; + ecs_registry.assign(maple_tree_entity, snap); auto nest_entity = nest_archetype->create(ecs_registry); @@ -151,8 +156,24 @@ void play_state_enter(game_context* ctx) auto grass_entity_2 = grass_archetype->create(ecs_registry); ecs_registry.get(grass_entity_2).transform.rotation = math::angle_axis(math::radians(120.0f), float3{0, 1, 0}); */ + + // Setup camera focal point + ecs::transform_component focal_point_transform; + focal_point_transform.transform = math::identity_transform; + focal_point_transform.warp = true; + ecs::camera_subject_component focal_point_subject; + ecs::snap_component 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; + + ecs_registry.assign_or_replace(ctx->focal_point_entity, focal_point_transform); + ecs_registry.assign_or_replace(ctx->focal_point_entity, focal_point_subject); + ecs_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->camera_system->set_camera(ctx->overworld_camera); ctx->camera_system->set_azimuth(0.0f); ctx->camera_system->set_elevation(math::radians(45.0f)); diff --git a/src/game/states/splash-state.cpp b/src/game/states/splash-state.cpp index c6b3c2f..3c8f481 100644 --- a/src/game/states/splash-state.cpp +++ b/src/game/states/splash-state.cpp @@ -34,6 +34,8 @@ void splash_state_enter(game_context* ctx) logger* logger = ctx->logger; logger->push_task("Entering splash state"); + //ctx->app->set_window_opacity(0.5f); + // Disable sky pass ctx->overworld_sky_pass->set_enabled(false); diff --git a/src/game/systems/camera-system.cpp b/src/game/systems/camera-system.cpp index 3518442..2daffa0 100644 --- a/src/game/systems/camera-system.cpp +++ b/src/game/systems/camera-system.cpp @@ -33,70 +33,81 @@ camera_system::camera_system(entt::registry& registry): camera(nullptr), viewport{0, 0, 0, 0}, mouse_position{0, 0} -{} +{ + // Init azimuth spring constraint + azimuth_spring.v = 0.0f; + azimuth_spring.z = 1.0f; + azimuth_spring.w = 2.0f * math::two_pi; + + // Init elevation spring constraint + elevation_spring.v = 0.0f; + elevation_spring.z = 1.0f; + elevation_spring.w = 2.0f * math::two_pi; + + // Init focal distance spring constraint + focal_distance_spring.v = 0.0f; + focal_distance_spring.z = 1.0f; + focal_distance_spring.w = 5.0f * math::two_pi; + + // Init fov spring constraint + fov_spring.v = 0.0f; + fov_spring.z = 1.0f; + fov_spring.w = 5.0f * math::two_pi; +} void camera_system::update(double t, double dt) { if (!camera) return; - // Determine focal point + // Determine target focal point int subject_count = 0; - float3 focal_point = {0, 0, 0}; + float3 target_focal_point = {0, 0, 0}; registry.view().each( [&](auto entity, auto& subject, auto& transform) { - focal_point += transform.transform.translation; + target_focal_point += transform.transform.translation; ++subject_count; }); if (subject_count > 1) - focal_point /= static_cast(subject_count); + target_focal_point /= static_cast(subject_count); - // Determine focal distance - float focal_distance = math::log_lerp(focal_distance_far, focal_distance_near, zoom_factor); - - // Determine view point - quaternion_type rotation = math::normalize(azimuth_rotation * elevation_rotation); - float3 view_point = focal_point + rotation * float3{0.0f, 0.0f, focal_distance}; - - // Update camera transform + // Get source transform transform_type source_transform = camera->get_transform(); - transform_type target_transform = math::identity_transform; - target_transform.translation = view_point; - target_transform.rotation = rotation; + // Solve azimuth spring + float2 xz_direction = math::normalize(math::swizzle<0, 2>(target_focal_point) - math::swizzle<0, 2>(source_transform.translation)); + azimuth_spring.x0 = math::wrap_radians(std::atan2(-xz_direction.y, xz_direction.x) - math::half_pi); + azimuth_spring.x1 = azimuth_spring.x0 + math::wrap_radians(azimuth_spring.x1 - azimuth_spring.x0); + solve_spring_constraint(azimuth_spring, dt); - float2 xz_direction = math::normalize(math::swizzle<0, 2>(focal_point) - math::swizzle<0, 2>(source_transform.translation)); - float source_azimuth = math::wrap_radians(std::atan2(-xz_direction.y, xz_direction.x) - math::half_pi); - float source_elevation = elevation; + // Sovle elevation spring + elevation_spring.x0 = elevation; + elevation_spring.x1 = elevation_spring.x0 + math::wrap_radians(elevation_spring.x1 - elevation_spring.x0); + solve_spring_constraint(elevation_spring, dt); - float smooth_factor = 0.1f; - float smooth_azimuth = math::lerp_angle(source_azimuth, azimuth, smooth_factor); - float smooth_elevation = math::lerp_angle(source_elevation, elevation, smooth_factor); + // Solve focal distance spring + focal_distance_spring.x0 = math::length(source_transform.translation - target_focal_point); + solve_spring_constraint(focal_distance_spring, dt); + // Solve FOV spring + fov_spring.x0 = camera->get_fov(); + solve_spring_constraint(fov_spring, dt); - smooth_azimuth = source_azimuth; - float shortest_angle = math::wrap_radians(azimuth - source_azimuth); - static float velocity = 0.0f; - spring(smooth_azimuth, velocity, smooth_azimuth + shortest_angle, 1.0f, 2.0f * math::two_pi, dt); - - quaternion_type smooth_azimuth_rotation = math::angle_axis(smooth_azimuth, float3{0.0f, 1.0f, 0.0f}); - quaternion_type smooth_elevation_rotation = math::angle_axis(smooth_elevation, float3{-1.0f, 0.0f, 0.0f}); + // Determine camera rotation + quaternion_type smooth_azimuth_rotation = math::angle_axis(azimuth_spring.x0, float3{0.0f, 1.0f, 0.0f}); + quaternion_type smooth_elevation_rotation = math::angle_axis(elevation_spring.x0, float3{-1.0f, 0.0f, 0.0f}); quaternion_type smooth_rotation = math::normalize(smooth_azimuth_rotation * smooth_elevation_rotation); - float3 smooth_view_point = focal_point + smooth_rotation * float3{0.0f, 0.0f, focal_distance}; + // Determine camera view point + float3 smooth_view_point = target_focal_point + smooth_rotation * float3{0.0f, 0.0f, focal_distance_spring.x0}; + // Update camera transform transform_type smooth_transform; smooth_transform.translation = smooth_view_point; - //smooth_transform.translation = math::lerp(source_transform.translation, target_transform.translation, smooth_factor); - //smooth_transform.rotation = math::slerp(source_transform.rotation, target_transform.rotation, smooth_factor); smooth_transform.rotation = smooth_rotation; - smooth_transform.scale = math::lerp(source_transform.scale, target_transform.scale, smooth_factor); + smooth_transform.scale = source_transform.scale; camera->set_transform(smooth_transform); - - - // Determine FOV - float fov = math::log_lerp(fov_far, fov_near, zoom_factor); // Determine aspect ratio float aspect_ratio = viewport[2] / viewport[3]; @@ -106,7 +117,7 @@ void camera_system::update(double t, double dt) float clip_far = math::log_lerp(far_clip_far, far_clip_near, zoom_factor); // Update camera projection - camera->set_perspective(fov, aspect_ratio, clip_near, clip_far); + camera->set_perspective(fov_spring.x0, aspect_ratio, clip_near, clip_far); } void camera_system::rotate(float angle) @@ -117,12 +128,11 @@ void camera_system::rotate(float angle) void camera_system::tilt(float angle) { set_elevation(elevation + angle); - } void camera_system::zoom(float factor) { - set_zoom(std::max(0.0f, std::min(1.0f, zoom_factor + factor))); + set_zoom(zoom_factor + factor); } void camera_system::set_camera(::camera* camera) @@ -139,29 +149,35 @@ void camera_system::set_azimuth(float angle) { azimuth = math::wrap_radians(angle); azimuth_rotation = math::angle_axis(azimuth, float3{0.0f, 1.0f, 0.0f}); + azimuth_spring.x1 = azimuth; } void camera_system::set_elevation(float angle) { elevation = math::wrap_radians(angle); elevation_rotation = math::angle_axis(elevation, float3{-1.0f, 0.0f, 0.0f}); + elevation_spring.x1 = elevation; } void camera_system::set_zoom(float factor) { - this->zoom_factor = factor; + this->zoom_factor = std::max(0.0f, std::min(1.0f, factor)); + update_focal_distance(); + update_fov(); } void camera_system::set_focal_distance(float distance_near, float distance_far) { focal_distance_near = distance_near; focal_distance_far = distance_far; + update_focal_distance(); } void camera_system::set_fov(float angle_near, float angle_far) { fov_near = angle_near; fov_far = angle_far; + update_fov(); } void camera_system::set_clip_near(float distance_near, float distance_far) @@ -186,3 +202,15 @@ void camera_system::handle_event(const window_resized_event& event) { set_viewport({0.0f, 0.0f, static_cast(event.w), static_cast(event.h)}); } + +void camera_system::update_focal_distance() +{ + focal_distance = math::log_lerp(focal_distance_far, focal_distance_near, zoom_factor); + focal_distance_spring.x1 = focal_distance; +} + +void camera_system::update_fov() +{ + fov = math::log_lerp(fov_far, fov_near, zoom_factor); + fov_spring.x1 = fov; +} diff --git a/src/game/systems/camera-system.hpp b/src/game/systems/camera-system.hpp index a467f0a..ee297cc 100644 --- a/src/game/systems/camera-system.hpp +++ b/src/game/systems/camera-system.hpp @@ -27,6 +27,7 @@ #include "utility/fundamental-types.hpp" #include "math/quaternion-type.hpp" #include "math/transform-type.hpp" +#include "animation/spring.hpp" class camera; class orbit_cam; @@ -56,18 +57,32 @@ public: void set_fov(float angle_near, float angle_far); void set_clip_near(float distance_near, float distance_far); void set_clip_far(float distance_near, float distance_far); + + const spring_constraint& get_azimuth_spring() const; private: virtual void handle_event(const mouse_moved_event& event); virtual void handle_event(const window_resized_event& event); + + void update_focal_distance(); + void update_fov(); camera* camera; float4 viewport; float2 mouse_position; + spring_constraint azimuth_spring; + spring_constraint elevation_spring; + spring_constraint focal_distance_spring; + spring_constraint fov_spring; + + float azimuth; float elevation; + float focal_distance; float zoom_factor; + float fov; + float focal_distance_near; float focal_distance_far; float fov_near; @@ -81,5 +96,10 @@ private: quaternion_type azimuth_rotation; }; +inline const spring_constraint& camera_system::get_azimuth_spring() const +{ + return azimuth_spring; +} + #endif // ANTKEEPER_CAMERA_SYSTEM_HPP diff --git a/src/game/systems/control-system.cpp b/src/game/systems/control-system.cpp index 21699cb..2c9ddcd 100644 --- a/src/game/systems/control-system.cpp +++ b/src/game/systems/control-system.cpp @@ -26,6 +26,7 @@ #include "nest.hpp" #include "math/math.hpp" #include "game/entity-commands.hpp" +#include "game/systems/camera-system.hpp" control_system::control_system(entt::registry& registry): entity_system(registry), @@ -58,7 +59,7 @@ control_system::control_system(entt::registry& registry): control->set_deadzone(0.15f); } - zoom_speed = 4.0f; //1 + zoom_speed = 5.0f; //1 min_elevation = math::radians(-85.0f); max_elevation = math::radians(85.0f); near_focal_distance = 2.0f; @@ -82,6 +83,74 @@ control_system::control_system(entt::registry& registry): flashlight_turns_f = 0.0f; } +void control_system::update(double t, double dt) +{ + // Zoom camera + if (zoom_in_control.is_active()) + camera_system->zoom(zoom_speed * dt); + if (zoom_out_control.is_active()) + camera_system->zoom(-zoom_speed * dt); + + // Move camera + float3 movement{0.0f, 0.0f, 0.0f}; + if (move_right_control.is_active()) + movement.x += move_right_control.get_current_value(); + if (move_left_control.is_active()) + movement.x -= move_left_control.get_current_value(); + if (move_forward_control.is_active()) + movement.z -= move_forward_control.get_current_value(); + if (move_back_control.is_active()) + movement.z += move_back_control.get_current_value(); + + if (math::length_squared(movement) != 0.0f) + { + float max_speed = 100.0f * dt; + float speed = std::min(max_speed, math::length(movement * max_speed)); + movement = math::normalize(movement) * speed; + + float azimuth = camera_system->get_azimuth_spring().x0; + math::quaternion azimuth_rotation = math::angle_axis(azimuth, float3{0.0f, 1.0f, 0.0f}); + movement = azimuth_rotation * movement; + + ec::translate(registry, camera_subject_eid, movement); + } + + // Turn flashlight + float2 viewport_center = {(viewport[0] + viewport[2]) * 0.5f, (viewport[1] + viewport[3]) * 0.5f}; + float2 mouse_direction = math::normalize(mouse_position - viewport_center); + old_mouse_angle = mouse_angle; + mouse_angle = std::atan2(-mouse_direction.y, mouse_direction.x); + + if (mouse_angle - old_mouse_angle != 0.0f) + { + if (mouse_angle - old_mouse_angle <= -math::pi) + flashlight_turns_i -= 1; + else if (mouse_angle - old_mouse_angle >= math::pi) + flashlight_turns_i += 1; + + flashlight_turns_f = (mouse_angle) / math::two_pi; + flashlight_turns = flashlight_turns_i - flashlight_turns_f; + + if (flashlight_eid != entt::null && nest) + { + math::transform flashlight_transform = math::identity_transform; + + float flashlight_depth = nest->get_shaft_depth(*nest->get_central_shaft(), flashlight_turns); + + flashlight_transform.translation = {0.0f, -flashlight_depth, 0.0f}; + flashlight_transform.rotation = math::angle_axis(-flashlight_turns * math::two_pi + math::half_pi, {0, 1, 0}); + + ec::set_transform(registry, flashlight_eid, flashlight_transform, false); + + if (underworld_camera) + { + underworld_camera->look_at({0, -flashlight_depth + 50.0f, 0}, {0, -flashlight_depth, 0}, {0, 0, -1}); + } + } + } +} + +/* void control_system::update(double t, double dt) { this->timestep = dt; @@ -205,52 +274,20 @@ void control_system::update(double t, double dt) } - // Turn flashlight - - - float2 viewport_center = {(viewport[0] + viewport[2]) * 0.5f, (viewport[1] + viewport[3]) * 0.5f}; - float2 mouse_direction = math::normalize(mouse_position - viewport_center); - old_mouse_angle = mouse_angle; - mouse_angle = std::atan2(-mouse_direction.y, mouse_direction.x); - - if (mouse_angle - old_mouse_angle != 0.0f) - { - - - if (mouse_angle - old_mouse_angle <= -math::pi) - flashlight_turns_i -= 1; - else if (mouse_angle - old_mouse_angle >= math::pi) - flashlight_turns_i += 1; - - flashlight_turns_f = (mouse_angle) / math::two_pi; - flashlight_turns = flashlight_turns_i - flashlight_turns_f; - - if (flashlight_eid != entt::null && nest) - { - math::transform flashlight_transform = math::identity_transform; - - float flashlight_depth = nest->get_shaft_depth(*nest->get_central_shaft(), flashlight_turns); - - flashlight_transform.translation = {0.0f, -flashlight_depth, 0.0f}; - flashlight_transform.rotation = math::angle_axis(-flashlight_turns * math::two_pi + math::half_pi, {0, 1, 0}); - - ec::set_transform(registry, flashlight_eid, flashlight_transform, false); - - if (underworld_camera) - { - underworld_camera->look_at({0, -flashlight_depth + 50.0f, 0}, {0, -flashlight_depth, 0}, {0, 0, -1}); - } - } - } - } +*/ void control_system::set_orbit_cam(::orbit_cam* orbit_cam) { this->orbit_cam = orbit_cam; } +void control_system::set_camera_system(::camera_system* camera_system) +{ + this->camera_system = camera_system; +} + void control_system::set_nest(::nest* nest) { this->nest = nest; @@ -266,6 +303,11 @@ void control_system::set_flashlight(entt::entity eid) flashlight_eid = eid; } +void control_system::set_camera_subject(entt::entity eid) +{ + camera_subject_eid = eid; +} + void control_system::set_viewport(const float4& viewport) { this->viewport = viewport; @@ -309,3 +351,7 @@ void control_system::handle_event(const mouse_moved_event& event) } } +void control_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/control-system.hpp b/src/game/systems/control-system.hpp index 05beffa..c2b617f 100644 --- a/src/game/systems/control-system.hpp +++ b/src/game/systems/control-system.hpp @@ -23,6 +23,7 @@ #include "game/systems/entity-system.hpp" #include "event/event-handler.hpp" #include "event/input-events.hpp" +#include "event/window-events.hpp" #include "input/control.hpp" #include "input/control-set.hpp" #include "scene/model-instance.hpp" @@ -31,10 +32,12 @@ class orbit_cam; class nest; class camera; +class camera_system; class control_system: public entity_system, - public event_handler + public event_handler, + public event_handler { public: control_system(entt::registry& registry); @@ -45,9 +48,11 @@ public: void set_invert_mouse_y(bool invert); void set_orbit_cam(orbit_cam* orbit_cam); + void set_camera_system(camera_system* camera_system); void set_nest(::nest* nest); void set_tool(model_instance* tool); void set_flashlight(entt::entity eid); + void set_camera_subject(entt::entity eid); void set_viewport(const float4& viewport); void set_underworld_camera(::camera* camera); @@ -71,6 +76,7 @@ public: private: virtual void handle_event(const mouse_moved_event& event); + virtual void handle_event(const window_resized_event& event); control_set control_set; control move_forward_control; @@ -106,12 +112,14 @@ private: float timestep; float zoom; orbit_cam* orbit_cam; + camera_system* camera_system; ::nest* nest; model_instance* tool; float2 mouse_position; float4 viewport; entt::entity flashlight_eid; + entt::entity camera_subject_eid; camera* underworld_camera; float mouse_angle; diff --git a/src/game/systems/placement-system.cpp b/src/game/systems/snapping-system.cpp similarity index 61% rename from src/game/systems/placement-system.cpp rename to src/game/systems/snapping-system.cpp index 26fe9ea..2ab78b5 100644 --- a/src/game/systems/placement-system.cpp +++ b/src/game/systems/snapping-system.cpp @@ -17,35 +17,41 @@ * along with Antkeeper source code. If not, see . */ -#include "placement-system.hpp" +#include "snapping-system.hpp" #include "game/components/collision-component.hpp" -#include "game/components/placement-component.hpp" +#include "game/components/snap-component.hpp" #include "game/components/transform-component.hpp" -#include "game/components/terrain-component.hpp" #include "utility/fundamental-types.hpp" using namespace ecs; -placement_system::placement_system(entt::registry& registry): +snapping_system::snapping_system(entt::registry& registry): entity_system(registry) {} -void placement_system::update(double t, double dt) +void snapping_system::update(double t, double dt) { - registry.view().each( - [&](auto entity, auto& transform, auto& placement) + registry.view().each( + [&](auto entity, auto& snap_transform, auto& snap) { bool intersection = false; float a = std::numeric_limits::infinity(); float3 pick; + + ray snap_ray = snap.ray; + if (snap.relative) + { + snap_ray.origin += snap_transform.transform.translation; + snap_ray.direction = snap_transform.transform.rotation * snap_ray.direction; + } registry.view().each( - [&](auto entity, auto& transform, auto& collision) + [&](auto entity, auto& collision_transform, auto& collision) { // Transform ray into local space of collision component - math::transform inverse_transform = math::inverse(transform.transform); - float3 origin = inverse_transform * placement.ray.origin; - float3 direction = math::normalize(math::conjugate(transform.transform.rotation) * placement.ray.direction); + math::transform inverse_transform = math::inverse(collision_transform.transform); + float3 origin = inverse_transform * snap_ray.origin; + float3 direction = math::normalize(math::conjugate(collision_transform.transform.rotation) * snap_ray.direction); ray transformed_ray = {origin, direction}; // Broad phase AABB test @@ -55,6 +61,7 @@ void placement_system::update(double t, double dt) return; } + // Narrow phase mesh test auto mesh_result = collision.mesh_accelerator.query_nearest(transformed_ray); if (mesh_result) { @@ -62,17 +69,20 @@ void placement_system::update(double t, double dt) if (mesh_result->t < a) { a = mesh_result->t; - pick = placement.ray.extrapolate(a); + pick = snap_ray.extrapolate(a); } } }); if (intersection) { - transform.transform.translation = pick; - transform.warp = true; - registry.remove(entity); + snap_transform.transform.translation = pick; + snap_transform.warp = snap.warp; + + if (snap.autoremove) + { + registry.remove(entity); + } } }); } - diff --git a/src/game/systems/placement-system.hpp b/src/game/systems/snapping-system.hpp similarity index 82% rename from src/game/systems/placement-system.hpp rename to src/game/systems/snapping-system.hpp index 7ec32c8..28e351c 100644 --- a/src/game/systems/placement-system.hpp +++ b/src/game/systems/snapping-system.hpp @@ -17,18 +17,18 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_PLACEMENT_SYSTEM_HPP -#define ANTKEEPER_PLACEMENT_SYSTEM_HPP +#ifndef ANTKEEPER_SNAPPING_SYSTEM_HPP +#define ANTKEEPER_SNAPPING_SYSTEM_HPP #include "entity-system.hpp" -class placement_system: +class snapping_system: public entity_system { public: - placement_system(entt::registry& registry); + snapping_system(entt::registry& registry); virtual void update(double t, double dt); }; -#endif // ANTKEEPER_PLACEMENT_SYSTEM_HPP +#endif // ANTKEEPER_SNAPPING_SYSTEM_HPP diff --git a/src/game/systems/vegetation-system.cpp b/src/game/systems/vegetation-system.cpp index 9e010ac..6fce8a9 100644 --- a/src/game/systems/vegetation-system.cpp +++ b/src/game/systems/vegetation-system.cpp @@ -169,7 +169,7 @@ void vegetation_system::on_terrain_construct(entt::registry& registry, entt::ent lod_group->update_tweens(); // Add LOD group to scene - //scene->add_object(lod_group); + scene->add_object(lod_group); } } }