Skip to content

Commit

Permalink
Game: Fix camera spin after set_horizontal_look
Browse files Browse the repository at this point in the history
  • Loading branch information
SmallJoker committed Dec 22, 2023
1 parent e0d4a9d commit ccffd85
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 53 deletions.
3 changes: 2 additions & 1 deletion builtin/settingtypes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@

[*General]

# Smooths rotation of camera, also called look or mouse smoothing. 0 to disable.
# Smooths rotation of camera, also called look or mouse smoothing.
# 0.99 results in the smoothest transitions. 0 to disable.
camera_smoothing (Camera smoothing) float 0.0 0.0 0.99

# Smooths rotation of camera when in cinematic mode, 0 to disable. Enter cinematic mode by using the key set in Change Keys.
Expand Down
9 changes: 5 additions & 4 deletions src/client/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1295,10 +1295,10 @@ void Game::run()
processUserInput(dtime);
// Update camera before player movement to avoid camera lag of one frame
updateCameraDirection(&cam_view_target, dtime);
cam_view.camera_yaw += (cam_view_target.camera_yaw -
cam_view.camera_yaw) * m_cache_cam_smoothing;
cam_view.camera_pitch += (cam_view_target.camera_pitch -
cam_view.camera_pitch) * m_cache_cam_smoothing;
// Previously, cam_smoothing likely assumed 60 FPS, thus factor 60.
float factor = dtime * 60.0f * m_cache_cam_smoothing;
wrappedApproachFactor(cam_view.camera_yaw, cam_view_target.camera_yaw, factor, 360.f);
wrappedApproachFactor(cam_view.camera_pitch, cam_view_target.camera_pitch, factor, 360.f);
updatePlayerControl(cam_view);

updatePauseState();
Expand Down Expand Up @@ -4399,6 +4399,7 @@ void Game::readSettings()
else
m_cache_cam_smoothing = 1 - g_settings->getFloat("camera_smoothing");

// 1: instant update, 0.01: very smooth
m_cache_cam_smoothing = rangelim(m_cache_cam_smoothing, 0.01f, 1.0f);
m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0);

Expand Down
4 changes: 2 additions & 2 deletions src/client/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ struct RunStats {
};

struct CameraOrientation {
f32 camera_yaw; // "right/left"
f32 camera_pitch; // "up/down"
f32 camera_yaw; // "right/left" in degrees
f32 camera_pitch; // "up/down" in degrees
};


Expand Down
50 changes: 50 additions & 0 deletions src/util/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,56 @@ s16 adjustDist(s16 dist, float zoom_fov)
return std::round(adjustDist((float)dist, zoom_fov));
}

void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
{
if (length < 1 || pagecount < 1 || page < 1 || page > pagecount) {
// Special cases or invalid parameters
minindex = maxindex = 0;
} else if(pagecount <= length) {
// Less pages than entries in the list:
// Each page contains at least one entry
minindex = (length * (page-1) + (pagecount-1)) / pagecount;
maxindex = (length * page + (pagecount-1)) / pagecount;
} else {
// More pages than entries in the list:
// Make sure the empty pages are at the end
if (page < length) {
minindex = page-1;
maxindex = page;
} else {
minindex = 0;
maxindex = 0;
}
}
}

void wrappedApproachShortest(float &current, float target, float stepsize, float maximum)
{
float delta = target - current;
if (delta < 0)
delta += maximum;

if (delta > stepsize && maximum - delta > stepsize) {
current += (delta < maximum / 2) ? stepsize : -stepsize;
if (current >= maximum)
current -= maximum;
} else {
current = target;
}
}

void wrappedApproachFactor(float &current, float target, float factor, float maximum)
{
float delta = fmod(target - current, maximum); // range ]-max, +max[
if (delta < -maximum * 0.5f)
delta += maximum; // -340° -> +20°
else if (delta > maximum * 0.5f)
delta -= maximum; // +340° -> -20°

current += delta * rangelim(factor, 0.0f, 1.0f);
}


void setPitchYawRollRad(core::matrix4 &m, const v3f &rot)
{
f64 a1 = rot.Z, a2 = rot.X, a3 = rot.Y;
Expand Down
55 changes: 9 additions & 46 deletions src/util/numeric.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,35 +384,7 @@ class IntervalLimiter
Ensures 0 <= minindex <= maxindex <= length.
*/
inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
{
if (length < 1 || pagecount < 1 || page < 1 || page > pagecount) {
// Special cases or invalid parameters
minindex = maxindex = 0;
} else if(pagecount <= length) {
// Less pages than entries in the list:
// Each page contains at least one entry
minindex = (length * (page-1) + (pagecount-1)) / pagecount;
maxindex = (length * page + (pagecount-1)) / pagecount;
} else {
// More pages than entries in the list:
// Make sure the empty pages are at the end
if (page < length) {
minindex = page-1;
maxindex = page;
} else {
minindex = 0;
maxindex = 0;
}
}
}

inline float cycle_shift(float value, float by = 0, float max = 1)
{
if (value + by < 0) return value + by + max;
if (value + by > max) return value + by - max;
return value + by;
}
void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex);

inline bool is_power_of_two(u32 n)
{
Expand All @@ -431,24 +403,15 @@ inline u32 npot2(u32 orig) {
return orig + 1;
}

// Gradual steps towards the target value in a wrapped (circular) system
// using the shorter of both ways
template<typename T>
inline void wrappedApproachShortest(T &current, const T target, const T stepsize,
const T maximum)
{
T delta = target - current;
if (delta < 0)
delta += maximum;
/// Linear interpolation of two values in a wrapped range (radians, degrees)
/// @param stepsize Maximal step size between function calls
/// @param maximum Usually 360.0f or (2 * M_PI)
void wrappedApproachShortest(float &current, float target, float stepsize, float maximum);

if (delta > stepsize && maximum - delta > stepsize) {
current += (delta < maximum / 2) ? stepsize : -stepsize;
if (current >= maximum)
current -= maximum;
} else {
current = target;
}
}
/// Exponential interpolation of two values in a wrapped range (radians, degrees)
/// @param factor Interpolation factor in range [0,1]
/// @param maximum Usually 360.0f or (2 * M_PI)
void wrappedApproachFactor(float &current, float target, float factor, float maximum);

void setPitchYawRollRad(core::matrix4 &m, const v3f &rot);

Expand Down

0 comments on commit ccffd85

Please sign in to comment.