Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase FOV when moving fast (Issue#716) #812

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
21 changes: 21 additions & 0 deletions src/game.zig
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ pub const Player = struct { // MARK: Player
pub var eyeVel: Vec3d = .{0, 0, 0};
pub var eyeCoyote: f64 = 0;
pub var eyeStep: @Vector(3, bool) = .{false, false, false};
pub var speedMod: f32 = 0.0;
pub var id: u32 = 0;
pub var gamemode: Atomic(Gamemode) = .init(.creative);
pub var isFlying: Atomic(bool) = .init(false);
Expand Down Expand Up @@ -401,6 +402,12 @@ pub const Player = struct { // MARK: Player
return eyeCoyote;
}

pub fn getSpeedModifierBlocking() f32 {
mutex.lock();
defer mutex.unlock();
return speedMod;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just make fovMod atomic?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Why does it have to be atomic, when other, similar, variables (like eyeVel or eyePos) are not atomic either?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's only ever used by the update and render functions, then you are right, it doesn't need to be thread safe.

pub fn setGamemode(newGamemode: Gamemode) void {
gamemode.store(newGamemode, .monotonic);

Expand Down Expand Up @@ -894,6 +901,20 @@ pub fn update(deltaTime: f64) void { // MARK: update()
Player.eyeVel[i] = firstTerm.mul(c_3.negate().subScalar(frictionCoefficient).mulScalar(0.5)).add(secondTerm.mul((c_3.subScalar(frictionCoefficient)).mulScalar(0.5))).val[0];
Player.eyePos[i] += firstTerm.add(secondTerm).addScalar(a/k).val[0];
}

// Calculate our FOV modifier based on our current speed.
{
const x : f32 = @as(f32, @floatCast(movementSpeed));
const speedModGoal : f32 = @max(@log10((x*x)-15)/1.8, 0);
const speedModDir: f32 = if(Player.speedMod < speedModGoal) 1 else -1;
const speedModNext: f32 = Player.speedMod + (speedModDir * @as(f32, @floatCast(deltaTime)) * 5.0);

if((Player.speedMod < speedModGoal and speedModNext < speedModGoal) or (Player.speedMod > speedModGoal and speedModNext > speedModGoal)) {
Player.speedMod = speedModNext;
} else {
Player.speedMod = speedModGoal;
}
}
}

const time = std.time.milliTimestamp();
Expand Down
3 changes: 2 additions & 1 deletion src/graphics/Window.zig
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ pub const GLFWCallbacks = struct { // MARK: GLFWCallbacks
std.log.info("Framebuffer: {}, {}", .{newWidth, newHeight});
width = @intCast(newWidth);
height = @intCast(newHeight);
main.renderer.updateViewport(width, height, main.settings.fov);
main.renderer.updateViewport(width, height);
main.renderer.updateFOV(main.settings.fov);
main.gui.updateGuiScale();
main.gui.updateWindowPositions();
}
Expand Down
21 changes: 15 additions & 6 deletions src/renderer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,18 @@ var worldFrameBuffer: graphics.FrameBuffer = undefined;
var lastWidth: u31 = 0;
var lastHeight: u31 = 0;
var lastFov: f32 = 0;
pub fn updateViewport(width: u31, height: u31, fov: f32) void {
pub fn updateViewport(width: u31, height: u31) void {
lastWidth = @intFromFloat(@as(f32, @floatFromInt(width))*main.settings.resolutionScale);
lastHeight = @intFromFloat(@as(f32, @floatFromInt(height))*main.settings.resolutionScale);
lastFov = fov;
game.projectionMatrix = Mat4f.perspective(std.math.degreesToRadians(fov), @as(f32, @floatFromInt(lastWidth))/@as(f32, @floatFromInt(lastHeight)), zNear, zFar);
worldFrameBuffer.updateSize(lastWidth, lastHeight, c.GL_RGB16F);
worldFrameBuffer.unbind();
}

pub fn updateFOV(fov: f32) void {
lastFov = fov;
game.projectionMatrix = Mat4f.perspective(std.math.degreesToRadians(fov), @as(f32, @floatFromInt(lastWidth))/@as(f32, @floatFromInt(lastHeight)), zNear, zFar);
}

pub fn render(playerPosition: Vec3d) void {
// TODO: player bobbing
if(game.world) |world| {
Expand All @@ -132,6 +135,9 @@ pub fn render(playerPosition: Vec3d) void {
const skyColor = vec.xyz(world.clearColor);
game.fog.skyColor = skyColor;

const fov: f32 = settings.fov + (game.Player.getSpeedModifierBlocking() * 20);
updateFOV(fov);
IntegratedQuantum marked this conversation as resolved.
Show resolved Hide resolved

renderWorld(world, ambient, skyColor, playerPosition);
const startTime = std.time.milliTimestamp();
mesh_storage.updateMeshes(startTime + maximumMeshTime);
Expand Down Expand Up @@ -507,7 +513,8 @@ pub const MenuBackGround = struct {
lastTime = newTime;
const viewMatrix = Mat4f.rotationZ(angle);
shader.bind();
updateViewport(main.Window.width, main.Window.height, 70.0);
updateViewport(main.Window.width, main.Window.height);
updateFOV(70.0);

c.glUniformMatrix4fv(uniforms.viewMatrix, 1, c.GL_TRUE, @ptrCast(&viewMatrix));
c.glUniformMatrix4fv(uniforms.projectionMatrix, 1, c.GL_TRUE, @ptrCast(&game.projectionMatrix));
Expand All @@ -527,9 +534,11 @@ pub const MenuBackGround = struct {

const oldResolutionScale = main.settings.resolutionScale;
main.settings.resolutionScale = 1;
updateViewport(size, size, 90.0);
updateViewport(size, size);
updateFOV(90.0);
main.settings.resolutionScale = oldResolutionScale;
defer updateViewport(Window.width, Window.height, settings.fov);
defer updateViewport(Window.width, Window.height);
defer updateFOV(settings.fov);

var buffer: graphics.FrameBuffer = undefined;
buffer.init(true, c.GL_NEAREST, c.GL_REPEAT);
Expand Down
Loading