From 8d0610649d873c8c6427337b7cb59ccf0dd035f8 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Tue, 21 Mar 2023 06:11:55 +0800 Subject: [PATCH] Improve subframe interpolation. Remove tweens from scene objects. Clean up scene object classes --- CMakeLists.txt | 1 - src/engine/animation/screen-transition.cpp | 1 - .../constraints/spring-constraint.cpp | 4 +- src/engine/physics/kinematics/rigid-body.cpp | 22 +- src/engine/physics/kinematics/rigid-body.hpp | 125 +++++- src/engine/render/context.hpp | 24 -- src/engine/render/passes/material-pass.cpp | 48 ++- src/engine/render/passes/shadow-map-pass.cpp | 20 +- src/engine/render/passes/sky-pass.cpp | 28 +- src/engine/render/renderer.cpp | 11 +- src/engine/render/stages/culling-stage.cpp | 7 +- src/engine/scene/ambient-light.hpp | 23 + src/engine/scene/billboard-type.hpp | 42 ++ src/engine/scene/billboard.cpp | 110 +++-- src/engine/scene/billboard.hpp | 80 ++-- src/engine/scene/camera.cpp | 162 ++----- src/engine/scene/camera.hpp | 396 ++++++++---------- src/engine/scene/collection.cpp | 25 +- src/engine/scene/collection.hpp | 19 +- src/engine/scene/directional-light.cpp | 40 +- src/engine/scene/directional-light.hpp | 69 +-- .../scene/light-type.hpp} | 28 +- src/engine/scene/light.cpp | 30 +- src/engine/scene/light.hpp | 88 +--- src/engine/scene/lod-group.cpp | 80 ---- src/engine/scene/lod-group.hpp | 131 ------ src/engine/scene/object.cpp | 27 +- src/engine/scene/object.hpp | 78 ++-- src/engine/scene/point-light.cpp | 14 - src/engine/scene/point-light.hpp | 39 +- src/engine/scene/scene.hpp | 15 +- src/engine/scene/spot-light.cpp | 39 +- src/engine/scene/spot-light.hpp | 84 ++-- src/engine/scene/static-mesh.cpp | 61 ++- src/engine/scene/static-mesh.hpp | 36 +- src/engine/scene/text.cpp | 158 +++---- src/engine/scene/text.hpp | 102 ++--- src/game/ant/ant-swarm.cpp | 3 +- src/game/commands/commands.cpp | 6 +- src/game/commands/commands.hpp | 2 +- src/game/components/scene-component.hpp | 4 +- src/game/components/transform-component.hpp | 2 - src/game/controls.cpp | 4 +- src/game/game.cpp | 40 +- src/game/game.hpp | 13 +- src/game/loaders/entity-archetype-loader.cpp | 3 +- src/game/menu.cpp | 28 +- src/game/menu.hpp | 1 - src/game/spawn.cpp | 4 +- src/game/states/collection-menu-state.cpp | 9 +- src/game/states/controls-menu-state.cpp | 1 - src/game/states/credits-state.cpp | 10 +- src/game/states/extras-menu-state.cpp | 1 - src/game/states/gamepad-config-menu-state.cpp | 3 - src/game/states/graphics-menu-state.cpp | 10 - .../states/keyboard-config-menu-state.cpp | 3 - src/game/states/language-menu-state.cpp | 2 - src/game/states/main-menu-state.cpp | 14 +- src/game/states/nest-selection-state.cpp | 250 ++++------- src/game/states/nest-selection-state.hpp | 4 - src/game/states/nuptial-flight-state.cpp | 22 +- src/game/states/options-menu-state.cpp | 1 - src/game/states/pause-menu-state.cpp | 1 - src/game/states/sound-menu-state.cpp | 7 - src/game/states/splash-state.cpp | 7 +- src/game/systems/astronomy-system.cpp | 8 +- src/game/systems/physics-system.cpp | 88 ++-- src/game/systems/physics-system.hpp | 5 +- src/game/systems/render-system.cpp | 32 +- src/game/systems/terrain-system.cpp | 1 - src/game/world.cpp | 18 +- 71 files changed, 1089 insertions(+), 1785 deletions(-) create mode 100644 src/engine/scene/billboard-type.hpp rename src/{game/components/camera-component.hpp => engine/scene/light-type.hpp} (69%) delete mode 100644 src/engine/scene/lod-group.cpp delete mode 100644 src/engine/scene/lod-group.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e1a79..21ca183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.25) - option(APPLICATION_NAME "Application name" "Antkeeper") option(APPLICATION_VERSION "Application version string" "0.0.0") option(APPLICATION_AUTHOR "Application author" "C. J. Howard") diff --git a/src/engine/animation/screen-transition.cpp b/src/engine/animation/screen-transition.cpp index dcc678c..f8d4697 100644 --- a/src/engine/animation/screen-transition.cpp +++ b/src/engine/animation/screen-transition.cpp @@ -107,7 +107,6 @@ void screen_transition::transition(float duration, bool reverse, ::animationset(initial_state); - //material.update_tweens(); // Reset and play transition animation animation.stop(); diff --git a/src/engine/physics/kinematics/constraints/spring-constraint.cpp b/src/engine/physics/kinematics/constraints/spring-constraint.cpp index 07329d5..e47be3e 100644 --- a/src/engine/physics/kinematics/constraints/spring-constraint.cpp +++ b/src/engine/physics/kinematics/constraints/spring-constraint.cpp @@ -33,8 +33,8 @@ void spring_constraint::solve(float dt) const math::vector radius_b = m_body_b->get_orientation() * m_point_b; // Get world-space spring attachment points - const math::vector point_a = m_body_a->get_center_of_mass() + radius_a; - const math::vector point_b = m_body_b->get_center_of_mass() + radius_b; + const math::vector point_a = m_body_a->get_position() + radius_a; + const math::vector point_b = m_body_b->get_position() + radius_b; // Calculate relative velocity between the attachment points const math::vector velocity = m_body_b->get_point_velocity(radius_b) - m_body_a->get_point_velocity(radius_a); diff --git a/src/engine/physics/kinematics/rigid-body.cpp b/src/engine/physics/kinematics/rigid-body.cpp index 85a6d09..57b9bf8 100644 --- a/src/engine/physics/kinematics/rigid-body.cpp +++ b/src/engine/physics/kinematics/rigid-body.cpp @@ -18,6 +18,7 @@ */ #include +#include #include namespace physics { @@ -43,12 +44,25 @@ void rigid_body::integrate_forces(float dt) noexcept void rigid_body::integrate_velocities(float dt) noexcept { - // Update center of mass - m_center_of_mass += m_linear_velocity * dt; + // Record previous state + m_previous_transform = m_current_transform; + + // Update position + m_current_transform.translation += m_linear_velocity * dt; // Update orientation - const math::quaternion spin = math::quaternion{0.0f, m_angular_velocity * 0.5f} * m_orientation; - m_orientation = math::normalize(m_orientation + spin * dt); + const math::quaternion spin = math::quaternion{0.0f, m_angular_velocity * 0.5f} * m_current_transform.rotation; + m_current_transform.rotation = math::normalize(m_current_transform.rotation + spin * dt); +} + +math::transform rigid_body::interpolate(float alpha) const +{ + return + { + math::lerp(m_previous_transform.translation, m_current_transform.translation, alpha), + math::nlerp(m_previous_transform.rotation, m_current_transform.rotation, alpha), + math::lerp(m_previous_transform.scale, m_current_transform.scale, alpha), + }; } } // namespace physics \ No newline at end of file diff --git a/src/engine/physics/kinematics/rigid-body.hpp b/src/engine/physics/kinematics/rigid-body.hpp index 2363b95..556066b 100644 --- a/src/engine/physics/kinematics/rigid-body.hpp +++ b/src/engine/physics/kinematics/rigid-body.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace physics { @@ -34,23 +35,73 @@ class rigid_body { public: /** - * Sets the center of mass of the rigid body. + * Sets the transformation representing the current state of the rigid body. * - * @param point World-space center of mass. + * @param transform Transformation representing the current state of the rigid body. */ - inline void set_center_of_mass(const math::vector& point) noexcept + inline void set_transform(const math::transform& transform) noexcept { - m_center_of_mass = point; + m_current_transform = transform; } /** - * Sets the world-space orientation of the rigid body. + * Sets the current position of the rigid body. * - * @param orientation World-space orientation. + * @param position Position of the rigid body. + */ + inline void set_position(const math::vector& position) noexcept + { + m_current_transform.translation = position; + } + + /** + * Sets the current orientation of the rigid body. + * + * @param orientation Orientation of the rigid body. */ inline void set_orientation(const math::quaternion& orientation) noexcept { - m_orientation = orientation; + m_current_transform.rotation = orientation; + } + + /** + * Sets the transformation representing the previous state of the rigid body. + * + * @param transform Transformation representing the previous state of the rigid body. + */ + inline void set_previous_transform(const math::transform& transform) noexcept + { + m_previous_transform = transform; + } + + /** + * Sets the previous position of the rigid body. + * + * @param position Position of the rigid body. + */ + inline void set_previous_position(const math::vector& position) noexcept + { + m_previous_transform.translation = position; + } + + /** + * Sets the previous orientation of the rigid body. + * + * @param orientation Orientation of the rigid body. + */ + inline void set_previous_orientation(const math::quaternion& orientation) noexcept + { + m_previous_transform.rotation = orientation; + } + + /** + * Sets the center of mass of the rigid body. + * + * @param point World-space center of mass. + */ + inline void set_center_of_mass(const math::vector& point) noexcept + { + m_center_of_mass = point; } /** @@ -149,16 +200,46 @@ public: m_angular_momentum = m_inertia * m_angular_velocity; } - /// Returns the world-space center of mass of the rigid body. - [[nodiscard]] inline const math::vector& get_center_of_mass() const noexcept + /// Returns the transformation representing the current state of the rigid body. + [[nodiscard]] inline const math::transform& get_transform() const noexcept { - return m_center_of_mass; + return m_current_transform; + } + + /// Returns the current position of the rigid body. + [[nodiscard]] inline const math::vector& get_position() const noexcept + { + return m_current_transform.translation; } - /// Returns the world-space orientation of the rigid body. + /// Returns the current orientation of the rigid body. [[nodiscard]] inline const math::quaternion& get_orientation() const noexcept { - return m_orientation; + return m_current_transform.rotation; + } + + /// Returns the transformation representing the previous state of the rigid body. + [[nodiscard]] inline const math::transform& get_previous_transform() const noexcept + { + return m_previous_transform; + } + + /// Returns the previous position of the rigid body. + [[nodiscard]] inline const math::vector& get_previous_position() const noexcept + { + return m_previous_transform.translation; + } + + /// Returns the previous orientation of the rigid body. + [[nodiscard]] inline const math::quaternion& get_previous_orientation() const noexcept + { + return m_previous_transform.rotation; + } + + /// Returns the center of mass of the rigid body. + [[nodiscard]] inline const math::vector& get_center_of_mass() const noexcept + { + return m_center_of_mass; } /// Returns the mass of the rigid body, in kg. @@ -365,12 +446,24 @@ public: integrate_velocities(dt); } + /** + * Returns a transformation representing a state of the rigid body between its current and previous states. + * + * @param alpha State interpolation factor. + * + * @return Interpolated transformation. + */ + [[nodiscard]] math::transform interpolate(float alpha) const; + private: - /// World-space center of mass. - math::vector m_center_of_mass{math::vector::zero()}; + /// Transformation representing the current state of the rigid body. + math::transform m_current_transform{math::transform::identity}; - /// World-space orientation. - math::quaternion m_orientation{math::quaternion::identity()}; + /// Transformation representing the previous state of the rigid body. + math::transform m_previous_transform{math::transform::identity}; + + /// Center of mass. + math::vector m_center_of_mass{math::vector::zero()}; /// Mass, in kg. float m_mass{1.0f}; diff --git a/src/engine/render/context.hpp b/src/engine/render/context.hpp index 580b98b..23d8a59 100644 --- a/src/engine/render/context.hpp +++ b/src/engine/render/context.hpp @@ -44,33 +44,9 @@ struct context /// Pointer to the camera. const scene::camera* camera; - /// Camera transform. - math::transform camera_transform; - - /// Camera forward vector - float3 camera_forward; - - /// Camera up vector. - float3 camera_up; - /// Camera culling volume. const geom::bounding_volume* camera_culling_volume; - /// Near clipping plane of the camera. - geom::plane clip_near; - - /// Camera view matrix. - float4x4 view; - - /// Camera projection matrix. - float4x4 projection; - - /// Camera view projection matrix. - float4x4 view_projection; - - /// Camera exposure normalization factor. - float exposure; - /// Collection of scene objects being rendered. const scene::collection* collection; diff --git a/src/engine/render/passes/material-pass.cpp b/src/engine/render/passes/material-pass.cpp index ac0ef29..832da7a 100644 --- a/src/engine/render/passes/material-pass.cpp +++ b/src/engine/render/passes/material-pass.cpp @@ -293,15 +293,15 @@ void material_pass::set_fallback_material(std::shared_ptr fall void material_pass::evaluate_camera(const render::context& ctx) { - view = &ctx.view; - projection = &ctx.projection; - view_projection = &ctx.view_projection; - camera_position = &ctx.camera_transform.translation; - camera_exposure = ctx.exposure; + view = &ctx.camera->get_view(); + projection = &ctx.camera->get_projection(); + view_projection = &ctx.camera->get_view_projection(); + camera_position = &ctx.camera->get_translation(); + camera_exposure = ctx.camera->get_exposure_normalization(); clip_depth = { - ctx.camera->get_clip_near_tween().interpolate(ctx.alpha), - ctx.camera->get_clip_far_tween().interpolate(ctx.alpha) + ctx.camera->get_clip_near(), + ctx.camera->get_clip_far() }; log_depth_coef = 2.0f / std::log2(clip_depth[1] + 1.0f); } @@ -324,8 +324,8 @@ void material_pass::evaluate_lighting(const render::context& ctx) continue; } - const scene::light* light = static_cast(object); - switch (light->get_light_type()) + const scene::light& light = static_cast(*object); + switch (light.get_light_type()) { // Add ambient light case scene::light_type::ambient: @@ -338,13 +338,17 @@ void material_pass::evaluate_lighting(const render::context& ctx) ambient_light_colors.resize(ambient_light_count); } - ambient_light_colors[index] = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; + + + ambient_light_colors[index] = static_cast(light).get_illuminance() * ctx.camera->get_exposure_normalization(); break; } // Add point light case scene::light_type::point: { + const scene::point_light& point_light = static_cast(light); + const std::size_t index = point_light_count; ++point_light_count; @@ -355,16 +359,16 @@ void material_pass::evaluate_lighting(const render::context& ctx) point_light_attenuations.resize(point_light_count); } - point_light_colors[index] = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; - point_light_positions[index] = light->get_transform_tween().interpolate(ctx.alpha).translation; - point_light_attenuations[index] = static_cast(light)->get_attenuation_tween().interpolate(ctx.alpha); + point_light_colors[index] = point_light.get_luminous_flux() * ctx.camera->get_exposure_normalization(); + point_light_positions[index] = point_light.get_translation(); + point_light_attenuations[index] = point_light.get_attenuation(); break; } // Add directional light case scene::light_type::directional: { - const scene::directional_light& directional_light = static_cast(*light); + const scene::directional_light& directional_light = static_cast(light); const std::size_t index = directional_light_count; @@ -375,8 +379,8 @@ void material_pass::evaluate_lighting(const render::context& ctx) directional_light_directions.resize(directional_light_count); } - directional_light_colors[index] = directional_light.get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; - directional_light_directions[index] = directional_light.get_direction_tween().interpolate(ctx.alpha); + directional_light_colors[index] = directional_light.get_illuminance() * ctx.camera->get_exposure_normalization(); + directional_light_directions[index] = directional_light.get_direction(); // Add directional shadow if (directional_light.is_shadow_caster() && directional_light.get_shadow_framebuffer()) @@ -403,7 +407,7 @@ void material_pass::evaluate_lighting(const render::context& ctx) // Add spot_light case scene::light_type::spot: { - const scene::spot_light& spot_light = static_cast(*light); + const scene::spot_light& spot_light = static_cast(light); const std::size_t index = spot_light_count; @@ -417,11 +421,11 @@ void material_pass::evaluate_lighting(const render::context& ctx) spot_light_cutoffs.resize(spot_light_count); } - spot_light_colors[index] = spot_light.get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure; - spot_light_positions[index] = spot_light.get_transform_tween().interpolate(ctx.alpha).translation; - spot_light_directions[index] = spot_light.get_direction_tween().interpolate(ctx.alpha); - spot_light_attenuations[index] = spot_light.get_attenuation_tween().interpolate(ctx.alpha); - spot_light_cutoffs[index] = spot_light.get_cosine_cutoff_tween().interpolate(ctx.alpha); + spot_light_colors[index] = spot_light.get_luminous_flux() * ctx.camera->get_exposure_normalization(); + spot_light_positions[index] = spot_light.get_translation(); + spot_light_directions[index] = spot_light.get_direction(); + spot_light_attenuations[index] = spot_light.get_attenuation(); + spot_light_cutoffs[index] = spot_light.get_cosine_cutoff(); break; } diff --git a/src/engine/render/passes/shadow-map-pass.cpp b/src/engine/render/passes/shadow-map-pass.cpp index 84bcb50..ab2c3d9 100644 --- a/src/engine/render/passes/shadow-map-pass.cpp +++ b/src/engine/render/passes/shadow-map-pass.cpp @@ -134,14 +134,8 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, render:: // Get camera const scene::camera& camera = *ctx.camera; - // Get tweened camera parameters - const float camera_fov = camera.get_fov_tween().interpolate(ctx.alpha); - const float camera_aspect_ratio = camera.get_aspect_ratio_tween().interpolate(ctx.alpha); - const float camera_clip_near = camera.get_clip_near_tween().interpolate(ctx.alpha); - const float camera_clip_far = camera.get_clip_far_tween().interpolate(ctx.alpha); - // Calculate distance to shadow cascade depth clipping planes - const float shadow_clip_far = math::lerp(camera_clip_near, camera_clip_far, light.get_shadow_cascade_coverage()); + const float shadow_clip_far = math::lerp(camera.get_clip_near(), camera.get_clip_far(), light.get_shadow_cascade_coverage()); const unsigned int cascade_count = light.get_shadow_cascade_count(); @@ -156,8 +150,8 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, render:: const float weight = static_cast(i + 1) / static_cast(cascade_count); // Calculate linear and logarithmic distribution distances - const float linear_distance = math::lerp(camera_clip_near, shadow_clip_far, weight); - const float log_distance = math::log_lerp(camera_clip_near, shadow_clip_far, weight); + const float linear_distance = math::lerp(camera.get_clip_near(), shadow_clip_far, weight); + const float log_distance = math::log_lerp(camera.get_clip_near(), shadow_clip_far, weight); // Interpolate between linear and logarithmic distribution distances cascade_distances[i] = math::lerp(linear_distance, log_distance, light.get_shadow_cascade_distribution()); @@ -180,7 +174,7 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, render:: } // Calculate a view-projection matrix from the directional light's transform - math::transform light_transform = light.get_transform_tween().interpolate(ctx.alpha); + const auto& light_transform = light.get_transform(); float3 forward = light_transform.rotation * config::global_forward; float3 up = light_transform.rotation * config::global_up; float4x4 light_view = math::look_at(light_transform.translation, light_transform.translation + forward, up); @@ -202,12 +196,12 @@ void shadow_map_pass::render_csm(const scene::directional_light& light, render:: rasterizer->set_viewport(viewport[0], viewport[1], viewport[2], viewport[3]); // Calculate projection matrix for view camera subfrustum - const float subfrustum_near = (i) ? cascade_distances[i - 1] : camera_clip_near; + const float subfrustum_near = (i) ? cascade_distances[i - 1] : camera.get_clip_near(); const float subfrustum_far = cascade_distances[i]; - float4x4 subfrustum_projection = math::perspective_half_z(camera_fov, camera_aspect_ratio, subfrustum_near, subfrustum_far); + float4x4 subfrustum_projection = math::perspective_half_z(camera.get_fov(), camera.get_aspect_ratio(), subfrustum_near, subfrustum_far); // Calculate view camera subfrustum - geom::view_frustum subfrustum(subfrustum_projection * ctx.view); + geom::view_frustum subfrustum(subfrustum_projection * camera.get_view()); // Create AABB containing the view camera subfrustum corners const std::array& subfrustum_corners = subfrustum.get_corners(); diff --git a/src/engine/render/passes/sky-pass.cpp b/src/engine/render/passes/sky-pass.cpp index cc1fa06..62ee24a 100644 --- a/src/engine/render/passes/sky-pass.cpp +++ b/src/engine/render/passes/sky-pass.cpp @@ -191,13 +191,11 @@ void sky_pass::render(render::context& ctx) // Construct matrices const scene::camera& camera = *ctx.camera; - float clip_near = camera.get_clip_near_tween().interpolate(ctx.alpha); - float clip_far = camera.get_clip_far_tween().interpolate(ctx.alpha); - float3 model_scale = float3{1.0f, 1.0f, 1.0f} * (clip_near + clip_far) * 0.5f; + float3 model_scale = float3{1.0f, 1.0f, 1.0f} * (camera.get_clip_near() + camera.get_clip_far()) * 0.5f; float4x4 model = math::scale(math::matrix4::identity(), model_scale); - float4x4 view = float4x4(float3x3(ctx.view)); + float4x4 view = float4x4(float3x3(camera.get_view())); float4x4 model_view = view * model; - const float4x4& projection = ctx.projection; + const float4x4& projection = camera.get_projection(); float4x4 view_projection = projection * view; float4x4 model_view_projection = projection * model_view; @@ -216,12 +214,12 @@ void sky_pass::render(render::context& ctx) float3 sun_direction = math::normalize(sun_position); // Interpolate and expose sun luminance and illuminance - float3 sun_illuminance = sun_illuminance_tween.interpolate(ctx.alpha) * ctx.exposure; - float3 sun_luminance = sun_luminance_tween.interpolate(ctx.alpha) * ctx.exposure; + float3 sun_illuminance = sun_illuminance_tween.interpolate(ctx.alpha) * camera_exposure; + float3 sun_luminance = sun_luminance_tween.interpolate(ctx.alpha) * camera_exposure; float3 moon_position = moon_position_tween.interpolate(ctx.alpha); float3 moon_direction = math::normalize(moon_position); - float3 moon_illuminance = moon_illuminance_tween.interpolate(ctx.alpha) * ctx.exposure; + float3 moon_illuminance = moon_illuminance_tween.interpolate(ctx.alpha) * camera_exposure; float moon_angular_radius = moon_angular_radius_tween.interpolate(ctx.alpha) * magnification; float sun_y = color::aces::ap1.luminance(sun_transmitted_illuminance); @@ -234,7 +232,7 @@ void sky_pass::render(render::context& ctx) sun_luminance *= 0.0f; } - camera_exposure = ctx.exposure; + camera_exposure = camera.get_exposure_normalization(); // Render sky illuminance LUT for (const auto& command: sky_lut_command_buffer) @@ -286,7 +284,7 @@ void sky_pass::render(render::context& ctx) // Draw stars if (star_shader_program) { - float star_distance = (clip_near + clip_far) * 0.5f; + float star_distance = (camera.get_clip_near() + camera.get_clip_far()) * 0.5f; model = float4x4(float3x3(icrf_to_eus.r)); model = math::scale(model, {star_distance, star_distance, star_distance}); @@ -301,7 +299,7 @@ void sky_pass::render(render::context& ctx) if (star_distance_var) star_distance_var->update(star_distance); if (star_exposure_var) - star_exposure_var->update(ctx.exposure); + star_exposure_var->update(camera_exposure); //star_material->update(ctx.alpha); @@ -312,7 +310,7 @@ void sky_pass::render(render::context& ctx) //if (moon_position.y() >= -moon_angular_radius) if (moon_shader_program) { - float moon_distance = (clip_near + clip_far) * 0.5f; + float moon_distance = (camera.get_clip_near() + camera.get_clip_far()) * 0.5f; float moon_radius = moon_angular_radius * moon_distance; math::transform moon_transform; @@ -331,15 +329,15 @@ void sky_pass::render(render::context& ctx) if (moon_normal_model_var) moon_normal_model_var->update(normal_model); if (moon_camera_position_var) - moon_camera_position_var->update(ctx.camera_transform.translation); + moon_camera_position_var->update(camera.get_translation()); if (moon_sunlight_direction_var) moon_sunlight_direction_var->update(math::normalize(moon_sunlight_direction_tween.interpolate(ctx.alpha))); if (moon_sunlight_illuminance_var) - moon_sunlight_illuminance_var->update(moon_sunlight_illuminance_tween.interpolate(ctx.alpha) * ctx.exposure); + moon_sunlight_illuminance_var->update(moon_sunlight_illuminance_tween.interpolate(ctx.alpha) * camera_exposure); if (moon_planetlight_direction_var) moon_planetlight_direction_var->update(math::normalize(moon_planetlight_direction_tween.interpolate(ctx.alpha))); if (moon_planetlight_illuminance_var) - moon_planetlight_illuminance_var->update(moon_planetlight_illuminance_tween.interpolate(ctx.alpha) * ctx.exposure); + moon_planetlight_illuminance_var->update(moon_planetlight_illuminance_tween.interpolate(ctx.alpha) * camera_exposure); //moon_material->update(ctx.alpha); rasterizer->draw_arrays(*moon_model_vao, moon_model_drawing_mode, moon_model_start_index, moon_model_index_count); diff --git a/src/engine/render/renderer.cpp b/src/engine/render/renderer.cpp index c41bca1..1743b13 100644 --- a/src/engine/render/renderer.cpp +++ b/src/engine/render/renderer.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -73,16 +72,8 @@ void renderer::render(float t, float dt, float alpha, const scene::collection& c continue; } - // Update render context with camera-specific parameters + // Update render context camera ctx.camera = &camera; - ctx.camera_transform = camera.get_transform_tween().interpolate(alpha); - ctx.camera_forward = ctx.camera_transform.rotation * config::global_forward; - ctx.camera_up = ctx.camera_transform.rotation * config::global_up; - ctx.clip_near = camera.get_view_frustum().get_near(); ///< @TODO: tween this - ctx.view = camera.get_view_tween().interpolate(alpha); - ctx.projection = camera.get_projection_tween().interpolate(alpha); - ctx.view_projection = ctx.projection * ctx.view; - ctx.exposure = std::exp2(-camera.get_exposure_tween().interpolate(alpha)); // Clear render queues ctx.objects.clear(); diff --git a/src/engine/render/stages/culling-stage.cpp b/src/engine/render/stages/culling-stage.cpp index 3b62e7f..b118444 100644 --- a/src/engine/render/stages/culling-stage.cpp +++ b/src/engine/render/stages/culling-stage.cpp @@ -35,8 +35,9 @@ void culling_stage::execute(render::context& ctx) ctx.camera_culling_volume = ctx.camera->get_culling_mask(); if (!ctx.camera_culling_volume) { - ctx.camera_culling_volume = &ctx.camera->get_world_bounds(); + ctx.camera_culling_volume = &ctx.camera->get_view_frustum().get_bounds(); } + const auto& culling_volume = *ctx.camera_culling_volume; // Construct mutex to guard set of visible objects std::mutex mutex; @@ -63,11 +64,11 @@ void culling_stage::execute(render::context& ctx) const geom::bounding_volume* object_culling_volume = object->get_culling_mask(); if (!object_culling_volume) { - object_culling_volume = &object->get_world_bounds(); + object_culling_volume = &object->get_bounds(); } // Cull object if it's outside of the camera culling volume - if (!ctx.camera_culling_volume->intersects(*object_culling_volume)) + if (!culling_volume.intersects(*object_culling_volume)) { return; } diff --git a/src/engine/scene/ambient-light.hpp b/src/engine/scene/ambient-light.hpp index a0f721f..b196475 100644 --- a/src/engine/scene/ambient-light.hpp +++ b/src/engine/scene/ambient-light.hpp @@ -21,9 +21,13 @@ #define ANTKEEPER_SCENE_AMBIENT_LIGHT_HPP #include +#include namespace scene { +/** + * Omnidirectional source of illuminance. + */ class ambient_light: public light { public: @@ -31,6 +35,25 @@ public: { return light_type::ambient; } + + /** + * Sets the illuminance of the ambient light. + * + * @param illuminance Illuminance, in *lx*. + */ + inline void set_illuminance(const math::vector& illuminance) noexcept + { + m_illuminance = illuminance; + } + + /// Returns the illuminance of the ambient light, in *lx*. + [[nodiscard]] inline const math::vector& get_illuminance() const noexcept + { + return m_illuminance; + } + +private: + math::vector m_illuminance{0.0f, 0.0f, 0.0f}; }; } // namespace scene diff --git a/src/engine/scene/billboard-type.hpp b/src/engine/scene/billboard-type.hpp new file mode 100644 index 0000000..cc7a624 --- /dev/null +++ b/src/engine/scene/billboard-type.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 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 . + */ + +#ifndef ANTKEEPER_SCENE_BILLBOARD_TYPE_HPP +#define ANTKEEPER_SCENE_BILLBOARD_TYPE_HPP + +#include + +namespace scene { + +/// Billboard types. +enum class billboard_type: std::uint8_t +{ + /// Billboard is unaligned. + flat, + + /// Billboard aligns to face camera. + spherical, + + /// Billboard rotates about an alignment axis to face camera. + cylindrical +}; + +} // namespace scene + +#endif // ANTKEEPER_SCENE_BILLBOARD_TYPE_HPP diff --git a/src/engine/scene/billboard.cpp b/src/engine/scene/billboard.cpp index 48b435b..828472f 100644 --- a/src/engine/scene/billboard.cpp +++ b/src/engine/scene/billboard.cpp @@ -21,15 +21,11 @@ #include #include #include +#include namespace scene { -const typename billboard::aabb_type billboard::local_bounds = {{-1, -1, -1}, {1, 1, 1}}; - -billboard::billboard(): - world_bounds(local_bounds), - type(billboard_type::flat), - alignment_axis(config::global_up) +billboard::billboard() { const float vertex_data[] = { @@ -45,13 +41,13 @@ billboard::billboard(): const std::size_t vertex_stride = sizeof(float) * vertex_size; const std::size_t vertex_count = 6; - vbo = std::make_unique(gl::buffer_usage::static_draw, sizeof(float) * vertex_size * vertex_count, std::as_bytes(std::span{vertex_data})); + m_vbo = std::make_unique(gl::buffer_usage::static_draw, sizeof(float) * vertex_size * vertex_count, std::as_bytes(std::span{vertex_data})); std::size_t attribute_offset = 0; // Define position vertex attribute gl::vertex_attribute position_attribute; - position_attribute.buffer = vbo.get(); + position_attribute.buffer = m_vbo.get(); position_attribute.offset = attribute_offset; position_attribute.stride = vertex_stride; position_attribute.type = gl::vertex_attribute_type::float_32; @@ -60,7 +56,7 @@ billboard::billboard(): // Define UV vertex attribute gl::vertex_attribute uv_attribute; - uv_attribute.buffer = vbo.get(); + uv_attribute.buffer = m_vbo.get(); uv_attribute.offset = attribute_offset; uv_attribute.stride = vertex_stride; uv_attribute.type = gl::vertex_attribute_type::float_32; @@ -69,7 +65,7 @@ billboard::billboard(): // Define barycentric vertex attribute gl::vertex_attribute barycentric_attribute; - barycentric_attribute.buffer = vbo.get(); + barycentric_attribute.buffer = m_vbo.get(); barycentric_attribute.offset = attribute_offset; barycentric_attribute.stride = vertex_stride; barycentric_attribute.type = gl::vertex_attribute_type::float_32; @@ -77,65 +73,87 @@ billboard::billboard(): //attribute_offset += barycentric_attribute.components * sizeof(float); // Bind vertex attributes to VAO - vao = std::make_unique(); - vao->bind(render::vertex_attribute::position, position_attribute); - vao->bind(render::vertex_attribute::uv, uv_attribute); - vao->bind(render::vertex_attribute::barycentric, barycentric_attribute); + m_vao = std::make_unique(); + m_vao->bind(render::vertex_attribute::position, position_attribute); + m_vao->bind(render::vertex_attribute::uv, uv_attribute); + m_vao->bind(render::vertex_attribute::barycentric, barycentric_attribute); // Init render operation - render_op.vertex_array = vao.get(); - render_op.drawing_mode = gl::drawing_mode::triangles; - render_op.start_index = 0; - render_op.index_count = 6; + m_render_op.vertex_array = m_vao.get(); + m_render_op.drawing_mode = gl::drawing_mode::triangles; + m_render_op.start_index = 0; + m_render_op.index_count = 6; + m_render_op.transform = float4x4::identity(); } void billboard::render(render::context& ctx) const { - auto transform = get_transform_tween().interpolate(ctx.alpha); - // Align billboard - if (type == scene::billboard_type::spherical) + switch (m_billboard_type) { - transform.rotation = math::normalize(math::look_rotation(ctx.camera_forward, ctx.camera_up) * transform.rotation); - } - else if (type == scene::billboard_type::cylindrical) - { - float3 look = math::normalize(geom::project_on_plane(transform.translation - ctx.camera_transform.translation, {0.0f, 0.0f, 0.0f}, alignment_axis)); - float3 right = math::normalize(math::cross(alignment_axis, look)); - look = math::cross(right, alignment_axis); - float3 up = math::cross(look, right); - transform.rotation = math::normalize(math::look_rotation(look, up) * transform.rotation); + case scene::billboard_type::spherical: + { + auto transform = get_transform(); + + transform.rotation = math::normalize(math::look_rotation(ctx.camera->get_forward(), ctx.camera->get_up()) * transform.rotation); + + m_render_op.transform = math::matrix_cast(transform); + + break; + } + + case scene::billboard_type::cylindrical: + { + auto transform = get_transform(); + + auto look = math::normalize(geom::project_on_plane(transform.translation - ctx.camera->get_translation(), {0.0f, 0.0f, 0.0f}, m_alignment_axis)); + const auto right = math::normalize(math::cross(m_alignment_axis, look)); + look = math::cross(right, m_alignment_axis); + const auto up = math::cross(look, right); + transform.rotation = math::normalize(math::look_rotation(look, up) * transform.rotation); + + m_render_op.transform = math::matrix_cast(transform); + + break; + } + + case scene::billboard_type::flat: + break; + + default: + break; } - render_op.transform = math::matrix_cast(transform); - render_op.depth = ctx.clip_near.signed_distance(transform.translation); + m_render_op.depth = ctx.camera->get_view_frustum().get_near().signed_distance(get_translation()); - ctx.operations.emplace_back(&render_op); + ctx.operations.emplace_back(&m_render_op); } void billboard::set_material(std::shared_ptr material) { - render_op.material = material; + m_render_op.material = material; } void billboard::set_billboard_type(billboard_type type) { - this->type = type; -} - -void billboard::set_alignment_axis(const float3& axis) -{ - this->alignment_axis = axis; + m_billboard_type = type; + + if (m_billboard_type == scene::billboard_type::flat) + { + m_render_op.transform = math::matrix_cast(get_transform()); + } } void billboard::transformed() { - world_bounds = aabb_type::transform(local_bounds, get_transform()); -} - -void billboard::update_tweens() -{ - object_base::update_tweens(); + static const aabb_type untransformed_bounds{{-1, -1, -1}, {1, 1, 1}}; + + m_bounds = aabb_type::transform(untransformed_bounds, get_transform()); + + if (m_billboard_type == scene::billboard_type::flat) + { + m_render_op.transform = math::matrix_cast(get_transform()); + } } } // namespace scene diff --git a/src/engine/scene/billboard.hpp b/src/engine/scene/billboard.hpp index 0fb7608..d394305 100644 --- a/src/engine/scene/billboard.hpp +++ b/src/engine/scene/billboard.hpp @@ -22,88 +22,82 @@ #include #include -#include +#include #include #include #include #include -#include +#include #include namespace scene { -/// Enumerates billboard types. -enum class billboard_type: std::uint8_t -{ - /// No alignment - flat, - - /// Aligns to face camera - spherical, - - /// Rotates about an alignment axis to face camera - cylindrical -}; - /** - * A 2D unit quad with one material. + * 2D unit quad with a single material. */ class billboard: public object { public: - typedef geom::aabb aabb_type; + using aabb_type = geom::aabb; + /// Constructs a billboard. billboard(); void render(render::context& ctx) const override; - + + /** + * Sets the billboard material. + * + * @param material Billboard material. + */ void set_material(std::shared_ptr material); - /// Sets the billboard alignment mode. + /** + * Sets the billboard type. + * + * @param type Billboard type. + */ void set_billboard_type(billboard_type type); - /// Sets the axis around which the billboard will be rotated when the alignment is set to billboard_alignment::cylindrical. - void set_alignment_axis(const float3& axis); - - [[nodiscard]] inline virtual const bounding_volume_type& get_local_bounds() const noexcept + /** + * Sets alignment axis for cylindrical billboards. + * + * @param axis Cylindral billboard aligmment axis. + */ + inline void set_alignment_axis(const math::vector& axis) noexcept { - return local_bounds; + m_alignment_axis = axis; } - [[nodiscard]] inline virtual const bounding_volume_type& get_world_bounds() const noexcept + [[nodiscard]] inline const bounding_volume_type& get_bounds() const noexcept override { - return world_bounds; + return m_bounds; } - + [[nodiscard]] inline std::shared_ptr get_material() const noexcept { - return render_op.material; + return m_render_op.material; } [[nodiscard]] inline billboard_type get_billboard_type() const noexcept { - return type; + return m_billboard_type; } - [[nodiscard]] inline const float3& get_alignment_axis() const noexcept + [[nodiscard]] inline const math::vector& get_alignment_axis() const noexcept { - return alignment_axis; + return m_alignment_axis; } - - virtual void update_tweens(); private: - static const aabb_type local_bounds; - - virtual void transformed(); - - std::unique_ptr vbo; - std::unique_ptr vao; + void transformed() override; - mutable render::operation render_op; - aabb_type world_bounds; - billboard_type type; - float3 alignment_axis; + std::unique_ptr m_vbo; + std::unique_ptr m_vao; + mutable render::operation m_render_op; + aabb_type m_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}; + billboard_type m_billboard_type{billboard_type::flat}; + math::vector m_alignment_axis{0.0f, 1.0f, 0.0f}; }; } // namespace scene diff --git a/src/engine/scene/camera.cpp b/src/engine/scene/camera.cpp index 1768243..29d2be7 100644 --- a/src/engine/scene/camera.cpp +++ b/src/engine/scene/camera.cpp @@ -18,70 +18,14 @@ */ #include -#include -#include -#include #include #include namespace scene { -static float4x4 interpolate_view(const camera* camera, const float4x4& x, const float4x4& y, float a) -{ - math::transform transform = camera->get_transform_tween().interpolate(a); - float3 forward = transform.rotation * config::global_forward; - float3 up = transform.rotation * config::global_up; - return math::look_at(transform.translation, transform.translation + forward, up); -} - -static float4x4 interpolate_projection(const camera* camera, const float4x4& x, const float4x4& y, float a) -{ - if (camera->is_orthographic()) - { - return math::ortho( - camera->get_clip_left_tween().interpolate(a), - camera->get_clip_right_tween().interpolate(a), - camera->get_clip_bottom_tween().interpolate(a), - camera->get_clip_top_tween().interpolate(a), - camera->get_clip_far_tween().interpolate(a), - camera->get_clip_near_tween().interpolate(a)); - } - else - { - return math::perspective( - camera->get_fov_tween().interpolate(a), - camera->get_aspect_ratio_tween().interpolate(a), - camera->get_clip_far_tween().interpolate(a), - camera->get_clip_near_tween().interpolate(a)); - } -} - -static float4x4 interpolate_view_projection(const camera* camera, const float4x4& x, const float4x4& y, float a) -{ - return camera->get_projection_tween().interpolate(a) * camera->get_view_tween().interpolate(a); -} - -camera::camera(): - compositor(nullptr), - composite_index(0), - orthographic(true), - clip_left(-1.0f, math::lerp), - clip_right(1.0f, math::lerp), - clip_bottom(-1.0f, math::lerp), - clip_top(1.0f, math::lerp), - clip_near(-1.0f, math::lerp), - clip_far(1.0f, math::lerp), - fov(math::half_pi, math::lerp), - aspect_ratio(1.0f, math::lerp), - view(math::matrix4::identity(), std::bind(&interpolate_view, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), - projection(math::matrix4::identity(), std::bind(&interpolate_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), - view_projection(math::matrix4::identity(), std::bind(&interpolate_view_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), - exposure(0.0f, math::lerp) -{} - geom::primitive::ray camera::pick(const float2& ndc) const { - const float4x4 inverse_view_projection = math::inverse(view_projection[1]); + const float4x4 inverse_view_projection = math::inverse(m_view_projection); const float4 near = inverse_view_projection * float4{ndc[0], ndc[1], 1.0f, 1.0f}; const float4 far = inverse_view_projection * float4{ndc[0], ndc[1], 0.0f, 1.0f}; @@ -94,7 +38,7 @@ geom::primitive::ray camera::pick(const float2& ndc) const float3 camera::project(const float3& object, const float4& viewport) const { - float4 result = view_projection[1] * float4{object[0], object[1], object[2], 1.0f}; + float4 result = m_view_projection * float4{object[0], object[1], object[2], 1.0f}; result[0] = (result[0] / result[3]) * 0.5f + 0.5f; result[1] = (result[1] / result[3]) * 0.5f + 0.5f; result[2] = (result[2] / result[3]) * 0.5f + 0.5f; @@ -115,96 +59,78 @@ float3 camera::unproject(const float3& window, const float4& viewport) const result[2] = 1.0f - window[2]; // z: [1, 0] result[3] = 1.0f; - result = math::inverse(view_projection[1]) * result; + result = math::inverse(m_view_projection) * result; return math::vector(result) * (1.0f / result[3]); } void camera::set_perspective(float fov, float aspect_ratio, float clip_near, float clip_far) { - orthographic = false; - - this->fov[1] = fov; - this->aspect_ratio[1] = aspect_ratio; - this->clip_near[1] = clip_near; - this->clip_far[1] = clip_far; - - projection[1] = math::perspective_half_z(fov, aspect_ratio, clip_far, clip_near); + m_orthographic = false; + + // Update perspective projection parameters + m_fov = fov; + m_aspect_ratio = aspect_ratio; + m_clip_near = clip_near; + m_clip_far = clip_far; + + // Recalculate projection matrix + m_projection = math::perspective_half_z(m_fov, m_aspect_ratio, m_clip_far, m_clip_near); // Recalculate view-projection matrix - view_projection[1] = projection[1] * view[1]; + m_view_projection = m_projection * m_view; // Recalculate view frustum /// @TODO: this is a hack to fix the half z projection matrix view frustum - view_frustum.set_matrix(math::perspective(this->fov[1], this->aspect_ratio[1], this->clip_near[1], this->clip_far[1]) * view[1]); + m_view_frustum.set_matrix(math::perspective(m_fov, m_aspect_ratio, m_clip_near, m_clip_far) * m_view); } void camera::set_orthographic(float clip_left, float clip_right, float clip_bottom, float clip_top, float clip_near, float clip_far) { - orthographic = true; - - this->clip_left[1] = clip_left; - this->clip_right[1] = clip_right; - this->clip_bottom[1] = clip_bottom; - this->clip_top[1] = clip_top; - this->clip_near[1] = clip_near; - this->clip_far[1] = clip_far; - - projection[1] = math::ortho_half_z(clip_left, clip_right, clip_bottom, clip_top, clip_far, clip_near); + m_orthographic = true; + + // Update signed distances to clipping planes + m_clip_left = clip_left; + m_clip_right = clip_right; + m_clip_bottom = clip_bottom; + m_clip_top = clip_top; + m_clip_near = clip_near; + m_clip_far = clip_far; + + // Update projection matrix + m_projection = math::ortho_half_z(m_clip_left, m_clip_right, m_clip_bottom, m_clip_top, m_clip_far, m_clip_near); // Recalculate view-projection matrix - view_projection[1] = projection[1] * view[1]; + m_view_projection = m_projection * m_view; // Recalculate view frustum - view_frustum.set_matrix(view_projection[1]); -} - -void camera::set_exposure(float ev100) -{ - exposure[1] = ev100; -} - -void camera::set_compositor(render::compositor* compositor) -{ - this->compositor = compositor; + m_view_frustum.set_matrix(m_view_projection); } -void camera::set_composite_index(int index) +void camera::set_exposure_value(float ev100) { - composite_index = index; -} - -void camera::update_tweens() -{ - object_base::update_tweens(); - clip_left.update(); - clip_right.update(); - clip_bottom.update(); - clip_top.update(); - clip_near.update(); - clip_far.update(); - fov.update(); - aspect_ratio.update(); - view.update(); - projection.update(); - view_projection.update(); - exposure.update(); + m_exposure_value = ev100; + m_exposure_normalization = 1.0f / (std::exp2(m_exposure_value) * 1.2f); } void camera::transformed() { // Recalculate view and view-projection matrices - float3 forward = get_rotation() * config::global_forward; - float3 up = get_rotation() * config::global_up; - view[1] = math::look_at(get_translation(), get_translation() + forward, up); - view_projection[1] = projection[1] * view[1]; + m_forward = get_rotation() * math::vector{0.0f, 0.0f, -1.0f}; + m_up = get_rotation() * math::vector{0.0f, 1.0f, 0.0f}; + m_view = math::look_at(get_translation(), get_translation() + m_forward, m_up); + m_view_projection = m_projection * m_view; // Recalculate view frustum - /// @TODO: this is a hack to fix the half z projection matrix view frustum - if (orthographic) - view_frustum.set_matrix(view_projection[1]); + if (m_orthographic) + { + m_view_frustum.set_matrix(m_view_projection); + } else - view_frustum.set_matrix(math::perspective(fov[1], aspect_ratio[1], clip_near[1], clip_far[1]) * view[1]); + { + /// @TODO: this is a hack to fix the half z projection matrix view frustum + m_view_frustum.set_matrix(math::perspective(m_fov, m_aspect_ratio, m_clip_near, m_clip_far) * m_view); + } } } // namespace scene diff --git a/src/engine/scene/camera.hpp b/src/engine/scene/camera.hpp index fa129bb..0c8ca6a 100644 --- a/src/engine/scene/camera.hpp +++ b/src/engine/scene/camera.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace scene { @@ -34,9 +35,7 @@ namespace scene { class camera: public object { public: - typedef geom::view_frustum view_frustum_type; - - camera(); + using view_frustum_type = geom::view_frustum; /** * Constructs a picking ray from normalized device coordinates (NDC). @@ -45,7 +44,7 @@ public: * * @return Picking ray. */ - geom::primitive::ray pick(const float2& ndc) const; + [[nodiscard]] geom::primitive::ray pick(const float2& ndc) const; /** * Maps object coordinates to window coordinates. @@ -54,7 +53,7 @@ public: * @param viewport Vector containing the `x`, `y`, `w`, and `h` of the viewport. * @return Projected window coordinates. */ - float3 project(const float3& object, const float4& viewport) const; + [[nodiscard]] float3 project(const float3& object, const float4& viewport) const; /** * Maps window coordinates to object coordinates. @@ -63,7 +62,7 @@ public: * @param viewport Vector containing the `x`, `y`, `w`, and `h` of the viewport. * @return Unprojected object coordinates. */ - float3 unproject(const float3& window, const float4& viewport) const; + [[nodiscard]] float3 unproject(const float3& window, const float4& viewport) const; /** * Sets the camera's projection matrix using perspective projection. @@ -88,241 +87,188 @@ public: void set_orthographic(float clip_left, float clip_right, float clip_bottom, float clip_top, float clip_near, float clip_far); /** - * Sets the camera's ISO 100 exposure value directly + * Sets the camera's ISO 100 exposure value. * * @param ev100 ISO 100 exposure value. */ - void set_exposure(float ev100); - - void set_compositor(render::compositor* compositor); - void set_composite_index(int index); + void set_exposure_value(float ev100); + /** + * Sets the camera's compositor. + * + * @param compositor Compositor. + */ + inline void set_compositor(render::compositor* compositor) noexcept + { + m_compositor = compositor; + } + + /** + * Sets the composite index of the camera. + * + * @param index Composite index. + */ + inline void set_composite_index(int index) noexcept + { + m_composite_index = index; + } + + /** + * Returns the camera's compositor. + */ + /// @{ + [[nodiscard]] inline const render::compositor* get_compositor() const noexcept + { + return m_compositor; + } + [[nodiscard]] inline render::compositor* get_compositor() noexcept + { + return m_compositor; + } + /// @} + + /// Returns the composite index of the camera. + [[nodiscard]] inline int get_composite_index() const noexcept + { + return m_composite_index; + } + + [[nodiscard]] inline const bounding_volume_type& get_bounds() const noexcept override + { + return m_view_frustum.get_bounds(); + } + + /// Returns `true` if the camera uses an orthographic projection matrix, `false` otherwise. + [[nodiscard]] inline bool is_orthographic() const noexcept + { + return m_orthographic; + } + + /// Returns the signed distance to the camera's left clipping plane. + [[nodiscard]] inline float get_clip_left() const noexcept + { + return m_clip_left; + } + + /// Returns the signed distance to the camera's right clipping plane. + [[nodiscard]] inline float get_clip_right() const noexcept + { + return m_clip_right; + } + + /// Returns the signed distance to the camera's bottom clipping plane. + [[nodiscard]] inline float get_clip_bottom() const noexcept + { + return m_clip_bottom; + } + + /// Returns the signed distance to the camera's top clipping plane. + [[nodiscard]] inline float get_clip_top() const noexcept + { + return m_clip_top; + } + + /// Returns the signed distance to the camera's near clipping plane. + [[nodiscard]] inline float get_clip_near() const noexcept + { + return m_clip_near; + } + + /// Returns the signed distance to the camera's far clipping plane. + [[nodiscard]] inline float get_clip_far() const noexcept + { + return m_clip_far; + } + + /// Returns the camera's field of view, in radians. + [[nodiscard]] inline float get_fov() const noexcept + { + return m_fov; + } + + /// Returns the camera's aspect ratio. + [[nodiscard]] inline float get_aspect_ratio() const noexcept + { + return m_aspect_ratio; + } + + /// Returns the camera's ISO 100 exposure value. + [[nodiscard]] inline float get_exposure_value() const noexcept + { + return m_exposure_value; + } + + /// Returns the camera's exposure normalization factor. + [[nodiscard]] inline float get_exposure_normalization() const noexcept + { + return m_exposure_normalization; + } - virtual const bounding_volume_type& get_local_bounds() const; - virtual const bounding_volume_type& get_world_bounds() const; - - float is_orthographic() const; - float get_clip_left() const; - float get_clip_right() const; - float get_clip_bottom() const; - float get_clip_top() const; - float get_clip_near() const; - float get_clip_far() const; - float get_fov() const; - float get_aspect_ratio() const; - /// Returns the camera's view matrix. - const float4x4& get_view() const; - + [[nodiscard]] inline const float4x4& get_view() const noexcept + { + return m_view; + } + /// Returns the camera's projection matrix. - const float4x4& get_projection() const; - + [[nodiscard]] inline const float4x4& get_projection() const noexcept + { + return m_projection; + } + /// Returns the camera's view-projection matrix. - const float4x4& get_view_projection() const; + [[nodiscard]] inline const float4x4& get_view_projection() const noexcept + { + return m_view_projection; + } - /// Returns the camera's view frustum. - const view_frustum_type& get_view_frustum() const; + /// Returns the camera's forward vector. + [[nodiscard]] inline const math::vector& get_forward() const noexcept + { + return m_forward; + } - /// Returns the camera's ISO 100 exposure value. - float get_exposure() const; - - const render::compositor* get_compositor() const; - render::compositor* get_compositor(); - int get_composite_index() const; - - const tween& get_clip_left_tween() const; - const tween& get_clip_right_tween() const; - const tween& get_clip_bottom_tween() const; - const tween& get_clip_top_tween() const; - const tween& get_clip_near_tween() const; - const tween& get_clip_far_tween() const; - const tween& get_fov_tween() const; - const tween& get_aspect_ratio_tween() const; - const tween& get_view_tween() const; - const tween& get_projection_tween() const; - const tween& get_view_projection_tween() const; - const tween& get_exposure_tween() const; - - /// @copydoc object_base::update_tweens(); - virtual void update_tweens(); + /// Returns the camera's up vector. + [[nodiscard]] inline const math::vector& get_up() const noexcept + { + return m_up; + } + + /// Returns the camera's view frustum. + [[nodiscard]] inline const view_frustum_type& get_view_frustum() const noexcept + { + return m_view_frustum; + } private: virtual void transformed(); - render::compositor* compositor; - int composite_index; - bool orthographic; - tween clip_left; - tween clip_right; - tween clip_bottom; - tween clip_top; - tween clip_near; - tween clip_far; - tween fov; - tween aspect_ratio; - tween view; - tween projection; - tween view_projection; - tween exposure; - view_frustum_type view_frustum; + render::compositor* m_compositor{nullptr}; + int m_composite_index{0}; + + bool m_orthographic{true}; + + float m_clip_left{-1.0f}; + float m_clip_right{1.0f}; + float m_clip_bottom{-1.0f}; + float m_clip_top{1.0f}; + float m_clip_near{-1.0f}; + float m_clip_far{1.0f}; + float m_fov{math::half_pi}; + float m_aspect_ratio{1.0f}; + float m_exposure_value{0.0f}; + float m_exposure_normalization{1.0f / 1.2f}; + + float4x4 m_view{float4x4::identity()}; + float4x4 m_projection{float4x4::identity()}; + float4x4 m_view_projection{float4x4::identity()}; + + math::vector m_forward{0.0f, 0.0f, -1.0f}; + math::vector m_up{0.0f, 1.0f, 0.0f}; + + view_frustum_type m_view_frustum; }; -inline const typename object_base::bounding_volume_type& camera::get_local_bounds() const -{ - /// @TODO: return local bounds, not world bounds - return view_frustum.get_bounds(); -} - -inline const typename object_base::bounding_volume_type& camera::get_world_bounds() const -{ - return view_frustum.get_bounds(); -} - -inline float camera::is_orthographic() const -{ - return orthographic; -} - -inline float camera::get_clip_left() const -{ - return clip_left[1]; -} - -inline float camera::get_clip_right() const -{ - return clip_right[1]; -} - -inline float camera::get_clip_bottom() const -{ - return clip_bottom[1]; -} - -inline float camera::get_clip_top() const -{ - return clip_top[1]; -} - -inline float camera::get_clip_near() const -{ - return clip_near[1]; -} - -inline float camera::get_clip_far() const -{ - return clip_far[1]; -} - -inline float camera::get_fov() const -{ - return fov[1]; -} - -inline float camera::get_aspect_ratio() const -{ - return aspect_ratio[1]; -} - -inline const float4x4& camera::get_view() const -{ - return view[1]; -} - -inline const float4x4& camera::get_projection() const -{ - return projection[1]; -} - -inline const float4x4& camera::get_view_projection() const -{ - return view_projection[1]; -} - -inline const typename camera::view_frustum_type& camera::get_view_frustum() const -{ - return view_frustum; -} - -inline float camera::get_exposure() const -{ - return exposure[1]; -} - -inline const render::compositor* camera::get_compositor() const -{ - return compositor; -} - -inline render::compositor* camera::get_compositor() -{ - return compositor; -} - -inline int camera::get_composite_index() const -{ - return composite_index; -} - -inline const tween& camera::get_clip_left_tween() const -{ - return clip_left; -} - -inline const tween& camera::get_clip_right_tween() const -{ - return clip_right; -} - -inline const tween& camera::get_clip_bottom_tween() const -{ - return clip_bottom; -} - -inline const tween& camera::get_clip_top_tween() const -{ - return clip_top; -} - -inline const tween& camera::get_clip_near_tween() const -{ - return clip_near; -} - -inline const tween& camera::get_clip_far_tween() const -{ - return clip_far; -} - -inline const tween& camera::get_fov_tween() const -{ - return fov; -} - -inline const tween& camera::get_aspect_ratio_tween() const -{ - return aspect_ratio; -} - -inline const tween& camera::get_view_tween() const -{ - return view; -} - -inline const tween& camera::get_projection_tween() const -{ - return projection; -} - -inline const tween& camera::get_view_projection_tween() const -{ - return view_projection; -} - -inline const tween& camera::get_exposure_tween() const -{ - return exposure; -} - } // namespace scene #endif // ANTKEEPER_SCENE_CAMERA_HPP diff --git a/src/engine/scene/collection.cpp b/src/engine/scene/collection.cpp index 271d64e..21bf1ab 100644 --- a/src/engine/scene/collection.cpp +++ b/src/engine/scene/collection.cpp @@ -18,34 +18,25 @@ */ #include -#include namespace scene { -void collection::add_object(object_base* object) +void collection::add_object(object_base& object) { - objects.emplace_back(object); - object_map[object->get_object_type_id()].emplace_back(object); + m_objects.emplace_back(&object); + m_object_map[object.get_object_type_id()].emplace_back(&object); } -void collection::remove_object(object_base* object) +void collection::remove_object(const object_base& object) { - std::erase(objects, object); - std::erase(object_map[object->get_object_type_id()], object); + std::erase(m_objects, &object); + std::erase(m_object_map[object.get_object_type_id()], &object); } void collection::remove_objects() { - objects.clear(); - object_map.clear(); -} - -void collection::update_tweens() -{ - for (object_base* object: objects) - { - object->update_tweens(); - } + m_objects.clear(); + m_object_map.clear(); } } // namespace scene diff --git a/src/engine/scene/collection.hpp b/src/engine/scene/collection.hpp index 6d4794a..612b78f 100644 --- a/src/engine/scene/collection.hpp +++ b/src/engine/scene/collection.hpp @@ -20,13 +20,12 @@ #ifndef ANTKEEPER_SCENE_COLLECTION_HPP #define ANTKEEPER_SCENE_COLLECTION_HPP +#include #include #include namespace scene { -class object_base; - /** * Collection of scene objects. */ @@ -38,25 +37,22 @@ public: * * @param object Object to add. */ - void add_object(object_base* object); + void add_object(object_base& object); /** * Removes an object from the collection. * * @param object Object to remove. */ - void remove_object(object_base* object); + void remove_object(const object_base& object); /// Removes all objects from the collection. void remove_objects(); - /// Updates the tweens of all objects in the collection. - void update_tweens(); - /// Returns all objects in the collection. [[nodiscard]] inline const std::vector& get_objects() const noexcept { - return objects; + return m_objects; } /** @@ -68,13 +64,12 @@ public: */ [[nodiscard]] inline const std::vector& get_objects(std::size_t type_id) const { - return object_map[type_id]; + return m_object_map[type_id]; } private: - std::vector objects; - - mutable std::unordered_map> object_map; + std::vector m_objects; + mutable std::unordered_map> m_object_map; }; } // namespace scene diff --git a/src/engine/scene/directional-light.cpp b/src/engine/scene/directional-light.cpp index 20a75cf..1240f9b 100644 --- a/src/engine/scene/directional-light.cpp +++ b/src/engine/scene/directional-light.cpp @@ -18,67 +18,51 @@ */ #include -#include #include #include namespace scene { -static float3 interpolate_direction(const float3& x, const float3& y, float a) -{ - math::quaternion q0 = math::rotation(config::global_forward, x); - math::quaternion q1 = math::rotation(config::global_forward, y); - return math::normalize(math::slerp(q0, q1, a) * config::global_forward); -} - directional_light::directional_light(): - direction(config::global_forward, interpolate_direction) -{ - shadow_cascade_distances.resize(shadow_cascade_count); - shadow_cascade_matrices.resize(shadow_cascade_count); -} + m_shadow_cascade_distances(m_shadow_cascade_count), + m_shadow_cascade_matrices(m_shadow_cascade_count) +{} void directional_light::set_shadow_caster(bool caster) noexcept { - shadow_caster = caster; + m_shadow_caster = caster; } void directional_light::set_shadow_framebuffer(const gl::framebuffer* framebuffer) noexcept { - shadow_framebuffer = framebuffer; + m_shadow_framebuffer = framebuffer; } void directional_light::set_shadow_bias(float bias) noexcept { - shadow_bias = bias; + m_shadow_bias = bias; } void directional_light::set_shadow_cascade_count(unsigned int count) noexcept { - shadow_cascade_count = count; - shadow_cascade_distances.resize(shadow_cascade_count); - shadow_cascade_matrices.resize(shadow_cascade_count); + m_shadow_cascade_count = count; + m_shadow_cascade_distances.resize(m_shadow_cascade_count); + m_shadow_cascade_matrices.resize(m_shadow_cascade_count); } void directional_light::set_shadow_cascade_coverage(float factor) noexcept { - shadow_cascade_coverage = factor; + m_shadow_cascade_coverage = factor; } void directional_light::set_shadow_cascade_distribution(float weight) noexcept { - shadow_cascade_distribution = weight; -} - -void directional_light::update_tweens() -{ - light::update_tweens(); - direction.update(); + m_shadow_cascade_distribution = weight; } void directional_light::transformed() { - direction[1] = math::normalize(get_transform().rotation * config::global_forward); + m_direction = get_rotation() * math::vector{0.0f, 0.0f, -1.0f}; } } // namespace scene diff --git a/src/engine/scene/directional-light.hpp b/src/engine/scene/directional-light.hpp index 05636d8..f43bea8 100644 --- a/src/engine/scene/directional-light.hpp +++ b/src/engine/scene/directional-light.hpp @@ -41,20 +41,33 @@ public: { return light_type::directional; } - + /// Returns the normalized direction vector of the light. - [[nodiscard]] inline const float3& get_direction() const noexcept + [[nodiscard]] inline const math::vector& get_direction() const noexcept { - return direction[1]; + return m_direction; } - inline const tween& get_direction_tween() const noexcept + /// @name Light + /// @{ + + /** + * Sets the illuminance of the directional light. + * + * @param illuminance Illuminance, in *lx*. + */ + inline void set_illuminance(const math::vector& illuminance) noexcept { - return direction; + m_illuminance = illuminance; } - /// @copydoc object_base::update_tweens(); - void update_tweens() override; + /// Returns the illuminance of the directional light, in *lx*. + [[nodiscard]] inline const math::vector& get_illuminance() const noexcept + { + return m_illuminance; + } + + /// @} /// @name Shadow /// @{ @@ -104,48 +117,48 @@ public: /// Returns `true` if the light casts shadows, `false` otherwise. [[nodiscard]] inline bool is_shadow_caster() const noexcept { - return shadow_caster; + return m_shadow_caster; } /// Returns the shadow map framebuffer, of `nullptr` if no shadow map framebuffer is set. [[nodiscard]] inline const gl::framebuffer* get_shadow_framebuffer() const noexcept { - return shadow_framebuffer; + return m_shadow_framebuffer; } /// Returns the shadow bias factor. [[nodiscard]] inline float get_shadow_bias() const noexcept { - return shadow_bias; + return m_shadow_bias; } /// Returns the number of shadow cascades. [[nodiscard]] inline unsigned int get_shadow_cascade_count() const noexcept { - return shadow_cascade_count; + return m_shadow_cascade_count; } /// Returns the shadow cascade coverage factor. [[nodiscard]] inline float get_shadow_cascade_coverage() const noexcept { - return shadow_cascade_coverage; + return m_shadow_cascade_coverage; } /// Returns the shadow cascade distribution weight. [[nodiscard]] inline float get_shadow_cascade_distribution() const noexcept { - return shadow_cascade_distribution; + return m_shadow_cascade_distribution; } /// Returns the array of shadow cascade far clipping plane distances. /// @{ [[nodiscard]] inline const std::vector& get_shadow_cascade_distances() const noexcept { - return shadow_cascade_distances; + return m_shadow_cascade_distances; } [[nodiscard]] inline std::vector& get_shadow_cascade_distances() noexcept { - return shadow_cascade_distances; + return m_shadow_cascade_distances; } /// @} @@ -153,11 +166,11 @@ public: /// @{ [[nodiscard]] inline const std::vector& get_shadow_cascade_matrices() const noexcept { - return shadow_cascade_matrices; + return m_shadow_cascade_matrices; } [[nodiscard]] inline std::vector& get_shadow_cascade_matrices() noexcept { - return shadow_cascade_matrices; + return m_shadow_cascade_matrices; } /// @} @@ -165,17 +178,17 @@ public: private: void transformed() override; - - tween direction; - - bool shadow_caster{false}; - const gl::framebuffer* shadow_framebuffer{nullptr}; - float shadow_bias{0.005f}; - unsigned int shadow_cascade_count{4}; - float shadow_cascade_coverage{1.0f}; - float shadow_cascade_distribution{0.8f}; - mutable std::vector shadow_cascade_distances; - mutable std::vector shadow_cascade_matrices; + + math::vector m_illuminance{0.0f, 0.0f, 0.0f}; + math::vector m_direction{0.0f, 0.0f, -1.0f}; + bool m_shadow_caster{false}; + const gl::framebuffer* m_shadow_framebuffer{nullptr}; + float m_shadow_bias{0.005f}; + unsigned int m_shadow_cascade_count{4}; + float m_shadow_cascade_coverage{1.0f}; + float m_shadow_cascade_distribution{0.8f}; + mutable std::vector m_shadow_cascade_distances; + mutable std::vector m_shadow_cascade_matrices; }; } // namespace scene diff --git a/src/game/components/camera-component.hpp b/src/engine/scene/light-type.hpp similarity index 69% rename from src/game/components/camera-component.hpp rename to src/engine/scene/light-type.hpp index bd16633..439b483 100644 --- a/src/game/components/camera-component.hpp +++ b/src/engine/scene/light-type.hpp @@ -17,19 +17,29 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_GAME_CAMERA_COMPONENT_HPP -#define ANTKEEPER_GAME_CAMERA_COMPONENT_HPP +#ifndef ANTKEEPER_SCENE_LIGHT_TYPE_HPP +#define ANTKEEPER_SCENE_LIGHT_TYPE_HPP -#include +#include +namespace scene { -/// Camera scene object component. -struct camera_component +/// Light types. +enum class light_type: std::uint8_t { - /// Pointer to camera scene object - scene::camera* object; + /// Ambient light. + ambient, + + /// Directional light. + directional, + + /// Point light. + point, + + /// Spot light. + spot }; +} // namespace scene -#endif // ANTKEEPER_GAME_CAMERA_COMPONENT_HPP - +#endif // ANTKEEPER_SCENE_LIGHT_TYPE_HPP diff --git a/src/engine/scene/light.cpp b/src/engine/scene/light.cpp index e981ba0..0fab0fb 100644 --- a/src/engine/scene/light.cpp +++ b/src/engine/scene/light.cpp @@ -22,37 +22,9 @@ namespace scene { -light::light(): - local_bounds{{0.0f, 0.0f, 0.0f}, 0.0f}, - world_bounds{{0.0f, 0.0f, 0.0f}, 0.0f}, - color(float3{1.0f, 1.0f, 1.0f}, math::lerp), - intensity(1.0f, math::lerp), - scaled_color(float3{1.0f, 1.0f, 1.0f}, math::lerp) -{} - -void light::set_color(const float3& color) -{ - this->color[1] = color; - scaled_color[1] = color * intensity[1]; -} - -void light::set_intensity(float intensity) -{ - this->intensity[1] = intensity; - scaled_color[1] = color[1] * intensity; -} - -void light::update_tweens() -{ - object_base::update_tweens(); - color.update(); - intensity.update(); - scaled_color.update(); -} - void light::transformed() { - world_bounds = {get_translation(), 0.0f}; + m_bounds = {get_translation(), 0.0f}; } } // namespace scene diff --git a/src/engine/scene/light.hpp b/src/engine/scene/light.hpp index 23adfa3..fa8bffc 100644 --- a/src/engine/scene/light.hpp +++ b/src/engine/scene/light.hpp @@ -22,26 +22,10 @@ #include #include -#include +#include namespace scene { -/// Light object type enumerations. -enum class light_type -{ - /// Denotes an ambient light. - ambient, - - /// Denotes a directional light. - directional, - - /// Denotes a point light. - point, - - /// Denotes a spot light. - spot -}; - /** * Abstract base class for light objects. */ @@ -49,83 +33,19 @@ class light: public object { public: typedef geom::sphere sphere_type; - - /// Creates a light. - light(); /// Returns an enumeration denoting the light object type. [[nodiscard]] virtual light_type get_light_type() const noexcept = 0; - /** - * Sets the color of the light. - * - * @param color Scene-linear light color. - */ - void set_color(const float3& color); - - /** - * Sets the intensity of the light. - * - * @param intensity Light intensity. - */ - void set_intensity(float intensity); - - /// Returns the local-space bounding volume of the light. - inline const bounding_volume_type& get_local_bounds() const noexcept override - { - return local_bounds; - } - - /// Returns the world-space bounding volume of the light. - inline const bounding_volume_type& get_world_bounds() const noexcept override + inline const bounding_volume_type& get_bounds() const noexcept override { - return world_bounds; + return m_bounds; } - - /// Returns the light color. - [[nodiscard]] inline const float3& get_color() const noexcept - { - return color[1]; - } - - /// Returns the light intensity. - [[nodiscard]] inline float get_intensity() const noexcept - { - return intensity[1]; - } - - /// Returns the intensity-scaled light color. - [[nodiscard]] inline const float3& get_scaled_color() const noexcept - { - return scaled_color[1]; - } - - [[nodiscard]] inline const tween& get_color_tween() const noexcept - { - return color; - } - - [[nodiscard]] inline const tween& get_intensity_tween() const noexcept - { - return intensity; - } - - [[nodiscard]] inline const tween& get_scaled_color_tween() const noexcept - { - return scaled_color; - } - - /// @copydoc object_base::update_tweens(); - virtual void update_tweens(); private: virtual void transformed(); - tween color; - tween intensity; - tween scaled_color; - sphere_type local_bounds; - sphere_type world_bounds; + sphere_type m_bounds{{0.0f, 0.0f, 0.0f}, 0.0f}; }; } // namespace scene diff --git a/src/engine/scene/lod-group.cpp b/src/engine/scene/lod-group.cpp deleted file mode 100644 index 2508965..0000000 --- a/src/engine/scene/lod-group.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2023 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 -#include - -namespace scene { - -lod_group::lod_group(std::size_t level_count): - local_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}, - world_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}} -{ - resize(level_count); -} - -lod_group::lod_group(): - lod_group(1) -{} - -void lod_group::resize(std::size_t level_count) -{ - levels.resize(level_count); -} - -std::size_t lod_group::select_lod(const camera& camera) const -{ - float distance = camera.get_view_frustum().get_near().signed_distance(get_translation()); - - if (distance < 300.0f) - return 0; - else if (distance < 500.0f) - return 1; - else if (distance < 600.0f) - return 2; - - return 3; -} - -void lod_group::add_object(std::size_t level, object_base* object) -{ - levels[level].push_back(object); -} - -void lod_group::remove_object(std::size_t level, object_base* object) -{ - levels[level].remove(object); -} - -void lod_group::remove_objects(std::size_t level) -{ - levels[level].clear(); -} - -void lod_group::update_bounds() -{ - world_bounds = {get_translation(), get_translation()}; -} - -void lod_group::transformed() -{ - update_bounds(); -} - -} // namespace scene diff --git a/src/engine/scene/lod-group.hpp b/src/engine/scene/lod-group.hpp deleted file mode 100644 index cff5f7c..0000000 --- a/src/engine/scene/lod-group.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2023 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 . - */ - -#ifndef ANTKEEPER_SCENE_LOD_GROUP_HPP -#define ANTKEEPER_SCENE_LOD_GROUP_HPP - -#include -#include -#include -#include - -namespace scene { - -class camera; - -class lod_group: public object -{ -public: - typedef geom::aabb aabb_type; - - /** - * Creates a LOD group. - * - * @param level_count Number of detail levels in the group. - */ - explicit lod_group(std::size_t level_count); - - /// Creates a LOD group with one level of detail. - lod_group(); - - /** - * Resizes the LOD group to accommodate the specified number of detail levels. - * - * @param level_count Number of desired detail levels in the group. - */ - void resize(std::size_t level_count); - - /** - * Selects the appropriate level of detail for a camera. - * - * @param camera Camera for which the LOD should be selected. - * @return Selected level of detail. - */ - std::size_t select_lod(const camera& camera) const; - - /** - * Adds an object to the LOD group. - * - * @param level Level of detail of the object to add. - * @param object Object to add. - */ - void add_object(std::size_t level, object_base* object); - - /** - * Removes an object from the LOD group. - * - * @param level Level of detail of the object to remove. - * @param object Object to remove. - */ - void remove_object(std::size_t level, object_base* object); - - /** - * Removes all objects with the specified level of detail. - * - * @param level Level of detail of the objects to remove. - */ - void remove_objects(std::size_t level); - - virtual const bounding_volume_type& get_local_bounds() const; - virtual const bounding_volume_type& get_world_bounds() const; - - /// Returns the number of detail levels in the group. - std::size_t get_level_count() const; - - /** - * Returns a list containing all objects in the LOD group with the specified detail level. - * - * @param level Level of detail. - * @return List of all objects in the group with the specified detail level. - */ - const std::list& get_objects(std::size_t level) const; - -private: - void update_bounds(); - virtual void transformed(); - - aabb_type local_bounds; - aabb_type world_bounds; - std::vector> levels; -}; - -inline const typename object_base::bounding_volume_type& lod_group::get_local_bounds() const -{ - return local_bounds; -} - -inline const typename object_base::bounding_volume_type& lod_group::get_world_bounds() const -{ - return world_bounds; -} - -inline std::size_t lod_group::get_level_count() const -{ - return levels.size(); -} - -inline const std::list& lod_group::get_objects(std::size_t level) const -{ - return levels[level]; -} - -} // namespace scene - -#endif // ANTKEEPER_SCENE_LOD_GROUP_HPP - diff --git a/src/engine/scene/object.cpp b/src/engine/scene/object.cpp index cd7da1e..e2baeef 100644 --- a/src/engine/scene/object.cpp +++ b/src/engine/scene/object.cpp @@ -18,43 +18,20 @@ */ #include -#include namespace scene { -typename object_base::transform_type object_base::interpolate_transforms(const transform_type& x, const transform_type& y, float a) -{ - return - { - math::lerp(x.translation, y.translation, a), - math::nlerp(x.rotation, y.rotation, a), - math::lerp(x.scale, y.scale, a), - }; -} - -object_base::object_base(): - transform(math::transform::identity, interpolate_transforms) -{} - std::size_t object_base::next_object_type_id() { static std::atomic id{0}; return id++; } -void object_base::update_tweens() -{ - transform.update(); -} - void object_base::look_at(const vector_type& position, const vector_type& target, const vector_type& up) { - transform[1].translation = position; - transform[1].rotation = math::look_rotation(math::normalize(math::sub(target, position)), up); + m_transform.translation = position; + m_transform.rotation = math::look_rotation(math::normalize(math::sub(target, position)), up); transformed(); } -void object_base::transformed() -{} - } // namespace scene diff --git a/src/engine/scene/object.hpp b/src/engine/scene/object.hpp index de333dd..3e32816 100644 --- a/src/engine/scene/object.hpp +++ b/src/engine/scene/object.hpp @@ -20,7 +20,6 @@ #ifndef ANTKEEPER_SCENE_OBJECT_HPP #define ANTKEEPER_SCENE_OBJECT_HPP -#include #include #include #include @@ -32,23 +31,18 @@ namespace scene { /** - * Internal base class for scene objects. + * Abstract base class for scene objects. */ class object_base { public: - typedef math::vector vector_type; - typedef math::quaternion quaternion_type; - typedef math::transform transform_type; - typedef geom::bounding_volume bounding_volume_type; + using vector_type = math::vector; + using quaternion_type = math::quaternion; + using transform_type = math::transform; + using bounding_volume_type = geom::bounding_volume; /// Returns the type ID for this scene object type. virtual const std::size_t get_object_type_id() const noexcept = 0; - - /** - * Creates a scene object base. - */ - object_base(); /** * Adds render operations to a render context. @@ -56,18 +50,13 @@ public: * @param ctx Render context. */ inline virtual void render(render::context& ctx) const {} - - /** - * Updates all tweens in the scene object. - */ - virtual void update_tweens(); /** * Activates or deactivates the scene object. */ inline void set_active(bool active) noexcept { - this->active = active; + m_active = active; } /** @@ -80,7 +69,7 @@ public: */ inline void set_transform(const transform_type& transform) { - this->transform[1] = transform; + m_transform = transform; transformed(); } @@ -89,7 +78,7 @@ public: */ inline void set_translation(const vector_type& translation) { - transform[1].translation = translation; + m_transform.translation = translation; transformed(); } @@ -98,7 +87,7 @@ public: */ inline void set_rotation(const quaternion_type& rotation) { - transform[1].rotation = rotation; + m_transform.rotation = rotation; transformed(); } @@ -107,7 +96,7 @@ public: */ inline void set_scale(const vector_type& scale) { - transform[1].scale = scale; + m_transform.scale = scale; transformed(); } @@ -116,13 +105,13 @@ public: */ inline void set_culling_mask(const bounding_volume_type* culling_mask) noexcept { - this->culling_mask = culling_mask; + m_culling_mask = culling_mask; } /// Returns whether the scene object is active. [[nodiscard]] inline bool is_active() const noexcept { - return active; + return m_active; } /** @@ -130,7 +119,7 @@ public: */ [[nodiscard]] inline const transform_type& get_transform() const noexcept { - return transform[1]; + return m_transform; } /** @@ -138,7 +127,7 @@ public: */ [[nodiscard]] inline const vector_type& get_translation() const noexcept { - return transform[1].translation; + return m_transform.translation; } /** @@ -146,7 +135,7 @@ public: */ [[nodiscard]] inline const quaternion_type& get_rotation() const noexcept { - return transform[1].rotation; + return m_transform.rotation; } /** @@ -154,39 +143,20 @@ public: */ [[nodiscard]] inline const vector_type& get_scale() const noexcept { - return transform[1].scale; - } - - /** - * Returns the transform tween. - */ - /// @{ - [[nodiscard]] inline const tween& get_transform_tween() const noexcept - { - return transform; + return m_transform.scale; } - [[nodiscard]] inline tween& get_transform_tween() noexcept - { - return transform; - } - /// @} - - /** - * Returns the local-space (untransformed) bounds of the object. - */ - [[nodiscard]] virtual const bounding_volume_type& get_local_bounds() const = 0; /** - * Returns the world-space (transformed) bounds of the object. + * Returns the bounds of the object. */ - [[nodiscard]] virtual const bounding_volume_type& get_world_bounds() const = 0; + [[nodiscard]] virtual const bounding_volume_type& get_bounds() const noexcept = 0; /** * Returns the culling mask of the object. */ [[nodiscard]] inline const bounding_volume_type* get_culling_mask() const noexcept { - return culling_mask; + return m_culling_mask; } protected: @@ -199,11 +169,11 @@ private: /** * Called every time the scene object's tranform is changed. */ - virtual void transformed(); - - bool active{true}; - tween transform; - const bounding_volume_type* culling_mask{nullptr}; + inline virtual void transformed() {} + + bool m_active{true}; + transform_type m_transform{transform_type::identity}; + const bounding_volume_type* m_culling_mask{nullptr}; }; /** diff --git a/src/engine/scene/point-light.cpp b/src/engine/scene/point-light.cpp index 9e62f8e..62e3046 100644 --- a/src/engine/scene/point-light.cpp +++ b/src/engine/scene/point-light.cpp @@ -18,23 +18,9 @@ */ #include -#include namespace scene { -point_light::point_light(): - attenuation(float3{1, 0, 0}, math::lerp) -{} -void point_light::set_attenuation(const float3& attenuation) -{ - this->attenuation[1] = attenuation; -} - -void point_light::update_tweens() -{ - light::update_tweens(); - attenuation.update(); -} } // namespace scene diff --git a/src/engine/scene/point-light.hpp b/src/engine/scene/point-light.hpp index 049680a..77902b2 100644 --- a/src/engine/scene/point-light.hpp +++ b/src/engine/scene/point-light.hpp @@ -21,7 +21,7 @@ #define ANTKEEPER_SCENE_POINT_LIGHT_HPP #include -#include +#include namespace scene { @@ -31,40 +31,49 @@ namespace scene { class point_light: public light { public: - point_light(); - /// Returns light_type::point [[nodiscard]] inline light_type get_light_type() const noexcept override { return light_type::point; } + /** + * Sets the luminous flux of the point light. + * + * @param luminous_flux Luminous flux, in *lm*. + */ + inline void set_luminous_flux(const math::vector& luminous_flux) noexcept + { + m_luminous_flux = luminous_flux; + } + + /// Returns the luminous flux of the point light, in *lm*. + [[nodiscard]] inline const math::vector& get_luminous_flux() const noexcept + { + return m_luminous_flux; + } + /** * Sets the attenuation factors of the light. * * @param attenuation Vector containing the constant, linear, and quadratic attenuation factors, as x, y, and z, respectively. */ - void set_attenuation(const float3& attenuation); - - /// Returns the attenuation factors of the light. - [[nodiscard]] inline const float3& get_attenuation() const noexcept + inline void set_attenuation(const float3& attenuation) noexcept { - return attenuation[1]; + m_attenuation = attenuation; } - /// Returns the attenuation tween. - [[nodiscard]] inline const tween& get_attenuation_tween() const noexcept + /// Returns the attenuation factors of the light. + [[nodiscard]] inline const math::vector& get_attenuation() const noexcept { - return attenuation; + return m_attenuation; } - void update_tweens() override; - private: - tween attenuation; + math::vector m_luminous_flux{0.0f, 0.0f, 0.0f}; + math::vector m_attenuation{1.0f, 0.0f, 0.0f}; }; } // namespace scene #endif // ANTKEEPER_SCENE_POINT_LIGHT_HPP - diff --git a/src/engine/scene/scene.hpp b/src/engine/scene/scene.hpp index b9b8c7e..9a80cfe 100644 --- a/src/engine/scene/scene.hpp +++ b/src/engine/scene/scene.hpp @@ -20,20 +20,7 @@ #ifndef ANTKEEPER_SCENE_HPP #define ANTKEEPER_SCENE_HPP -/// 3D scene +/// 3D scene. namespace scene {} -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #endif // ANTKEEPER_SCENE_HPP diff --git a/src/engine/scene/spot-light.cpp b/src/engine/scene/spot-light.cpp index 4a5811e..3b6110b 100644 --- a/src/engine/scene/spot-light.cpp +++ b/src/engine/scene/spot-light.cpp @@ -18,50 +18,19 @@ */ #include -#include -#include -#include #include namespace scene { -static float3 interpolate_direction(const float3& x, const float3& y, float a) +void spot_light::set_cutoff(const math::vector& cutoff) { - math::quaternion q0 = math::rotation(config::global_forward, x); - math::quaternion q1 = math::rotation(config::global_forward, y); - return math::normalize(math::slerp(q0, q1, a) * config::global_forward); -} - -spot_light::spot_light(): - direction(config::global_forward, interpolate_direction), - attenuation(float3{1, 0, 0}, math::lerp), - cutoff(float2{math::pi, math::pi}, math::lerp), - cosine_cutoff(float2{std::cos(math::pi), std::cos(math::pi)}, math::lerp) -{} - -void spot_light::set_attenuation(const float3& attenuation) -{ - this->attenuation[1] = attenuation; -} - -void spot_light::set_cutoff(const float2& cutoff) -{ - this->cutoff[1] = cutoff; - this->cosine_cutoff[1] = {std::cos(cutoff.x()), std::cos(cutoff.y())}; -} - -void spot_light::update_tweens() -{ - light::update_tweens(); - direction.update(); - attenuation.update(); - cutoff.update(); - cosine_cutoff.update(); + m_cutoff = cutoff; + m_cosine_cutoff = {std::cos(m_cutoff.x()), std::cos(m_cutoff.y())}; } void spot_light::transformed() { - direction[1] = math::normalize(get_transform().rotation * config::global_forward); + m_direction = get_transform().rotation * math::vector{0.0f, 0.0f, -1.0f}; } } // namespace scene diff --git a/src/engine/scene/spot-light.hpp b/src/engine/scene/spot-light.hpp index 7c62bda..efa906e 100644 --- a/src/engine/scene/spot-light.hpp +++ b/src/engine/scene/spot-light.hpp @@ -21,7 +21,8 @@ #define ANTKEEPER_SCENE_SPOT_LIGHT_HPP #include -#include +#include +#include namespace scene { @@ -31,86 +32,77 @@ namespace scene { class spot_light: public light { public: - /// Creates a spot light. - spot_light(); - - /// Returns light_type::spot + /// Returns light_type::spot. [[nodiscard]] inline light_type get_light_type() const noexcept override { return light_type::spot; } + /** + * Sets the luminous flux of the spot light. + * + * @param luminous_flux Luminous flux, in *lm*. + */ + inline void set_luminous_flux(const math::vector& luminous_flux) noexcept + { + m_luminous_flux = luminous_flux; + } + + /// Returns the luminous flux of the spot light, in *lm*. + [[nodiscard]] inline const math::vector& get_luminous_flux() const noexcept + { + return m_luminous_flux; + } + /** * Sets the attenuation factors of the light. * * @param attenuation Vector containing the constant, linear, and quadratic attenuation factors, as x, y, and z, respectively. */ - void set_attenuation(const float3& attenuation); + inline void set_attenuation(const math::vector& attenuation) noexcept + { + m_attenuation = attenuation; + } /** * Sets the spot light cutoff angles. * * @param cutoff Vector containing the inner and outer cutoff angles, as x and y, respectively. */ - void set_cutoff(const float2& cutoff); + void set_cutoff(const math::vector& cutoff); /// Returns the direction vector. - [[nodiscard]] inline const float3& get_direction() const noexcept + [[nodiscard]] inline const math::vector& get_direction() const noexcept { - return direction[1]; + return m_direction; } /// Returns the attenuation factors of the light. - [[nodiscard]] inline const float3& get_attenuation() const noexcept + [[nodiscard]] inline const math::vector& get_attenuation() const noexcept { - return attenuation[1]; + return m_attenuation; } /// Returns the spot light cutoff angles. - [[nodiscard]] inline const float2& get_cutoff() const noexcept + [[nodiscard]] inline const math::vector& get_cutoff() const noexcept { - return cutoff[1]; + return m_cutoff; } /// Returns the cosine of the spot light cutoff angles. - [[nodiscard]] inline const float2& get_cosine_cutoff() const noexcept + [[nodiscard]] inline const math::vector& get_cosine_cutoff() const noexcept { - return cosine_cutoff[1]; - } - - /// Returns the direction tween. - [[nodiscard]] inline const tween& get_direction_tween() const noexcept - { - return direction; - } - - /// Returns the attenuation tween. - [[nodiscard]] inline const tween& get_attenuation_tween() const noexcept - { - return attenuation; - } - - /// Returns the cutoff tween. - [[nodiscard]] inline const tween& get_cutoff_tween() const noexcept - { - return cutoff; - } - - /// Returns the cosine cutoff tween. - [[nodiscard]] inline const tween& get_cosine_cutoff_tween() const noexcept - { - return cosine_cutoff; + return m_cosine_cutoff; } - void update_tweens() override; - private: void transformed() override; - - tween direction; - tween attenuation; - tween cutoff; - tween cosine_cutoff; + + math::vector m_luminous_flux{0.0f, 0.0f, 0.0f}; + math::vector m_direction{0.0f, 0.0f, -1.0f}; + math::vector m_attenuation{1.0f, 0.0f, 0.0f}; + math::vector m_cutoff{math::pi, math::pi}; + math::vector m_cosine_cutoff{-1.0f, -1.0f}; }; } // namespace scene diff --git a/src/engine/scene/static-mesh.cpp b/src/engine/scene/static-mesh.cpp index 7d84dc8..d063d38 100644 --- a/src/engine/scene/static-mesh.cpp +++ b/src/engine/scene/static-mesh.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace scene { @@ -30,87 +31,83 @@ static_mesh::static_mesh(std::shared_ptr model) void static_mesh::set_model(std::shared_ptr model) { - this->model = model; + m_model = model; - if (model) + if (m_model) { - operations.resize(model->get_groups().size()); - for (std::size_t i = 0; i < operations.size(); ++i) + m_operations.resize(m_model->get_groups().size()); + for (std::size_t i = 0; i < m_operations.size(); ++i) { - const auto& group = model->get_groups()[i]; + const auto& group = m_model->get_groups()[i]; - auto& operation = operations[i]; - operation.vertex_array = model->get_vertex_array().get(); + auto& operation = m_operations[i]; + operation.vertex_array = m_model->get_vertex_array().get(); operation.drawing_mode = group.drawing_mode; operation.start_index = group.start_index; operation.index_count = group.index_count; operation.material = group.material; } - pose = model->get_skeleton().bind_pose; - ::concatenate(pose, pose); + ::concatenate(m_model->get_skeleton().bind_pose, m_pose); } else { - operations.clear(); - pose.clear(); + m_operations.clear(); + m_pose.clear(); } - update_bounds(); + transformed(); } void static_mesh::set_material(std::size_t index, std::shared_ptr material) { if (material) { - operations[index].material = material; + m_operations[index].material = material; } else { - operations[index].material = model->get_groups()[index].material; + m_operations[index].material = m_model->get_groups()[index].material; } } void static_mesh::reset_materials() { - for (std::size_t i = 0; i < operations.size(); ++i) + for (std::size_t i = 0; i < m_operations.size(); ++i) { - operations[i].material = model->get_groups()[i].material; + m_operations[i].material = m_model->get_groups()[i].material; } } void static_mesh::update_bounds() { - if (model) + if (m_model) { - local_bounds = aabb_type::transform(model->get_bounds(), get_transform()); - transformed(); + m_bounds = aabb_type::transform(m_model->get_bounds(), get_transform()); } else { - local_bounds = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}; - world_bounds = {get_translation(), get_translation()}; + m_bounds = {get_translation(), get_translation()}; } } void static_mesh::transformed() { - world_bounds = aabb_type::transform(local_bounds, get_transform()); -} - -void static_mesh::update_tweens() -{ - object_base::update_tweens(); + update_bounds(); + + const float4x4 transform_matrix = math::matrix_cast(get_transform()); + for (auto& operation: m_operations) + { + operation.transform = transform_matrix; + } } void static_mesh::render(render::context& ctx) const { - const float4x4 transform = math::matrix_cast(get_transform_tween().interpolate(ctx.alpha)); - - for (auto& operation: operations) + const float depth = ctx.camera->get_view_frustum().get_near().signed_distance(get_translation()); + for (auto& operation: m_operations) { - operation.transform = transform; - operation.depth = ctx.clip_near.signed_distance(float3(operation.transform[3])); + operation.depth = depth; ctx.operations.push_back(&operation); } } diff --git a/src/engine/scene/static-mesh.hpp b/src/engine/scene/static-mesh.hpp index fe5c5a9..054eb87 100644 --- a/src/engine/scene/static-mesh.hpp +++ b/src/engine/scene/static-mesh.hpp @@ -67,20 +67,9 @@ public: */ void reset_materials(); - /** - * Returns the local bounds of the model instance. - */ - [[nodiscard]] inline virtual const bounding_volume_type& get_local_bounds() const noexcept - { - return local_bounds; - } - - /** - * Returns the world bounds of the model instance. - */ - [[nodiscard]] inline virtual const bounding_volume_type& get_world_bounds() const noexcept + [[nodiscard]] inline const bounding_volume_type& get_bounds() const noexcept override { - return world_bounds; + return m_bounds; } /** @@ -88,7 +77,7 @@ public: */ [[nodiscard]] inline const std::shared_ptr& get_model() const noexcept { - return model; + return m_model; } /** @@ -97,29 +86,24 @@ public: /// @{ [[nodiscard]] inline const pose& get_pose() const noexcept { - return pose; + return m_pose; } [[nodiscard]] inline pose& get_pose() noexcept { - return pose; + return m_pose; } /// @} void render(render::context& ctx) const override; - void update_tweens() override; - - void update_bounds(); - private: + void update_bounds(); void transformed() override; - std::shared_ptr model; - mutable std::vector operations; - ::pose pose; - - aabb_type local_bounds{{0, 0, 0}, {0, 0, 0}}; - aabb_type world_bounds{{0, 0, 0}, {0, 0, 0}}; + std::shared_ptr m_model; + mutable std::vector m_operations; + ::pose m_pose; + aabb_type m_bounds{{0, 0, 0}, {0, 0, 0}}; }; } // namespace scene diff --git a/src/engine/scene/text.cpp b/src/engine/scene/text.cpp index 2794ab3..5d22c44 100644 --- a/src/engine/scene/text.cpp +++ b/src/engine/scene/text.cpp @@ -20,77 +20,66 @@ #include #include #include +#include #include namespace scene { -text::text(): - local_bounds{{0, 0, 0}, {0, 0, 0}}, - world_bounds{{0, 0, 0}, {0, 0, 0}}, - font(nullptr), - direction(type::text_direction::ltr), - content_u8(std::string()), - content_u32(std::u32string()), - color({0.0f, 0.0f, 0.0f, 1.0f}), - vertex_stride(0), - vertex_count(0), - vao(nullptr), - vbo(nullptr) +text::text() { // Allocate VBO and VAO - vbo = std::make_unique(); - vao = std::make_unique(); + m_vbo = std::make_unique(); + m_vao = std::make_unique(); // Calculate vertex stride - vertex_stride = (3 + 2 + 4) * sizeof(float); + m_vertex_stride = (3 + 2 + 4) * sizeof(float); // Init vertex attribute offset std::size_t attribute_offset = 0; // Define vertex position attribute gl::vertex_attribute position_attribute; - position_attribute.buffer = vbo.get(); + position_attribute.buffer = m_vbo.get(); position_attribute.offset = attribute_offset; - position_attribute.stride = vertex_stride; + position_attribute.stride = m_vertex_stride; position_attribute.type = gl::vertex_attribute_type::float_32; position_attribute.components = 3; attribute_offset += position_attribute.components * sizeof(float); // Define vertex UV attribute gl::vertex_attribute uv_attribute; - uv_attribute.buffer = vbo.get(); + uv_attribute.buffer = m_vbo.get(); uv_attribute.offset = attribute_offset; - uv_attribute.stride = vertex_stride; + uv_attribute.stride = m_vertex_stride; uv_attribute.type = gl::vertex_attribute_type::float_32; uv_attribute.components = 2; attribute_offset += uv_attribute.components * sizeof(float); // Define vertex color attribute gl::vertex_attribute color_attribute; - color_attribute.buffer = vbo.get(); + color_attribute.buffer = m_vbo.get(); color_attribute.offset = attribute_offset; - color_attribute.stride = vertex_stride; + color_attribute.stride = m_vertex_stride; color_attribute.type = gl::vertex_attribute_type::float_32; color_attribute.components = 4; //attribute_offset += color_attribute.components * sizeof(float); // Bind vertex attributes to VAO - vao->bind(render::vertex_attribute::position, position_attribute); - vao->bind(render::vertex_attribute::uv, uv_attribute); - vao->bind(render::vertex_attribute::color, color_attribute); + m_vao->bind(render::vertex_attribute::position, position_attribute); + m_vao->bind(render::vertex_attribute::uv, uv_attribute); + m_vao->bind(render::vertex_attribute::color, color_attribute); // Init render operation - render_op.vertex_array = vao.get(); - render_op.drawing_mode = gl::drawing_mode::triangles; + m_render_op.vertex_array = m_vao.get(); + m_render_op.drawing_mode = gl::drawing_mode::triangles; } void text::render(render::context& ctx) const { - if (vertex_count) + if (m_vertex_count) { - render_op.transform = math::matrix_cast(get_transform_tween().interpolate(ctx.alpha)); - render_op.depth = ctx.clip_near.signed_distance(math::vector(render_op.transform[3])); - ctx.operations.push_back(&render_op); + m_render_op.depth = ctx.camera->get_view_frustum().get_near().signed_distance(get_translation()); + ctx.operations.push_back(&m_render_op); } } @@ -101,112 +90,96 @@ void text::refresh() void text::set_material(std::shared_ptr material) { - render_op.material = material; + m_render_op.material = material; } void text::set_font(const type::bitmap_font* font) { - if (this->font != font) + if (m_font != font) { - this->font = font; - - // Update text in VBO + m_font = font; update_content(); } } void text::set_direction(type::text_direction direction) { - if (this->direction != direction) + if (m_direction != direction) { - this->direction = direction; - - // Update text in VBO + m_direction = direction; update_content(); } } void text::set_content(const std::string& content) { - // If content has changed - if (content_u8 != content) + if (m_content_u8 != content) { - // Update UTF-8 content - content_u8 = content; - - // Convert UTF-8 content to UTF-32 - content_u32 = type::unicode::u32(content_u8); - - // Update text in VBO + m_content_u8 = content; + m_content_u32 = type::unicode::u32(m_content_u8); update_content(); } } void text::set_color(const float4& color) { - this->color = color; - - // Update color in VBO + m_color = color; update_color(); } void text::transformed() { - world_bounds = aabb_type::transform(local_bounds, get_transform()); -} - -void text::update_tweens() -{ - object_base::update_tweens(); + m_world_bounds = aabb_type::transform(m_local_bounds, get_transform()); + m_render_op.transform = math::matrix_cast(get_transform()); } void text::update_content() { // If no valid font or no text, clear vertex count - if (!font || content_u32.empty()) + if (!m_font || m_content_u32.empty()) { - vertex_count = 0; - render_op.index_count = vertex_count; - local_bounds = {{0, 0, 0}, {0, 0, 0}}; + m_vertex_count = 0; + m_render_op.index_count = 0; + m_local_bounds = {{0, 0, 0}, {0, 0, 0}}; transformed(); return; } // Calculate new vertex count and minimum vertex buffer size - std::size_t vertex_count = content_u32.length() * 6; - std::size_t min_vertex_buffer_size = vertex_count * vertex_stride; + std::size_t vertex_count = m_content_u32.length() * 6; + std::size_t min_vertex_buffer_size = vertex_count * m_vertex_stride; // Expand vertex data buffer to accommodate vertices - if (vertex_data.size() < min_vertex_buffer_size) + if (m_vertex_data.size() < min_vertex_buffer_size) { - vertex_data.resize(min_vertex_buffer_size); + m_vertex_data.resize(min_vertex_buffer_size); } // Get font metrics and bitmap - const type::font_metrics& font_metrics = font->get_font_metrics(); - const image& font_bitmap = font->get_bitmap(); + const type::font_metrics& font_metrics = m_font->get_font_metrics(); + const image& font_bitmap = m_font->get_bitmap(); // Init pen position float2 pen_position = {0.0f, 0.0f}; // Reset local-space bounds - local_bounds = {{0, 0, 0}, {0, 0, 0}}; + m_local_bounds = {{0, 0, 0}, {0, 0, 0}}; // Generate vertex data char32_t previous_code = 0; - float* v = reinterpret_cast(vertex_data.data()); - for (char32_t code: content_u32) + float* v = reinterpret_cast(m_vertex_data.data()); + for (char32_t code: m_content_u32) { // Apply kerning if (previous_code) { - pen_position.x() += font->get_kerning(previous_code, code).x(); + pen_position.x() += m_font->get_kerning(previous_code, code).x(); } - if (font->contains(code)) + if (m_font->contains(code)) { // Get glyph - const type::bitmap_glyph& glyph = font->get_glyph(code); + const type::bitmap_glyph& glyph = m_font->get_glyph(code); // Calculate vertex positions float2 positions[6]; @@ -245,10 +218,10 @@ void text::update_content() *(v++) = 0.0f; *(v++) = uvs[i].x(); *(v++) = uvs[i].y(); - *(v++) = color[0]; - *(v++) = color[1]; - *(v++) = color[2]; - *(v++) = color[3]; + *(v++) = m_color[0]; + *(v++) = m_color[1]; + *(v++) = m_color[2]; + *(v++) = m_color[3]; } // Advance pen position @@ -260,8 +233,8 @@ void text::update_content() const float2& position = positions[i]; for (int j = 0; j < 2; ++j) { - local_bounds.min_point[j] = std::min(local_bounds.min_point[j], position[j]); - local_bounds.max_point[j] = std::max(local_bounds.max_point[j], position[j]); + m_local_bounds.min_point[j] = std::min(m_local_bounds.min_point[j], position[j]); + m_local_bounds.max_point[j] = std::max(m_local_bounds.max_point[j], position[j]); } } } @@ -269,7 +242,9 @@ void text::update_content() { // Glyph not in font, zero vertex data for (std::size_t i = 0; i < (6 * 9); ++i) + { *(v++) = 0.0f; + } } // Handle newlines @@ -284,19 +259,18 @@ void text::update_content() } // Resize VBO, if necessary, and upload vertex data - if (vertex_count > this->vertex_count) + if (vertex_count > m_vertex_count) { - this->vertex_count = vertex_count; - vbo->resize(min_vertex_buffer_size, vertex_data); + m_vbo->resize(min_vertex_buffer_size, m_vertex_data); } else { - vbo->write({vertex_data.data(), min_vertex_buffer_size}); + m_vbo->write({m_vertex_data.data(), min_vertex_buffer_size}); } // Update vertex count - this->vertex_count = vertex_count; - render_op.index_count = vertex_count; + m_vertex_count = vertex_count; + m_render_op.index_count = vertex_count; // Update world-space bounds transformed(); @@ -304,21 +278,21 @@ void text::update_content() void text::update_color() { - float* v = reinterpret_cast(vertex_data.data()); - for (std::size_t i = 0; i < vertex_count; ++i) + float* v = reinterpret_cast(m_vertex_data.data()); + for (std::size_t i = 0; i < m_vertex_count; ++i) { // Skip vertex position (vec3) and vertex UV (vec2) v += (3 + 2); // Update vertex color - *(v++) = color[0]; - *(v++) = color[1]; - *(v++) = color[2]; - *(v++) = color[3]; + *(v++) = m_color[0]; + *(v++) = m_color[1]; + *(v++) = m_color[2]; + *(v++) = m_color[3]; } // Update VBO - vbo->write({vertex_data.data(), vertex_count * vertex_stride}); + m_vbo->write({m_vertex_data.data(), m_vertex_count * m_vertex_stride}); } } // namespace scene diff --git a/src/engine/scene/text.hpp b/src/engine/scene/text.hpp index 43993f2..c4ddb91 100644 --- a/src/engine/scene/text.hpp +++ b/src/engine/scene/text.hpp @@ -37,7 +37,7 @@ namespace scene { class text: public object { public: - typedef geom::aabb aabb_type; + using aabb_type = geom::aabb; /// Constructs a text object. text(); @@ -87,28 +87,39 @@ public: void set_color(const float4& color); /// Returns the text material. - std::shared_ptr get_material() const; + [[nodiscard]] inline std::shared_ptr get_material() const noexcept + { + return m_render_op.material; + } /// Returns the text font. - const type::bitmap_font* get_font() const; + [[nodiscard]] inline const type::bitmap_font* get_font() const noexcept + { + return m_font; + } /// Returns the text direction. - const type::text_direction& get_direction() const; + [[nodiscard]] inline const type::text_direction& get_direction() const noexcept + { + return m_direction; + } /// Returns the text content. - const std::string& get_content() const; + [[nodiscard]] inline const std::string& get_content() const noexcept + { + return m_content_u8; + } /// Returns the text color. - const float4& get_color() const; - - /// @copydoc scene::object::get_local_bounds() const - virtual const bounding_volume_type& get_local_bounds() const; - - /// @copydoc scene::object::get_world_bounds() const - virtual const bounding_volume_type& get_world_bounds() const; - - /// @copydoc scene::object::update_tweens() - virtual void update_tweens(); + [[nodiscard]] inline const float4& get_color() const noexcept + { + return m_color; + } + + [[nodiscard]] inline virtual const bounding_volume_type& get_bounds() const noexcept + { + return m_world_bounds; + } private: void update_content(); @@ -116,56 +127,21 @@ private: virtual void transformed(); - mutable render::operation render_op; - aabb_type local_bounds; - aabb_type world_bounds; - const type::bitmap_font* font; - type::text_direction direction; - std::string content_u8; - std::u32string content_u32; - float4 color; - std::size_t vertex_stride; - std::size_t vertex_count; - std::vector vertex_data; - std::unique_ptr vao; - std::unique_ptr vbo; + mutable render::operation m_render_op; + aabb_type m_local_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}; + aabb_type m_world_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}; + const type::bitmap_font* m_font{nullptr}; + type::text_direction m_direction{type::text_direction::ltr}; + std::string m_content_u8; + std::u32string m_content_u32; + float4 m_color{1.0f, 0.0f, 1.0f, 1.0f}; + std::size_t m_vertex_stride{0}; + std::size_t m_vertex_count{0}; + std::vector m_vertex_data; + std::unique_ptr m_vao; + std::unique_ptr m_vbo; }; -inline std::shared_ptr text::get_material() const -{ - return render_op.material; -} - -inline const type::bitmap_font* text::get_font() const -{ - return font; -} - -inline const type::text_direction& text::get_direction() const -{ - return direction; -} - -inline const std::string& text::get_content() const -{ - return content_u8; -} - -inline const float4& text::get_color() const -{ - return color; -} - -inline const typename object_base::bounding_volume_type& text::get_local_bounds() const -{ - return local_bounds; -} - -inline const typename object_base::bounding_volume_type& text::get_world_bounds() const -{ - return world_bounds; -} - } // namespace scene #endif // ANTKEEPER_SCENE_TEXT_HPP diff --git a/src/game/ant/ant-swarm.cpp b/src/game/ant/ant-swarm.cpp index 69b9ab3..30d9c80 100644 --- a/src/game/ant/ant-swarm.cpp +++ b/src/game/ant/ant-swarm.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,6 @@ entity::id create_ant_swarm(::game& ctx) ::transform_component transform; transform.local = math::transform::identity; transform.world = transform.local; - transform.warp = true; // Init picking component ::picking_component picking; @@ -77,7 +77,6 @@ entity::id create_ant_swarm(::game& ctx) entity::id swarm_eid = ctx.entity_registry->create(); transform.local.translation = swarm_center; transform.world = transform.local; - transform.warp = true; ctx.entity_registry->emplace<::transform_component>(swarm_eid, transform); // Load male model diff --git a/src/game/commands/commands.cpp b/src/game/commands/commands.cpp index bc33e9a..5428e86 100644 --- a/src/game/commands/commands.cpp +++ b/src/game/commands/commands.cpp @@ -86,7 +86,6 @@ void warp_to(entity::registry& registry, entity::id eid, const float3& position) [&position](auto& transform) { transform.local.translation = position; - transform.warp = true; } ); } @@ -108,7 +107,7 @@ void set_scale(entity::registry& registry, entity::id eid, const float3& scale) } } -void set_transform(entity::registry& registry, entity::id eid, const math::transform& transform, bool warp) +void set_transform(entity::registry& registry, entity::id eid, const math::transform& transform) { const ::transform_component* transform_component = registry.try_get<::transform_component>(eid); if (transform_component) @@ -116,10 +115,9 @@ void set_transform(entity::registry& registry, entity::id eid, const math::trans registry.patch<::transform_component> ( eid, - [&other_transform = transform, warp](auto& transform) + [&other_transform = transform](auto& transform) { transform.local = other_transform; - transform.warp = warp; } ); } diff --git a/src/game/commands/commands.hpp b/src/game/commands/commands.hpp index abd7a07..9a9cb8e 100644 --- a/src/game/commands/commands.hpp +++ b/src/game/commands/commands.hpp @@ -34,7 +34,7 @@ void rotate(entity::registry& registry, entity::id eid, float angle, const float void move_to(entity::registry& registry, entity::id eid, const float3& position); void warp_to(entity::registry& registry, entity::id eid, const float3& position); void set_scale(entity::registry& registry, entity::id eid, const float3& scale); -void set_transform(entity::registry& registry, entity::id eid, const math::transform& transform, bool warp = false); +void set_transform(entity::registry& registry, entity::id eid, const math::transform& transform); void place(entity::registry& registry, entity::id eid, entity::id celestial_body_id, double altitude, double latitude, double longitude); void assign_render_layers(entity::registry& registry, entity::id eid, unsigned int layers); math::transform get_local_transform(entity::registry& registry, entity::id eid); diff --git a/src/game/components/scene-component.hpp b/src/game/components/scene-component.hpp index 8c4b396..6b9563c 100644 --- a/src/game/components/scene-component.hpp +++ b/src/game/components/scene-component.hpp @@ -26,8 +26,8 @@ struct scene_component { - std::unique_ptr object; - std::uint8_t layer_mask{0b11111111}; + std::shared_ptr object; + std::uint8_t layer_mask{0b00000001}; }; #endif // ANTKEEPER_GAME_SCENE_COMPONENT_HPP diff --git a/src/game/components/transform-component.hpp b/src/game/components/transform-component.hpp index f84d501..c2a7346 100644 --- a/src/game/components/transform-component.hpp +++ b/src/game/components/transform-component.hpp @@ -27,9 +27,7 @@ struct transform_component { math::transform local; math::transform world; - bool warp; }; - #endif // ANTKEEPER_GAME_TRANSFORM_COMPONENT_HPP diff --git a/src/game/controls.cpp b/src/game/controls.cpp index 80804fe..b668de0 100644 --- a/src/game/controls.cpp +++ b/src/game/controls.cpp @@ -416,7 +416,7 @@ void enable_menu_controls(::game& ctx) { auto [name, value] = ctx.menu_item_texts[i]; - const auto& name_bounds = static_cast&>(name->get_world_bounds()); + const auto& name_bounds = static_cast&>(name->get_bounds()); float min_x = name_bounds.min_point.x(); float min_y = name_bounds.min_point.y(); float max_x = name_bounds.max_point.x(); @@ -424,7 +424,7 @@ void enable_menu_controls(::game& ctx) if (value) { - const auto& value_bounds = static_cast&>(value->get_world_bounds()); + const auto& value_bounds = static_cast&>(value->get_bounds()); min_x = std::min(min_x, value_bounds.min_point.x()); min_y = std::min(min_y, value_bounds.min_point.y()); max_x = std::max(max_x, value_bounds.max_point.x()); diff --git a/src/game/game.cpp b/src/game/game.cpp index d2d9afd..0c7e318 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -802,27 +802,19 @@ void game::setup_scenes() surface_scene = std::make_unique(); // Setup surface camera - surface_camera = std::make_unique(); + surface_camera = std::make_shared(); surface_camera->set_perspective(math::radians(45.0f), viewport_aspect_ratio, 0.1f, 5000.0f); surface_camera->set_compositor(surface_compositor.get()); surface_camera->set_composite_index(0); - surface_camera->set_active(false); - - // Add surface scene objects to surface scene - surface_scene->add_object(surface_camera.get()); // Setup underground scene underground_scene = std::make_unique(); // Setup underground camera - underground_camera = std::make_unique(); + underground_camera = std::make_shared(); underground_camera->set_perspective(math::radians(45.0f), viewport_aspect_ratio, 0.1f, 1000.0f); underground_camera->set_compositor(underground_compositor.get()); underground_camera->set_composite_index(0); - underground_camera->set_active(false); - - // Add underground scene objects to underground scene - underground_scene->add_object(underground_camera.get()); // Clear active scene active_scene = nullptr; @@ -891,7 +883,6 @@ void game::setup_ui() const float clip_far = 100.0f; ui_camera->set_orthographic(clip_left, clip_right, clip_top, clip_bottom, clip_near, clip_far); ui_camera->look_at({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 0.0f}); - ui_camera->update_tweens(); // Menu BG material menu_bg_material = std::make_shared(); @@ -906,7 +897,6 @@ void game::setup_ui() menu_bg_billboard->set_material(menu_bg_material); menu_bg_billboard->set_scale({std::ceil(viewport_size.x() * 0.5f), std::ceil(viewport_size.y() * 0.5f), 1.0f}); menu_bg_billboard->set_translation({std::floor(viewport_size.x() * 0.5f), std::floor(viewport_size.y() * 0.5f), -100.0f}); - menu_bg_billboard->update_tweens(); // Create fade transition fade_transition = std::make_unique(); @@ -914,7 +904,6 @@ void game::setup_ui() fade_transition_color = std::make_shared(1, float3{0, 0, 0}); fade_transition->get_material()->set_variable("color", fade_transition_color); fade_transition->get_billboard()->set_translation({0, 0, 98}); - fade_transition->get_billboard()->update_tweens(); // Create inner radial transition radial_transition_inner = std::make_unique(); @@ -943,10 +932,9 @@ void game::setup_ui() ( [&, menu_bg_tint]() { - ui_scene->add_object(menu_bg_billboard.get()); + ui_scene->add_object(*menu_bg_billboard); menu_bg_tint->set(float4{0.0f, 0.0f, 0.0f, 0.0f}); - //menu_bg_tint->update_tweens(); menu_bg_billboard->set_active(true); } ); @@ -964,7 +952,7 @@ void game::setup_ui() ( [&]() { - ui_scene->remove_object(menu_bg_billboard.get()); + ui_scene->remove_object(*menu_bg_billboard); menu_bg_billboard->set_active(false); } ); @@ -972,8 +960,8 @@ void game::setup_ui() } // Add UI scene objects to UI scene - ui_scene->add_object(ui_camera.get()); - ui_scene->add_object(fade_transition->get_billboard()); + ui_scene->add_object(*ui_camera); + ui_scene->add_object(*fade_transition->get_billboard()); // Add UI animations to animator animator->add_animation(fade_transition->get_animation()); @@ -1017,7 +1005,6 @@ void game::setup_ui() // Re-align debug text frame_time_text->set_translation({std::round(0.0f), std::round(viewport_size.y() - debug_font.get_font_metrics().size), 99.0f}); - frame_time_text->update_tweens(); // Re-align menu text ::menu::align_text(*this); @@ -1186,9 +1173,8 @@ void game::setup_debugging() frame_time_text->set_color({1.0f, 1.0f, 0.0f, 1.0f}); frame_time_text->set_font(&debug_font); frame_time_text->set_translation({std::round(0.0f), std::round(viewport_size.y() - debug_font.get_font_metrics().size), 99.0f}); - frame_time_text->update_tweens(); - ui_scene->add_object(frame_time_text.get()); + ui_scene->add_object(*frame_time_text); } void game::setup_timing() @@ -1241,9 +1227,6 @@ void game::fixed_update(::frame_scheduler::duration_type fixed_update_time, ::fr // Update tweens sky_pass->update_tweens(); - surface_scene->update_tweens(); - underground_scene->update_tweens(); - ui_scene->update_tweens(); // Process window events window_manager->update(); @@ -1290,12 +1273,15 @@ void game::variable_update(::frame_scheduler::duration_type fixed_update_time, : // Update frame rate display frame_time_text->set_content(std::format("{:5.02f}ms / {:5.02f} FPS", average_frame_ms, average_frame_fps)); + // Process input events + input_manager->update(); + + // Interpolate physics + physics_system->interpolate(alpha); + // Render render_system->draw(alpha); window->swap_buffers(); - - // Process input events - input_manager->update(); } void game::execute() diff --git a/src/game/game.hpp b/src/game/game.hpp index de614d0..1ea7618 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -42,13 +42,20 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -312,9 +319,9 @@ public: // Scene std::unique_ptr surface_scene; - std::unique_ptr surface_camera; + std::shared_ptr surface_camera; std::unique_ptr underground_scene; - std::unique_ptr underground_camera; + std::shared_ptr underground_camera; std::unique_ptr underground_ambient_light; std::unique_ptr flashlight_spot_light; diff --git a/src/game/loaders/entity-archetype-loader.cpp b/src/game/loaders/entity-archetype-loader.cpp index a8eb6a2..2942c90 100644 --- a/src/game/loaders/entity-archetype-loader.cpp +++ b/src/game/loaders/entity-archetype-loader.cpp @@ -204,7 +204,7 @@ static bool load_component_model(entity::archetype& archetype, resource_manager& { handle.emplace_or_replace ( - std::make_unique(model), + std::make_shared(model), std::uint8_t{0b00000001} ); } @@ -242,7 +242,6 @@ static bool load_component_transform(entity::archetype& archetype, const json& e { ::transform_component component; component.local = math::transform::identity; - component.warp = true; if (element.contains("translation")) { diff --git a/src/game/menu.cpp b/src/game/menu.cpp index 3f5b09b..57c4ae6 100644 --- a/src/game/menu.cpp +++ b/src/game/menu.cpp @@ -72,16 +72,6 @@ void update_text_color(::game& ctx) } } -void update_text_tweens(::game& ctx) -{ - for (auto [name, value]: ctx.menu_item_texts) - { - name->update_tweens(); - if (value) - value->update_tweens(); - } -} - void align_text(::game& ctx, bool center, bool has_back, float anchor_y) { @@ -102,13 +92,13 @@ void align_text(::game& ctx, bool center, bool has_back, float anchor_y) float row_width = 0.0f; // Add name width to row width - const auto& name_bounds = static_cast&>(name->get_local_bounds()); + const auto& name_bounds = static_cast&>(name->get_bounds()); row_width += name_bounds.max_point.x() - name_bounds.min_point.x(); if (value) { // Add value width to row width - const auto& value_bounds = static_cast&>(value->get_local_bounds()); + const auto& value_bounds = static_cast&>(value->get_bounds()); row_width += value_bounds.max_point.x() - value_bounds.min_point.x(); // Add column spacing to row width @@ -143,7 +133,7 @@ void align_text(::game& ctx, bool center, bool has_back, float anchor_y) if (center || i == ctx.menu_item_texts.size() - 1) { - const auto& name_bounds = static_cast&>(name->get_local_bounds()); + const auto& name_bounds = static_cast&>(name->get_bounds()); const float name_width = name_bounds.max_point.x() - name_bounds.min_point.x(); x = viewport_center.x() - name_width * 0.5f; } @@ -152,7 +142,7 @@ void align_text(::game& ctx, bool center, bool has_back, float anchor_y) if (value) { - const auto& value_bounds = static_cast&>(value->get_local_bounds()); + const auto& value_bounds = static_cast&>(value->get_bounds()); const float value_width = value_bounds.max_point.x() - value_bounds.min_point.x(); if (center || i == ctx.menu_item_texts.size() - 1) @@ -179,9 +169,9 @@ void add_text_to_ui(::game& ctx) { for (auto [name, value]: ctx.menu_item_texts) { - ctx.ui_scene->add_object(name); + ctx.ui_scene->add_object(*name); if (value) - ctx.ui_scene->add_object(value); + ctx.ui_scene->add_object(*value); } } @@ -189,9 +179,9 @@ void remove_text_from_ui(::game& ctx) { for (auto [name, value]: ctx.menu_item_texts) { - ctx.ui_scene->remove_object(name); + ctx.ui_scene->remove_object(*name); if (value) - ctx.ui_scene->remove_object(value); + ctx.ui_scene->remove_object(*value); } } @@ -261,12 +251,10 @@ void fade_in(::game& ctx, const std::function& end_callback) if (name) { name->set_color(color); - name->update_tweens(); } if (value) { value->set_color(color); - value->update_tweens(); } } diff --git a/src/game/menu.hpp b/src/game/menu.hpp index a95bc5a..fcf8c5f 100644 --- a/src/game/menu.hpp +++ b/src/game/menu.hpp @@ -42,7 +42,6 @@ void fade_out_bg(::game& ctx); void update_text_color(::game& ctx); void update_text_font(::game& ctx); -void update_text_tweens(::game& ctx); void align_text(::game& ctx, bool center = false, bool has_back = true, float anchor_y = 0.0f); void refresh_text(::game& ctx); void add_text_to_ui(::game& ctx); diff --git a/src/game/spawn.cpp b/src/game/spawn.cpp index 4e69527..374268c 100644 --- a/src/game/spawn.cpp +++ b/src/game/spawn.cpp @@ -20,7 +20,7 @@ #include "game/spawn.hpp" #include "game/components/transform-component.hpp" #include "game/components/scene-component.hpp" - +#include entity::id spawn_ant_egg(::game& ctx, const ant_genome& genome, bool fertilized, const float3& position) { @@ -32,7 +32,6 @@ entity::id spawn_ant_egg(::game& ctx, const ant_genome& genome, bool fertilized, transform_component.local = math::transform::identity; transform_component.local.translation = position; transform_component.world = transform_component.local; - transform_component.warp = true; ctx.entity_registry->emplace<::transform_component>(egg_eid, transform_component); // Construct scene component @@ -51,7 +50,6 @@ entity::id spawn_ant_larva(::game& ctx, const ant_genome& genome, const float3& transform_component.local = math::transform::identity; transform_component.local.translation = position; transform_component.world = transform_component.local; - transform_component.warp = true; ctx.entity_registry->emplace<::transform_component>(larva_eid, transform_component); // Construct scene component diff --git a/src/game/states/collection-menu-state.cpp b/src/game/states/collection-menu-state.cpp index 7e14e1e..b21581c 100644 --- a/src/game/states/collection-menu-state.cpp +++ b/src/game/states/collection-menu-state.cpp @@ -45,7 +45,6 @@ collection_menu_state::collection_menu_state(::game& ctx): box_material->set_blend_mode(render::material_blend_mode::translucent); box_material->set_shader_template(ctx.resource_manager->load("ui-element-untextured.glsl")); box_material->set_variable("tint", std::make_shared(1, float4{0.5f, 0.5f, 0.5f, 1})); - //box_material.update_tweens(); // Construct box billboard box_billboard.set_material(box_material); @@ -55,14 +54,13 @@ collection_menu_state::collection_menu_state(::game& ctx): selection_material->set_blend_mode(render::material_blend_mode::translucent); selection_material->set_shader_template(ctx.resource_manager->load("ui-element-untextured.glsl")); box_material->set_variable("tint", std::make_shared(1, float4{1, 1, 1, 1})); - //selection_material.update_tweens(); // Construct selection billboard selection_billboard.set_material(selection_material); // Add box and selection billboard to UI scene - ctx.ui_scene->add_object(&box_billboard); - ctx.ui_scene->add_object(&selection_billboard); + ctx.ui_scene->add_object(box_billboard); + ctx.ui_scene->add_object(selection_billboard); row_count = 64; column_count = 6; @@ -107,7 +105,6 @@ collection_menu_state::collection_menu_state(::game& ctx): 0.0f } ); - selection_billboard.update_tweens(); debug::log::debug("selected colony: ({}, {})", selected_column, selected_row); } @@ -161,7 +158,6 @@ void collection_menu_state::resize_box() // Resize box box_billboard.set_scale({box_size.x() * 0.5f, box_size.y() * 0.5f, 1.0f}); box_billboard.set_translation({box_center.x(), box_center.y(), -1.0f}); - box_billboard.update_tweens(); // Resize selection selection_billboard.set_scale({selection_size * 0.5f, selection_size * 0.5f, 1.0f}); @@ -173,5 +169,4 @@ void collection_menu_state::resize_box() 0.0f } ); - selection_billboard.update_tweens(); } diff --git a/src/game/states/controls-menu-state.cpp b/src/game/states/controls-menu-state.cpp index 195a181..0523bf0 100644 --- a/src/game/states/controls-menu-state.cpp +++ b/src/game/states/controls-menu-state.cpp @@ -56,7 +56,6 @@ controls_menu_state::controls_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx, true); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); diff --git a/src/game/states/credits-state.cpp b/src/game/states/credits-state.cpp index 3393fe4..cdc1afb 100644 --- a/src/game/states/credits-state.cpp +++ b/src/game/states/credits-state.cpp @@ -46,11 +46,10 @@ credits_state::credits_state(::game& ctx): credits_text.set_content(get_string(ctx, "credits")); // Align credits text - const auto& credits_aabb = static_cast&>(credits_text.get_local_bounds()); + const auto& credits_aabb = static_cast&>(credits_text.get_bounds()); float credits_w = credits_aabb.max_point.x() - credits_aabb.min_point.x(); float credits_h = credits_aabb.max_point.y() - credits_aabb.min_point.y(); credits_text.set_translation({std::round(viewport_center.x() - credits_w * 0.5f), std::round(viewport_center.y() - credits_h * 0.5f), 0.0f}); - credits_text.update_tweens(); // Set up animation timing configuration const float credits_fade_in_duration = 0.5; @@ -81,11 +80,10 @@ credits_state::credits_state(::game& ctx): { const vec2 viewport_size = vec2(event.window->get_viewport_size()); const vec2 viewport_center = viewport_size * 0.5f; - const auto& credits_aabb = static_cast&>(credits_text.get_local_bounds()); + const auto& credits_aabb = static_cast&>(credits_text.get_bounds()); float credits_w = credits_aabb.max_point.x() - credits_aabb.min_point.x(); float credits_h = credits_aabb.max_point.y() - credits_aabb.min_point.y(); credits_text.set_translation({std::round(viewport_center.x() - credits_w * 0.5f), std::round(viewport_center.y() - credits_h * 0.5f), 0.0f}); - credits_text.update_tweens(); } ); @@ -135,7 +133,7 @@ credits_state::credits_state(::game& ctx): } ); - ctx.ui_scene->add_object(&credits_text); + ctx.ui_scene->add_object(credits_text); debug::log::trace("Entered credits state"); } @@ -149,7 +147,7 @@ credits_state::~credits_state() input_mapped_subscriptions.clear(); // Destruct credits text - ctx.ui_scene->remove_object(&credits_text); + ctx.ui_scene->remove_object(credits_text); // Destruct credits animations ctx.animator->remove_animation(&credits_fade_in_animation); diff --git a/src/game/states/extras-menu-state.cpp b/src/game/states/extras-menu-state.cpp index 370d175..3f1ffb2 100644 --- a/src/game/states/extras-menu-state.cpp +++ b/src/game/states/extras-menu-state.cpp @@ -53,7 +53,6 @@ extras_menu_state::extras_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); diff --git a/src/game/states/gamepad-config-menu-state.cpp b/src/game/states/gamepad-config-menu-state.cpp index 61498f4..f9418a6 100644 --- a/src/game/states/gamepad-config-menu-state.cpp +++ b/src/game/states/gamepad-config-menu-state.cpp @@ -62,7 +62,6 @@ gamepad_config_menu_state::gamepad_config_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); @@ -317,7 +316,6 @@ void gamepad_config_menu_state::add_control_item(input::action_map& action_map, // Update control mapping text value_text->set_content(this->get_mapping_string(*action_map, *control)); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); // Queue disabling of input mapper re-enabling of menu controls ctx.function_queue.push @@ -336,7 +334,6 @@ void gamepad_config_menu_state::add_control_item(input::action_map& action_map, // Set control mapping text to "..." value_text->set_content(get_string(ctx, "control_mapping")); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); // Setup input mapped callbacks gamepad_axis_mapped_subscription = ctx.input_mapper.get_gamepad_axis_mapped_channel().subscribe diff --git a/src/game/states/graphics-menu-state.cpp b/src/game/states/graphics-menu-state.cpp index 9ee9b33..52215a0 100644 --- a/src/game/states/graphics-menu-state.cpp +++ b/src/game/states/graphics-menu-state.cpp @@ -77,7 +77,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); @@ -90,7 +89,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); // Update fullscreen settings (*ctx.settings)["fullscreen"] = fullscreen; @@ -117,7 +115,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): // Update text this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto decrease_resolution_callback = [this, &ctx]() @@ -141,7 +138,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): // Update text this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto toggle_v_sync_callback = [this, &ctx]() @@ -155,7 +151,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto next_aa_method_callback = [this, &ctx]() @@ -182,7 +177,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): // Refresh and realign text ::menu::refresh_text(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto previous_aa_method_callback = [this, &ctx]() @@ -209,7 +203,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): // Refresh and realign text ::menu::refresh_text(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto increase_font_scale_callback = [this, &ctx]() @@ -238,7 +231,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): // Refresh and realign text ::menu::refresh_text(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto decrease_font_scale_callback = [this, &ctx]() @@ -267,7 +259,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): // Refresh and realign text ::menu::refresh_text(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto toggle_dyslexia_font_callback = [this, &ctx]() @@ -288,7 +279,6 @@ graphics_menu_state::graphics_menu_state(::game& ctx): // Refresh and realign text ::menu::refresh_text(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto select_back_callback = [&ctx]() { diff --git a/src/game/states/keyboard-config-menu-state.cpp b/src/game/states/keyboard-config-menu-state.cpp index 6662a69..356293e 100644 --- a/src/game/states/keyboard-config-menu-state.cpp +++ b/src/game/states/keyboard-config-menu-state.cpp @@ -62,7 +62,6 @@ keyboard_config_menu_state::keyboard_config_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); @@ -241,7 +240,6 @@ void keyboard_config_menu_state::add_control_item(input::action_map& action_map, // Update control mapping text value_text->set_content(this->get_mapping_string(*action_map, *control)); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); // Queue disabling of input mapper re-enabling of menu controls ctx.function_queue.push @@ -260,7 +258,6 @@ void keyboard_config_menu_state::add_control_item(input::action_map& action_map, // Set control mapping text to "..." value_text->set_content(get_string(ctx, "control_mapping")); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); // Setup input mapped callbacks key_mapped_subscription = ctx.input_mapper.get_key_mapped_channel().subscribe diff --git a/src/game/states/language-menu-state.cpp b/src/game/states/language-menu-state.cpp index 5eafa81..ef6a068 100644 --- a/src/game/states/language-menu-state.cpp +++ b/src/game/states/language-menu-state.cpp @@ -73,7 +73,6 @@ language_menu_state::language_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); @@ -114,7 +113,6 @@ language_menu_state::language_menu_state(::game& ctx): this->update_text_content(); ::menu::refresh_text(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; // Construct menu item callbacks diff --git a/src/game/states/main-menu-state.cpp b/src/game/states/main-menu-state.cpp index fc6c243..02d2b15 100644 --- a/src/game/states/main-menu-state.cpp +++ b/src/game/states/main-menu-state.cpp @@ -65,14 +65,13 @@ main_menu_state::main_menu_state(::game& ctx, bool fade_in): title_text->set_color({1.0f, 1.0f, 1.0f, (fade_in) ? 1.0f : 0.0f}); title_text->set_font(&ctx.title_font); title_text->set_content(get_string(ctx, "title_antkeeper")); - const auto& title_aabb = static_cast&>(title_text->get_local_bounds()); + const auto& title_aabb = static_cast&>(title_text->get_bounds()); float title_w = title_aabb.max_point.x() - title_aabb.min_point.x(); float title_h = title_aabb.max_point.y() - title_aabb.min_point.y(); title_text->set_translation({std::round(viewport_center.x() - title_w * 0.5f), std::round(viewport_center.y() - title_h * 0.5f + (viewport_size.y() / 3.0f) / 2.0f), 0.0f}); - title_text->update_tweens(); // Add text to UI - ctx.ui_scene->add_object(title_text.get()); + ctx.ui_scene->add_object(*title_text); // Construct title fade animation title_fade_animation.set_interpolator(ease::out_cubic); @@ -112,7 +111,6 @@ main_menu_state::main_menu_state(::game& ctx, bool fade_in): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx, true, false, (-viewport_size.y() / 3.0f) / 2.0f); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); @@ -266,14 +264,13 @@ main_menu_state::main_menu_state(::game& ctx, bool fade_in): ctx.surface_camera->set_active(true); const float ev100_sunny16 = physics::light::ev::from_settings(16.0f, 1.0f / 100.0f, 100.0f); - ctx.surface_camera->set_exposure(ev100_sunny16); + ctx.surface_camera->set_exposure_value(ev100_sunny16); const float aspect_ratio = viewport_size.x() / viewport_size.y(); float fov = math::vertical_fov(math::radians(100.0f), aspect_ratio); ctx.surface_camera->look_at({0, 2.0f, 0}, {0, 0, 0}, {0, 0, 1}); ctx.surface_camera->set_perspective(fov, ctx.surface_camera->get_aspect_ratio(), ctx.surface_camera->get_clip_near(), ctx.surface_camera->get_clip_far()); - ctx.surface_camera->update_tweens(); // Setup and enable sky and ground passes ctx.sky_pass->set_enabled(true); @@ -291,11 +288,10 @@ main_menu_state::main_menu_state(::game& ctx, bool fade_in): const vec2 viewport_center = viewport_size * 0.5f; // Re-align title text - const auto& title_aabb = static_cast&>(title_text->get_local_bounds()); + const auto& title_aabb = static_cast&>(title_text->get_bounds()); float title_w = title_aabb.max_point.x() - title_aabb.min_point.x(); float title_h = title_aabb.max_point.y() - title_aabb.min_point.y(); title_text->set_translation({std::round(viewport_center.x() - title_w * 0.5f), std::round(viewport_center.y() - title_h * 0.5f + (viewport_size.y() / 3.0f) / 2.0f), 0.0f}); - title_text->update_tweens(); ::menu::align_text(ctx, true, false, (-viewport_size.y() / 3.0f) / 2.0f); } @@ -325,7 +321,7 @@ main_menu_state::~main_menu_state() ctx.animator->remove_animation(&title_fade_animation); // Destruct text - ctx.ui_scene->remove_object(title_text.get()); + ctx.ui_scene->remove_object(*title_text); debug::log::trace("Exited main menu state"); } diff --git a/src/game/states/nest-selection-state.cpp b/src/game/states/nest-selection-state.cpp index 4c1e83e..9a146e0 100644 --- a/src/game/states/nest-selection-state.cpp +++ b/src/game/states/nest-selection-state.cpp @@ -23,7 +23,6 @@ #include "game/ant/ant-phenome.hpp" #include "game/commands/commands.hpp" #include "game/components/collision-component.hpp" -#include "game/components/camera-component.hpp" #include "game/components/constraint-stack-component.hpp" #include "game/components/scene-component.hpp" #include "game/components/picking-component.hpp" @@ -72,6 +71,7 @@ #include #include #include +#include nest_selection_state::nest_selection_state(::game& ctx): game_state(ctx) @@ -132,7 +132,6 @@ nest_selection_state::nest_selection_state(::game& ctx): worker_transform_component.local = math::transform::identity; worker_transform_component.local.translation = {0, 0.5f, -4}; worker_transform_component.world = worker_transform_component.local; - worker_transform_component.warp = true; ctx.entity_registry->emplace(worker_ant_eid, worker_transform_component); ctx.entity_registry->emplace(worker_ant_eid, std::make_unique(worker_model), std::uint8_t{1}); @@ -163,7 +162,7 @@ nest_selection_state::nest_selection_state(::game& ctx): // Set camera exposure const float ev100_sunny16 = physics::light::ev::from_settings(16.0f, 1.0f / 100.0f, 100.0f); - ctx.surface_camera->set_exposure(ev100_sunny16); + ctx.surface_camera->set_exposure_value(ev100_sunny16); const auto& viewport_size = ctx.window->get_viewport_size(); const float aspect_ratio = static_cast(viewport_size[0]) / static_cast(viewport_size[1]); @@ -274,72 +273,18 @@ nest_selection_state::~nest_selection_state() void nest_selection_state::create_first_person_camera_rig() { - // Construct first person camera rig track to constraint - track_to_constraint first_person_camera_rig_track_to; - first_person_camera_rig_track_to.target = worker_ant_eid; - first_person_camera_rig_track_to.up = {0.0f, 1.0f, 0.0f}; - - constraint_stack_node_component first_person_camera_rig_track_to_node; - first_person_camera_rig_track_to_node.active = false; - first_person_camera_rig_track_to_node.weight = 1.0f; - first_person_camera_rig_track_to_node.next = entt::null; - first_person_camera_rig_track_to_eid = ctx.entity_registry->create(); - ctx.entity_registry->emplace(first_person_camera_rig_track_to_eid, first_person_camera_rig_track_to); - ctx.entity_registry->emplace(first_person_camera_rig_track_to_eid, first_person_camera_rig_track_to_node); - - // Construct first person camera rig spring rotation constraint - spring_rotation_constraint first_person_camera_rig_spring_rotation; - first_person_camera_rig_spring_rotation.spring = - { - {0.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 0.0f}, - 1.0f, - first_person_camera_rig_rotation_spring_angular_frequency - }; - constraint_stack_node_component first_person_camera_rig_spring_rotation_node; - first_person_camera_rig_spring_rotation_node.active = false; - first_person_camera_rig_spring_rotation_node.weight = 1.0f; - first_person_camera_rig_spring_rotation_node.next = first_person_camera_rig_track_to_eid; - first_person_camera_rig_spring_rotation_eid = ctx.entity_registry->create(); - ctx.entity_registry->emplace(first_person_camera_rig_spring_rotation_eid, first_person_camera_rig_spring_rotation); - ctx.entity_registry->emplace(first_person_camera_rig_spring_rotation_eid, first_person_camera_rig_spring_rotation_node); - - // Construct first person camera rig spring translation constraint - spring_translation_constraint first_person_camera_rig_spring_translation; - first_person_camera_rig_spring_translation.spring = - { - {0.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 0.0f}, - 1.0f, - first_person_camera_rig_translation_spring_angular_frequency - }; - constraint_stack_node_component first_person_camera_rig_spring_translation_node; - first_person_camera_rig_spring_translation_node.active = false; - first_person_camera_rig_spring_translation_node.weight = 1.0f; - first_person_camera_rig_spring_translation_node.next = first_person_camera_rig_spring_rotation_eid; - first_person_camera_rig_spring_translation_eid = ctx.entity_registry->create(); - ctx.entity_registry->emplace(first_person_camera_rig_spring_translation_eid, first_person_camera_rig_spring_translation); - ctx.entity_registry->emplace(first_person_camera_rig_spring_translation_eid, first_person_camera_rig_spring_translation_node); - - // Construct first person camera rig constraint stack - constraint_stack_component first_person_camera_rig_constraint_stack; - first_person_camera_rig_constraint_stack.priority = 2; - first_person_camera_rig_constraint_stack.head = first_person_camera_rig_spring_translation_eid; - // Construct first person camera rig transform component transform_component first_person_camera_rig_transform; first_person_camera_rig_transform.local = math::transform::identity; first_person_camera_rig_transform.local.translation = {0, 10, 0}; first_person_camera_rig_transform.world = first_person_camera_rig_transform.local; - first_person_camera_rig_transform.warp = true; // Construct first person camera rig locomotion component winged_locomotion_component first_person_camera_rig_locomotion; // Construct first person camera rig physics component auto first_person_camera_rig_body = std::make_unique(); + first_person_camera_rig_body->set_position({0, 10, 0}); first_person_camera_rig_body->set_mass(1.0f); first_person_camera_rig_body->set_linear_damping(10.0f); first_person_camera_rig_body->set_angular_damping(0.5f); @@ -352,127 +297,102 @@ void nest_selection_state::create_first_person_camera_rig() first_person_camera_rig_collider->set_material(std::move(camera_collider_material)); first_person_camera_rig_body->set_collider(std::move(first_person_camera_rig_collider)); - // Construct first person camera rig camera component - camera_component first_person_camera_rig_camera; - first_person_camera_rig_camera.object = ctx.surface_camera.get(); + // Construct first person camera rig scene component + scene_component first_person_camera_rig_camera; + first_person_camera_rig_camera.object = ctx.surface_camera; // Construct first person camera rig entity first_person_camera_rig_eid = ctx.entity_registry->create(); - ctx.entity_registry->emplace(first_person_camera_rig_eid, first_person_camera_rig_camera); + ctx.entity_registry->emplace(first_person_camera_rig_eid, first_person_camera_rig_camera); ctx.entity_registry->emplace(first_person_camera_rig_eid, first_person_camera_rig_transform); ctx.entity_registry->emplace(first_person_camera_rig_eid, std::move(first_person_camera_rig_body)); ctx.entity_registry->emplace(first_person_camera_rig_eid, first_person_camera_rig_locomotion); - ctx.entity_registry->emplace(first_person_camera_rig_eid, first_person_camera_rig_constraint_stack); - - // Construct first person camera rig fov spring - spring1_component first_person_camera_rig_fov_spring; - first_person_camera_rig_fov_spring.spring = - { - 0.0f, - 0.0f, - 0.0f, - 1.0f, - first_person_camera_rig_fov_spring_angular_frequency - }; - first_person_camera_rig_fov_spring.callback = [&](float fov) - { - ctx.surface_camera->set_perspective(fov, ctx.surface_camera->get_aspect_ratio(), ctx.surface_camera->get_clip_near(), ctx.surface_camera->get_clip_far()); - }; - - // Construct first person camera rig fov spring entity - first_person_camera_rig_fov_spring_eid = ctx.entity_registry->create(); - ctx.entity_registry->emplace(first_person_camera_rig_fov_spring_eid, first_person_camera_rig_fov_spring); - - set_first_person_camera_rig_pedestal(first_person_camera_rig_pedestal); } void nest_selection_state::destroy_first_person_camera_rig() { ctx.entity_registry->destroy(first_person_camera_rig_eid); - ctx.entity_registry->destroy(first_person_camera_rig_spring_translation_eid); - ctx.entity_registry->destroy(first_person_camera_rig_spring_rotation_eid); - ctx.entity_registry->destroy(first_person_camera_rig_fov_spring_eid); } void nest_selection_state::set_first_person_camera_rig_pedestal(float pedestal) { - first_person_camera_rig_pedestal = pedestal; - const float elevation = math::log_lerp(first_person_camera_rig_min_elevation, first_person_camera_rig_max_elevation, first_person_camera_rig_pedestal); - const float fov = math::log_lerp(first_person_camera_near_fov, first_person_camera_far_fov, first_person_camera_rig_pedestal); - - ctx.entity_registry->patch - ( - first_person_camera_rig_spring_translation_eid, - [&](auto& component) - { - component.spring.x1[1] = elevation; - } - ); - - ctx.entity_registry->patch - ( - first_person_camera_rig_fov_spring_eid, - [&](auto& component) - { - component.spring.x1 = fov; - } - ); + // first_person_camera_rig_pedestal = pedestal; + // const float elevation = math::log_lerp(first_person_camera_rig_min_elevation, first_person_camera_rig_max_elevation, first_person_camera_rig_pedestal); + // const float fov = math::log_lerp(first_person_camera_near_fov, first_person_camera_far_fov, first_person_camera_rig_pedestal); + + // ctx.entity_registry->patch + // ( + // first_person_camera_rig_spring_translation_eid, + // [&](auto& component) + // { + // component.spring.x1[1] = elevation; + // } + // ); + + // ctx.entity_registry->patch + // ( + // first_person_camera_rig_fov_spring_eid, + // [&](auto& component) + // { + // component.spring.x1 = fov; + // } + // ); } void nest_selection_state::move_first_person_camera_rig(const float2& direction, float factor) { - const float speed = math::log_lerp(first_person_camera_near_speed, first_person_camera_far_speed, first_person_camera_rig_pedestal) * factor; - - const spring_rotation_constraint& first_person_camera_rig_spring_rotation = ctx.entity_registry->get(first_person_camera_rig_spring_rotation_eid); - - const math::quaternion yaw_rotation = math::angle_axis(first_person_camera_rig_spring_rotation.spring.x0[0], float3{0.0f, 1.0f, 0.0f}); - const float3 rotated_direction = math::normalize(yaw_rotation * float3{direction[0], 0.0f, direction[1]}); - const float3 velocity = rotated_direction * speed; - - ctx.entity_registry->patch - ( - first_person_camera_rig_spring_translation_eid, - [&](auto& component) - { - component.spring.x1 += velocity * static_cast(1.0 / ctx.fixed_update_rate); - } - ); + // const float speed = math::log_lerp(first_person_camera_near_speed, first_person_camera_far_speed, first_person_camera_rig_pedestal) * factor; + + // const spring_rotation_constraint& first_person_camera_rig_spring_rotation = ctx.entity_registry->get(first_person_camera_rig_spring_rotation_eid); + + // const math::quaternion yaw_rotation = math::angle_axis(first_person_camera_rig_spring_rotation.spring.x0[0], float3{0.0f, 1.0f, 0.0f}); + // const float3 rotated_direction = math::normalize(yaw_rotation * float3{direction[0], 0.0f, direction[1]}); + // const float3 velocity = rotated_direction * speed; + + // ctx.entity_registry->patch + // ( + // first_person_camera_rig_spring_translation_eid, + // [&](auto& component) + // { + // component.spring.x1 += velocity * static_cast(1.0 / ctx.fixed_update_rate); + // } + // ); } void nest_selection_state::satisfy_first_person_camera_rig_constraints() { // Satisfy first person camera rig spring translation constraint - ctx.entity_registry->patch - ( - first_person_camera_rig_spring_translation_eid, - [&](auto& component) - { - component.spring.x0 = component.spring.x1; - component.spring.v *= 0.0f; - } - ); + // ctx.entity_registry->patch + // ( + // first_person_camera_rig_spring_translation_eid, + // [&](auto& component) + // { + // component.spring.x0 = component.spring.x1; + // component.spring.v *= 0.0f; + // } + // ); // Satisfy first person camera rig spring rotation constraint - ctx.entity_registry->patch - ( - first_person_camera_rig_spring_rotation_eid, - [&](auto& component) - { - component.spring.x0 = component.spring.x1; - component.spring.v *= 0.0f; - } - ); + // ctx.entity_registry->patch + // ( + // first_person_camera_rig_spring_rotation_eid, + // [&](auto& component) + // { + // component.spring.x0 = component.spring.x1; + // component.spring.v *= 0.0f; + // } + // ); // Satisfy first person camera rig fov spring - ctx.entity_registry->patch - ( - first_person_camera_rig_fov_spring_eid, - [&](auto& component) - { - component.spring.x0 = component.spring.x1; - component.spring.v *= 0.0f; - } - ); + // ctx.entity_registry->patch + // ( + // first_person_camera_rig_fov_spring_eid, + // [&](auto& component) + // { + // component.spring.x0 = component.spring.x1; + // component.spring.v *= 0.0f; + // } + // ); } void nest_selection_state::setup_controls() @@ -522,12 +442,14 @@ void nest_selection_state::setup_controls() { const transform_component& first_person_camera_rig_transform = ctx.entity_registry->get(first_person_camera_rig_eid); - const spring_rotation_constraint& first_person_camera_rig_spring_rotation = ctx.entity_registry->get(first_person_camera_rig_spring_rotation_eid); + //const spring_rotation_constraint& first_person_camera_rig_spring_rotation = ctx.entity_registry->get(first_person_camera_rig_spring_rotation_eid); - const math::quaternion yaw_rotation = math::angle_axis(first_person_camera_rig_spring_rotation.spring.x0[0], float3{0.0f, 1.0f, 0.0f}); + //const math::quaternion yaw_rotation = math::angle_axis(first_person_camera_rig_spring_rotation.spring.x0[0], float3{0.0f, 1.0f, 0.0f}); //const float3 rotated_direction = yaw_rotation * float3{direction[0], 0.0f, direction[1]}; - const float3 rotated_direction = first_person_camera_rig_transform.world.rotation * float3{direction[0], 0.0f, direction[1]}; + const math::quaternion yaw_rotation = math::angle_axis(static_cast(first_person_camera_yaw), float3{0.0f, 1.0f, 0.0f}); + + const float3 rotated_direction = yaw_rotation * float3{direction[0], 0.0f, direction[1]}; const float3 force = rotated_direction * speed; @@ -578,13 +500,12 @@ void nest_selection_state::setup_controls() const math::quaternion pitch_rotation = math::angle_axis(first_person_camera_pitch, {-1.0, 0.0, 0.0}); const math::quaternion first_person_camera_orientation = math::quaternion(math::normalize(yaw_rotation * pitch_rotation)); - ctx.entity_registry->patch + ctx.entity_registry->patch ( first_person_camera_rig_eid, [&](auto& component) { component.object->set_rotation(first_person_camera_orientation); - component.object->update_tweens(); } ); @@ -593,6 +514,7 @@ void nest_selection_state::setup_controls() first_person_camera_rig_eid, [&](auto& component) { + component.body->set_previous_orientation(first_person_camera_orientation); component.body->set_orientation(first_person_camera_orientation); } ); @@ -752,16 +674,15 @@ void nest_selection_state::setup_controls() const auto& camera_transform = ctx.entity_registry->get(first_person_camera_rig_eid); scene_component projectile_scene; - projectile_scene.object = std::make_unique(ctx.resource_manager->load("sphere.mdl")); - //projectile_scene.object = std::make_unique(ctx.resource_manager->load("cube.mdl")); + projectile_scene.object = std::make_shared(ctx.resource_manager->load("sphere.mdl")); + //projectile_scene.object = std::make_shared(ctx.resource_manager->load("cube.mdl")); transform_component projectile_transform; projectile_transform.local = camera_transform.world; projectile_transform.world = projectile_transform.local; - projectile_transform.warp = true; auto projectile_body = std::make_unique(); - projectile_body->set_center_of_mass(camera_transform.world.translation); + projectile_body->set_position(camera_transform.world.translation); projectile_body->set_mass(0.1f); projectile_body->set_inertia(0.05f); projectile_body->set_angular_damping(0.5f); @@ -814,14 +735,7 @@ void nest_selection_state::setup_controls() ( [&](const auto& event) { - ctx.entity_registry->patch - ( - first_person_camera_rig_track_to_eid, - [&](auto& component) - { - component.active = false; - } - ); + } ) ); diff --git a/src/game/states/nest-selection-state.hpp b/src/game/states/nest-selection-state.hpp index 31b6f85..f055a2d 100644 --- a/src/game/states/nest-selection-state.hpp +++ b/src/game/states/nest-selection-state.hpp @@ -54,10 +54,6 @@ private: entity::id worker_ant_eid; entity::id first_person_camera_rig_eid; - entity::id first_person_camera_rig_spring_translation_eid; - entity::id first_person_camera_rig_spring_rotation_eid; - entity::id first_person_camera_rig_track_to_eid; - entity::id first_person_camera_rig_fov_spring_eid; float first_person_camera_rig_translation_spring_angular_frequency; float first_person_camera_rig_rotation_spring_angular_frequency; float first_person_camera_rig_fov_spring_angular_frequency; diff --git a/src/game/states/nuptial-flight-state.cpp b/src/game/states/nuptial-flight-state.cpp index 5a03670..2832f8c 100644 --- a/src/game/states/nuptial-flight-state.cpp +++ b/src/game/states/nuptial-flight-state.cpp @@ -29,12 +29,12 @@ #include "game/components/ant-caste-component.hpp" #include "game/components/transform-component.hpp" #include "game/components/terrain-component.hpp" -#include "game/components/camera-component.hpp" #include "game/components/name-component.hpp" #include "game/components/constraint-stack-component.hpp" #include "game/components/steering-component.hpp" #include "game/components/picking-component.hpp" #include "game/components/spring-component.hpp" +#include "game/components/scene-component.hpp" #include "game/constraints/child-of-constraint.hpp" #include "game/constraints/copy-rotation-constraint.hpp" #include "game/constraints/copy-scale-constraint.hpp" @@ -140,7 +140,7 @@ nuptial_flight_state::nuptial_flight_state(::game& ctx): // Set camera exposure const float ev100_sunny16 = physics::light::ev::from_settings(16.0f, 1.0f / 100.0f, 100.0f); - ctx.surface_camera->set_exposure(ev100_sunny16); + ctx.surface_camera->set_exposure_value(ev100_sunny16); const auto& viewport_size = ctx.window->get_viewport_size(); const float aspect_ratio = static_cast(viewport_size[0]) / static_cast(viewport_size[1]); @@ -163,14 +163,13 @@ nuptial_flight_state::nuptial_flight_state(::game& ctx): selection_text.set_material(ctx.menu_font_material); selection_text.set_color({1.0f, 1.0f, 1.0f, 1.0f}); selection_text.set_font(&ctx.menu_font); - const auto& text_aabb = static_cast&>(selection_text.get_local_bounds()); + const auto& text_aabb = static_cast&>(selection_text.get_bounds()); float text_w = text_aabb.max_point.x() - text_aabb.min_point.x(); float text_h = text_aabb.max_point.y() - text_aabb.min_point.y(); selection_text.set_translation({std::round(viewport_size.x() * 0.5f - text_w * 0.5f), std::round(ctx.menu_font.get_font_metrics().size), 0.0f}); - selection_text.update_tweens(); // Add text to UI - ctx.ui_scene->add_object(&selection_text); + ctx.ui_scene->add_object(selection_text); // Select random alate entity::id random_alate_eid; @@ -219,7 +218,7 @@ nuptial_flight_state::~nuptial_flight_state() ::disable_game_controls(ctx); // Remove text from UI - ctx.ui_scene->remove_object(&selection_text); + ctx.ui_scene->remove_object(selection_text); // Deselect selected entity select_entity(entt::null); @@ -257,7 +256,6 @@ void nuptial_flight_state::create_camera_rig() transform_component camera_rig_focus_transform; camera_rig_focus_transform.local = math::transform::identity; camera_rig_focus_transform.world = camera_rig_focus_transform.local; - camera_rig_focus_transform.warp = true; // Construct camera rig focus entity camera_rig_focus_eid = ctx.entity_registry->create(); @@ -339,15 +337,14 @@ void nuptial_flight_state::create_camera_rig() transform_component camera_rig_transform; camera_rig_transform.local = math::transform::identity; camera_rig_transform.world = camera_rig_transform.local; - camera_rig_transform.warp = true; // Construct camera rig camera component - camera_component camera_rig_camera; - camera_rig_camera.object = ctx.surface_camera.get(); + scene_component camera_rig_camera; + camera_rig_camera.object = ctx.surface_camera; // Construct camera rig entity camera_rig_eid = ctx.entity_registry->create(); - ctx.entity_registry->emplace(camera_rig_eid, camera_rig_camera); + ctx.entity_registry->emplace(camera_rig_eid, camera_rig_camera); ctx.entity_registry->emplace(camera_rig_eid, camera_rig_transform); ctx.entity_registry->emplace(camera_rig_eid, camera_rig_constraint_stack); @@ -1104,11 +1101,10 @@ void nuptial_flight_state::select_entity(entity::id entity_id) } const auto& viewport_size = ctx.window->get_viewport_size(); - const auto& text_aabb = static_cast&>(selection_text.get_local_bounds()); + const auto& text_aabb = static_cast&>(selection_text.get_bounds()); float text_w = text_aabb.max_point.x() - text_aabb.min_point.x(); float text_h = text_aabb.max_point.y() - text_aabb.min_point.y(); selection_text.set_translation({std::round(viewport_size.x() * 0.5f - text_w * 0.5f), std::round(ctx.menu_font.get_font_metrics().size), 0.0f}); - selection_text.update_tweens(); } } } diff --git a/src/game/states/options-menu-state.cpp b/src/game/states/options-menu-state.cpp index 34b30d9..d22a1c8 100644 --- a/src/game/states/options-menu-state.cpp +++ b/src/game/states/options-menu-state.cpp @@ -68,7 +68,6 @@ options_menu_state::options_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx, true); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); diff --git a/src/game/states/pause-menu-state.cpp b/src/game/states/pause-menu-state.cpp index 27bc6ea..b87bcd4 100644 --- a/src/game/states/pause-menu-state.cpp +++ b/src/game/states/pause-menu-state.cpp @@ -64,7 +64,6 @@ pause_menu_state::pause_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx, true, false); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); diff --git a/src/game/states/sound-menu-state.cpp b/src/game/states/sound-menu-state.cpp index ee521f2..3251fd0 100644 --- a/src/game/states/sound-menu-state.cpp +++ b/src/game/states/sound-menu-state.cpp @@ -74,7 +74,6 @@ sound_menu_state::sound_menu_state(::game& ctx): ::menu::update_text_color(ctx); ::menu::update_text_font(ctx); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); ::menu::add_text_to_ui(ctx); ::menu::setup_animations(ctx); @@ -93,7 +92,6 @@ sound_menu_state::sound_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto decrease_volume_callback = [this, &ctx](float* volume) { @@ -109,7 +107,6 @@ sound_menu_state::sound_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto toggle_mono_audio_callback = [this, &ctx]() @@ -118,7 +115,6 @@ sound_menu_state::sound_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto toggle_captions_callback = [this, &ctx]() @@ -127,7 +123,6 @@ sound_menu_state::sound_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto increase_captions_size_callback = [this, &ctx]() @@ -144,7 +139,6 @@ sound_menu_state::sound_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto decrease_captions_size_callback = [this, &ctx]() @@ -161,7 +155,6 @@ sound_menu_state::sound_menu_state(::game& ctx): this->update_value_text_content(); ::menu::align_text(ctx); - ::menu::update_text_tweens(ctx); }; auto select_back_callback = [&ctx]() { diff --git a/src/game/states/splash-state.cpp b/src/game/states/splash-state.cpp index c197340..0f4855d 100644 --- a/src/game/states/splash-state.cpp +++ b/src/game/states/splash-state.cpp @@ -58,16 +58,14 @@ splash_state::splash_state(::game& ctx): auto splash_tint = std::make_shared(1, float4{1, 1, 1, 0}); splash_billboard_material->set_variable("tint", splash_tint); - //splash_billboard_material.update_tweens(); // Construct splash billboard splash_billboard.set_material(splash_billboard_material); splash_billboard.set_scale({static_cast(std::get<0>(splash_dimensions)) * 0.5f, static_cast(std::get<1>(splash_dimensions)) * 0.5f, 1.0f}); splash_billboard.set_translation({std::round(viewport_center.x()), std::round(viewport_center.y()), 0.0f}); - splash_billboard.update_tweens(); // Add splash billboard to UI scene - ctx.ui_scene->add_object(&splash_billboard); + ctx.ui_scene->add_object(splash_billboard); // Load animation timing configuration const float splash_fade_in_duration = 0.5; @@ -136,7 +134,6 @@ splash_state::splash_state(::game& ctx): const vec2 viewport_size = vec2(event.window->get_viewport_size()); const vec2 viewport_center = viewport_size * 0.5f; splash_billboard.set_translation({std::round(viewport_center.x()), std::round(viewport_center.y()), 0.0f}); - splash_billboard.update_tweens(); } ); @@ -207,7 +204,7 @@ splash_state::~splash_state() ctx.animator->remove_animation(&splash_fade_out_animation); // Remove splash billboard from UI scene - ctx.ui_scene->remove_object(&splash_billboard); + ctx.ui_scene->remove_object(splash_billboard); // Disable color buffer clearing in UI pass ctx.ui_clear_pass->set_cleared_buffers(false, true, false); diff --git a/src/game/systems/astronomy-system.cpp b/src/game/systems/astronomy-system.cpp index 9a44864..98aaf28 100644 --- a/src/game/systems/astronomy-system.cpp +++ b/src/game/systems/astronomy-system.cpp @@ -206,7 +206,7 @@ void astronomy_system::update(float t, float dt) ) ); - sun_light->set_color(float3(observer_blackbody_transmitted_illuminance)); + sun_light->set_illuminance(float3(observer_blackbody_transmitted_illuminance)); // Bounce sun light bounce_illuminance += std::max(0.0, math::dot(bounce_normal, -observer_blackbody_direction_eus)) * observer_blackbody_transmitted_illuminance * bounce_albedo; @@ -226,7 +226,7 @@ void astronomy_system::update(float t, float dt) sky_light_illuminance += starlight_illuminance; // Update sky light - sky_light->set_color(float3(sky_light_illuminance)); + sky_light->set_illuminance(float3(sky_light_illuminance)); // Bounce sky light bounce_illuminance += sky_light_illuminance * bounce_albedo; @@ -314,7 +314,7 @@ void astronomy_system::update(float t, float dt) { const float3 reflector_up_eus = float3(icrf_to_eus.r * double3{0, 0, 1}); - this->moon_light->set_color(float3(observer_reflector_illuminance)); + this->moon_light->set_illuminance(float3(observer_reflector_illuminance)); this->moon_light->set_rotation ( math::look_rotation @@ -332,7 +332,7 @@ void astronomy_system::update(float t, float dt) if (bounce_light) { - bounce_light->set_color(float3(bounce_illuminance)); + bounce_light->set_illuminance(float3(bounce_illuminance)); } } diff --git a/src/game/systems/physics-system.cpp b/src/game/systems/physics-system.cpp index f28078a..a054af3 100644 --- a/src/game/systems/physics-system.cpp +++ b/src/game/systems/physics-system.cpp @@ -22,6 +22,7 @@ #include "game/components/rigid-body-component.hpp" #include "game/components/rigid-body-constraint-component.hpp" #include "game/components/transform-component.hpp" +#include "game/components/scene-component.hpp" #include #include #include @@ -77,33 +78,15 @@ physics_system::physics_system(entity::registry& registry): void physics_system::update(float t, float dt) { - /// Update rigid body transforms - auto transform_view = registry.view(); - std::for_each - ( - std::execution::par_unseq, - transform_view.begin(), - transform_view.end(), - [&](auto entity_id) - { - auto& body = *(transform_view.get(entity_id).body); - auto& transform = transform_view.get(entity_id); - - // Update body center of mass and orientation - body.set_center_of_mass(transform.local.translation); - body.set_orientation(transform.local.rotation); - } - ); - detect_collisions_broad(); detect_collisions_narrow(); solve_constraints(dt); resolve_collisions(); - integrate_forces(dt); - integrate_velocities(dt); + integrate(dt); correct_positions(); // Update transform component transforms + auto transform_view = registry.view(); for (const auto entity_id: transform_view) { const auto& body = *(transform_view.get(entity_id).body); @@ -115,14 +98,32 @@ void physics_system::update(float t, float dt) [&, dt](auto& transform) { // Integrate position - transform.local.translation = body.get_center_of_mass(); - transform.local.rotation = body.get_orientation(); + transform.local = body.get_transform(); } ); } } -void physics_system::integrate_forces(float dt) +void physics_system::interpolate(float alpha) +{ + // Interpolate rigid body states + auto view = registry.view(); + std::for_each + ( + std::execution::par_unseq, + view.begin(), + view.end(), + [&, alpha](auto entity_id) + { + const auto& rigid_body = *(view.get(entity_id).body); + auto& scene_object = *(view.get(entity_id).object); + + scene_object.set_transform(rigid_body.interpolate(alpha)); + } + ); +} + +void physics_system::integrate(float dt) { // Drag /* @@ -152,24 +153,7 @@ void physics_system::integrate_forces(float dt) // Apply gravity body.apply_central_force(gravity / 10.0f * body.get_mass()); - body.integrate_forces(dt); - } - ); -} - -void physics_system::integrate_velocities(float dt) -{ - auto view = registry.view(); - std::for_each - ( - std::execution::par_unseq, - view.begin(), - view.end(), - [&](auto entity_id) - { - auto& body = *(view.get(entity_id).body); - - body.integrate_velocities(dt); + body.integrate(dt); } ); } @@ -312,8 +296,8 @@ void physics_system::resolve_collisions() { const physics::collision_contact& contact = manifold.contacts[i]; - const math::vector radius_a = contact.point - body_a.get_center_of_mass(); - const math::vector radius_b = contact.point - body_b.get_center_of_mass(); + const math::vector radius_a = contact.point - body_a.get_position(); + const math::vector radius_b = contact.point - body_b.get_position(); math::vector relative_velocity = body_b.get_point_velocity(radius_b) - body_a.get_point_velocity(radius_a); @@ -391,8 +375,8 @@ void physics_system::correct_positions() math::vector correction = contact.normal * (std::max(0.0f, contact.depth - depth_threshold) / sum_inverse_mass) * correction_factor; - body_a.set_center_of_mass(body_a.get_center_of_mass() - correction * body_a.get_inverse_mass()); - body_b.set_center_of_mass(body_b.get_center_of_mass() + correction * body_b.get_inverse_mass()); + body_a.set_position(body_a.get_position() - correction * body_a.get_inverse_mass()); + body_b.set_position(body_b.get_position() + correction * body_b.get_inverse_mass()); } } } @@ -409,9 +393,9 @@ void physics_system::narrow_phase_plane_sphere(physics::rigid_body& body_a, phys // Transform plane into world-space const math::vector plane_normal = body_a.get_orientation() * plane_a.get_normal(); - const float plane_constant = plane_a.get_constant() - math::dot(plane_normal, body_a.get_center_of_mass()); + const float plane_constant = plane_a.get_constant() - math::dot(plane_normal, body_a.get_position()); - const float signed_distance = math::dot(plane_normal, body_b.get_center_of_mass()) + plane_constant; + const float signed_distance = math::dot(plane_normal, body_b.get_position()) + plane_constant; if (signed_distance > sphere_b.get_radius()) { return; @@ -425,7 +409,7 @@ void physics_system::narrow_phase_plane_sphere(physics::rigid_body& body_a, phys // Generate collision contact auto& contact = manifold.contacts[0]; - contact.point = body_b.get_center_of_mass() - plane_normal * sphere_b.get_radius(); + contact.point = body_b.get_position() - plane_normal * sphere_b.get_radius(); contact.normal = plane_normal * -normal_sign; contact.depth = std::abs(signed_distance - sphere_b.get_radius()); @@ -439,7 +423,7 @@ void physics_system::narrow_phase_plane_box(physics::rigid_body& body_a, physics // Transform plane into world-space const math::vector plane_normal = body_a.get_orientation() * plane_a.get_normal(); - const float plane_constant = plane_a.get_constant() - math::dot(plane_normal, body_a.get_center_of_mass()); + const float plane_constant = plane_a.get_constant() - math::dot(plane_normal, body_a.get_position()); const auto& box_min = box_b.get_min(); const auto& box_max = box_b.get_max(); @@ -463,7 +447,7 @@ void physics_system::narrow_phase_plane_box(physics::rigid_body& body_a, physics for (std::size_t i = 0; i < 8; ++i) { // Transform corner into world-space - const math::vector point = body_b.get_center_of_mass() + body_b.get_orientation() * corners[i]; + const math::vector point = body_b.get_transform() * corners[i]; const float signed_distance = math::dot(plane_normal, point) + plane_constant; @@ -504,7 +488,7 @@ void physics_system::narrow_phase_sphere_sphere(physics::rigid_body& body_a, phy const float sum_radii = sphere_a.get_radius() + sphere_b.get_radius(); const float sqr_sum_radii = sum_radii * sum_radii; - const math::vector difference = body_b.get_center_of_mass() - body_a.get_center_of_mass(); + const math::vector difference = body_b.get_position() - body_a.get_position(); const float sqr_distance = math::dot(difference, difference); if (sqr_distance > sqr_sum_radii) @@ -531,7 +515,7 @@ void physics_system::narrow_phase_sphere_sphere(physics::rigid_body& body_a, phy contact.normal = {1.0f, 0.0f, 0.0f}; contact.depth = sum_radii; } - contact.point = body_a.get_center_of_mass() + contact.normal * sphere_a.get_radius(); + contact.point = body_a.get_position() + contact.normal * sphere_a.get_radius(); narrow_phase_manifolds.emplace_back(std::move(manifold)); } diff --git a/src/game/systems/physics-system.hpp b/src/game/systems/physics-system.hpp index e97078f..9f9c39c 100644 --- a/src/game/systems/physics-system.hpp +++ b/src/game/systems/physics-system.hpp @@ -38,6 +38,8 @@ public: explicit physics_system(entity::registry& registry); void update(float t, float dt) override; + void interpolate(float alpha); + /** * Sets the gravity vector. * @@ -51,8 +53,7 @@ public: private: using collision_manifold_type = physics::collision_manifold<4>; - void integrate_forces(float dt); - void integrate_velocities(float dt); + void integrate(float dt); void solve_constraints(float dt); diff --git a/src/game/systems/render-system.cpp b/src/game/systems/render-system.cpp index b4ca201..4a35758 100644 --- a/src/game/systems/render-system.cpp +++ b/src/game/systems/render-system.cpp @@ -19,7 +19,6 @@ #include "game/systems/render-system.hpp" #include "game/components/transform-component.hpp" -#include "game/components/camera-component.hpp" #include #include @@ -63,30 +62,9 @@ void render_system::update(float t, float dt) // WARNING: could potentially lead to multithreading issues with scene::object_base::transformed() scene.object->set_transform(transform.world); - - if (transform.warp) - { - scene.object->get_transform_tween().update(); - transform.warp = false; - } } ); updated_scene_transforms.clear(); - - // Update camera transforms - registry.view().each - ( - [this](entity::id entity_id, auto& transform, auto& camera) - { - camera.object->set_transform(transform.world); - if (transform.warp) - { - camera.object->get_transform_tween().update(); - camera.object->update_tweens(); - transform.warp = false; - } - } - ); } void render_system::draw(float alpha) @@ -123,14 +101,13 @@ void render_system::on_scene_construct(entity::registry& registry, entity::id en if (const auto transform = registry.try_get(entity_id)) { component.object->set_transform(transform->world); - component.object->get_transform_tween().update(); } for (std::size_t i = 0; i < layers.size(); ++i) { if (component.layer_mask & static_cast(1 << i)) { - layers[i]->add_object(component.object.get()); + layers[i]->add_object(*component.object); } } } @@ -143,12 +120,12 @@ void render_system::on_scene_update(entity::registry& registry, entity::id entit { // Remove from layer scene::collection* layer = layers[i]; - layer->remove_object(component.object.get()); + layer->remove_object(*component.object); if (component.layer_mask & static_cast(1 << i)) { // Add to layer - layer->add_object(component.object.get()); + layer->add_object(*component.object); } } } @@ -161,7 +138,7 @@ void render_system::on_scene_destroy(entity::registry& registry, entity::id enti { if (component.layer_mask & static_cast(1 << i)) { - layers[i]->remove_object(component.object.get()); + layers[i]->remove_object(*component.object); } } } @@ -174,6 +151,5 @@ void render_system::on_transform_construct(entity::registry& registry, entity::i const auto& transform = registry.get(entity_id); scene->object->set_transform(transform.world); - scene->object->get_transform_tween().update(); } } diff --git a/src/game/systems/terrain-system.cpp b/src/game/systems/terrain-system.cpp index c3c0910..f821473 100644 --- a/src/game/systems/terrain-system.cpp +++ b/src/game/systems/terrain-system.cpp @@ -19,7 +19,6 @@ #include "game/systems/terrain-system.hpp" #include "game/components/terrain-component.hpp" -#include "game/components/camera-component.hpp" #include #include #include diff --git a/src/game/world.cpp b/src/game/world.cpp index fffad26..7db4713 100644 --- a/src/game/world.cpp +++ b/src/game/world.cpp @@ -361,29 +361,26 @@ void create_sun(::game& ctx) // Create sun directional light scene object ctx.sun_light = std::make_unique(); - ctx.sun_light->set_color({0, 0, 0}); + ctx.sun_light->set_illuminance({0, 0, 0}); ctx.sun_light->set_shadow_caster(true); ctx.sun_light->set_shadow_framebuffer(ctx.shadow_map_framebuffer.get()); ctx.sun_light->set_shadow_bias(0.005f); ctx.sun_light->set_shadow_cascade_count(4); ctx.sun_light->set_shadow_cascade_coverage(0.15f); ctx.sun_light->set_shadow_cascade_distribution(0.8f); - ctx.sun_light->update_tweens(); // Create sky ambient light scene object ctx.sky_light = std::make_unique(); - ctx.sky_light->set_color({0, 0, 0}); - ctx.sky_light->update_tweens(); + ctx.sky_light->set_illuminance({0, 0, 0}); // Create bounce directional light scene object ctx.bounce_light = std::make_unique(); - ctx.bounce_light->set_color({0, 0, 0}); + ctx.bounce_light->set_illuminance({0, 0, 0}); ctx.bounce_light->look_at({0, 0, 0}, {0, 1, 0}, {1, 0, 0}); - ctx.bounce_light->update_tweens(); // Add sun light scene objects to surface scene - ctx.surface_scene->add_object(ctx.sun_light.get()); - ctx.surface_scene->add_object(ctx.sky_light.get()); + ctx.surface_scene->add_object(*ctx.sun_light); + ctx.surface_scene->add_object(*ctx.sky_light); //ctx.surface_scene->add_object(ctx.bounce_light); // Pass direct sun light scene object to shadow map pass and astronomy system @@ -450,11 +447,10 @@ void create_moon(::game& ctx) // Create moon directional light scene object ctx.moon_light = std::make_unique(); - ctx.moon_light->set_color({0, 0, 0}); - ctx.moon_light->update_tweens(); + ctx.moon_light->set_illuminance({0, 0, 0}); // Add moon light scene objects to surface scene - ctx.surface_scene->add_object(ctx.moon_light.get()); + ctx.surface_scene->add_object(*ctx.moon_light); // Pass moon light scene object to astronomy system ctx.astronomy_system->set_moon_light(ctx.moon_light.get());