diff options
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/camera.cpp | 84 | ||||
-rw-r--r-- | src/client/camera.h | 15 |
2 files changed, 81 insertions, 18 deletions
diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 69bd82a47..1a5253db4 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -86,6 +86,51 @@ Camera::~Camera() m_wieldmgr->drop(); } +void Camera::notifyFovChange() +{ + LocalPlayer *player = m_client->getEnv().getLocalPlayer(); + assert(player); + + PlayerFovSpec spec = player->getFov(); + + /* + * Update m_old_fov_degrees first - it serves as the starting point of the + * upcoming transition. + * + * If an FOV transition is already active, mark current FOV as the start of + * the new transition. If not, set it to the previous transition's target FOV. + */ + if (m_fov_transition_active) + m_old_fov_degrees = m_curr_fov_degrees; + else + m_old_fov_degrees = m_server_sent_fov ? m_target_fov_degrees : m_cache_fov; + + /* + * Update m_server_sent_fov next - it corresponds to the target FOV of the + * upcoming transition. + * + * Set it to m_cache_fov, if server-sent FOV is 0. Otherwise check if + * server-sent FOV is a multiplier, and multiply it with m_cache_fov instead + * of overriding. + */ + if (spec.fov == 0.0f) { + m_server_sent_fov = false; + m_target_fov_degrees = m_cache_fov; + } else { + m_server_sent_fov = true; + m_target_fov_degrees = spec.is_multiplier ? m_cache_fov * spec.fov : spec.fov; + } + + if (spec.transition_time > 0.0f) + m_fov_transition_active = true; + + // If FOV smooth transition is active, initialize required variables + if (m_fov_transition_active) { + m_transition_time = spec.transition_time; + m_fov_diff = m_target_fov_degrees - m_old_fov_degrees; + } +} + bool Camera::successfullyCreated(std::string &error_message) { if (!m_playernode) { @@ -462,33 +507,38 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r m_camera_position = my_cp; /* - * Apply server-sent FOV. If server doesn't enforce FOV, - * check for zoom and set to zoom FOV. - * Otherwise, default to m_cache_fov + * Apply server-sent FOV, instantaneous or smooth transition. + * If not, check for zoom and set to zoom FOV. + * Otherwise, default to m_cache_fov. */ - - f32 fov_degrees; - PlayerFovSpec fov_spec = player->getFov(); - if (fov_spec.fov > 0.0f) { - // If server-sent FOV is a multiplier, multiply - // it with m_cache_fov instead of overriding - if (fov_spec.is_multiplier) - fov_degrees = m_cache_fov * fov_spec.fov; - else - fov_degrees = fov_spec.fov; + if (m_fov_transition_active) { + // Smooth FOV transition + // Dynamically calculate FOV delta based on frametimes + f32 delta = (frametime / m_transition_time) * m_fov_diff; + m_curr_fov_degrees += delta; + + // Mark transition as complete if target FOV has been reached + if ((m_fov_diff > 0.0f && m_curr_fov_degrees >= m_target_fov_degrees) || + (m_fov_diff < 0.0f && m_curr_fov_degrees <= m_target_fov_degrees)) { + m_fov_transition_active = false; + m_curr_fov_degrees = m_target_fov_degrees; + } + } else if (m_server_sent_fov) { + // Instantaneous FOV change + m_curr_fov_degrees = m_target_fov_degrees; } else if (player->getPlayerControl().zoom && player->getZoomFOV() > 0.001f) { // Player requests zoom, apply zoom FOV - fov_degrees = player->getZoomFOV(); + m_curr_fov_degrees = player->getZoomFOV(); } else { // Set to client's selected FOV - fov_degrees = m_cache_fov; + m_curr_fov_degrees = m_cache_fov; } - fov_degrees = rangelim(fov_degrees, 1.0f, 160.0f); + m_curr_fov_degrees = rangelim(m_curr_fov_degrees, 1.0f, 160.0f); // FOV and aspect ratio const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); m_aspect = (f32) window_size.X / (f32) window_size.Y; - m_fov_y = fov_degrees * M_PI / 180.0; + m_fov_y = m_curr_fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); diff --git a/src/client/camera.h b/src/client/camera.h index 6ec37fe10..3a59637bc 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -112,6 +112,9 @@ public: return MYMAX(m_fov_x, m_fov_y); } + // Notify about new server-sent FOV and initialize smooth FOV transition + void notifyFovChange(); + // Checks if the constructor was able to create the scene nodes bool successfullyCreated(std::string &error_message); @@ -186,6 +189,9 @@ private: Client *m_client; + // Default Client FOV (as defined by the "fov" setting) + f32 m_cache_fov; + // Absolute camera position v3f m_camera_position; // Absolute camera direction @@ -193,6 +199,14 @@ private: // Camera offset v3s16 m_camera_offset; + // Server-sent FOV variables + bool m_server_sent_fov = false; + f32 m_curr_fov_degrees, m_old_fov_degrees, m_target_fov_degrees; + + // FOV transition variables + bool m_fov_transition_active = false; + f32 m_fov_diff, m_transition_time; + v2f m_wieldmesh_offset = v2f(55.0f, -35.0f); v2f m_arm_dir; v2f m_cam_vel; @@ -230,7 +244,6 @@ private: f32 m_cache_fall_bobbing_amount; f32 m_cache_view_bobbing_amount; - f32 m_cache_fov; bool m_arm_inertia; std::list<Nametag *> m_nametags; |