aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorANAND <ClobberXD@gmail.com>2020-05-02 16:22:11 +0530
committerGitHub <noreply@github.com>2020-05-02 12:52:11 +0200
commite0ea87f1f32273dba2eb5421c2a8c890479ba078 (patch)
treef4a64ef33340f60707f7cbe7b937bc183d0562c3 /src/client
parentac368af4fe27f61f5a4209cdfe90956ff745993c (diff)
downloadminetest-e0ea87f1f32273dba2eb5421c2a8c890479ba078.tar.gz
minetest-e0ea87f1f32273dba2eb5421c2a8c890479ba078.tar.bz2
minetest-e0ea87f1f32273dba2eb5421c2a8c890479ba078.zip
set_fov: Add support for time-based transitions (#9705)
Diffstat (limited to 'src/client')
-rw-r--r--src/client/camera.cpp84
-rw-r--r--src/client/camera.h15
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;