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

Add View Bobbing to Camera #665

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open

Conversation

AlexDavies8
Copy link

View bobbing can make movement feel more natural. I've added view bobbing to the camera while walking on the ground. The strength of it can be changed in the graphics section of the settings menu.

@IntegratedQuantum
Copy link
Member

I think it feels kind of weird, but I might be biased since I've played this game without any view bobbing for a while. Maybe someone else could take a look.

Also make sure you fix the formatting.

@ikabod-kee
Copy link
Collaborator

I will take a look

@ikabod-kee
Copy link
Collaborator

Here's a few issues I found:

  1. Bobbing should not effect the player's actual sightline
  2. It seems to effect the player's position (which is no bueno)
  3. Sometimes I get teleported to a random position, that persists between worlds
2024-09-03.15-30-45.mp4
2024-09-03.15-29-31.mp4

@ikabod-kee
Copy link
Collaborator

The teleport is caused by walking backwards.

@ITR13
Copy link
Contributor

ITR13 commented Sep 3, 2024

The teleport is caused by walking backwards.
Doesn't happen for me after 2ced078, so I think this is fixed.

https://github.com/user-attachments/assets/8a83f2d8-bcdb-4d05-87f3-fb2bac8116d4
If the FPS is set to unlimited and vsync is off, you kinda slowly sink into the ground even when you're standing still.
EDIT: not sure why that didn't embed as a video

@AlexDavies8
Copy link
Author

Thanks for the feedback. To address each of the original points:

  1. How would this work? The only thing I can think that wouldn't change the sightline would be to change the roll of the camera or to move it along the local z axis (so forwards/backwards), both of which would feel very strange. I've taken a look at minecraft's view bobbing and it also affects the player's sightline. I've updated the view bobbing to be more natural based off minecraft's implementation.
  2. Not sure what you mean by affecting the player's position. I'm adding an extra position term to the return of Player.getEyePosBlocking() which seems to only be used for clientside rendering stuff and some calculations around which chunks should be visible.
  3. Fixed now. I was accidentally taking a fractional power of a negative number, so everything became 'nan'.

@AlexDavies8
Copy link
Author

Also, the sinking isn't caused by my changes. It also happens on commit before any of my changes. It also seems to only happen if you're looking below the horizon.

@ITR13
Copy link
Contributor

ITR13 commented Sep 3, 2024

Also, the sinking isn't caused by my changes. It also happens on commit before any of my changes. It also seems to only happen if you're looking below the horizon.

Makes sense, I should have double checked that it didn't happen before.

@careeoki
Copy link
Contributor

careeoki commented Sep 4, 2024

I'm not a fan of view bobbing in any game. I don't think it adds to immersion, and at worst it can cause motion sickness.
I bet most players would turn it off as soon as they find the option.

Regardless, setting View Bobbing to 0 doesn't seem to actually turn it off.
If you're walking directly into a wall or corner, your view still bobs despite the player not actually moving.

@AlexDavies8
Copy link
Author

AlexDavies8 commented Sep 4, 2024

Fixed the issue with view bobbing 0 not turning it off. I'm a big fan of view bobbing personally. For me it feels massively jarring without it, but there's always the option of just defaulting it to be off if most people prefer that.

@ikabod-kee
Copy link
Collaborator

How would this work? The only thing I can think that wouldn't change the sightline would be to change the roll of the camera or to move it along the local z axis (so forwards/backwards), both of which would feel very strange. I've taken a look at minecraft's view bobbing and it also affects the player's sightline. I've updated the view bobbing to be more natural based off minecraft's implementation.

Could make the block selection ray and camera separate. Like player separate from camera.
Right now the camera is the player; it's probably a good idea to make them separate.

Also, here is footage of Minecraft to prove that it's separate.

2024-09-03.23-17-53.mp4

@ikabod-kee
Copy link
Collaborator

Also, intensity of view bobbing should change with speed. More speed=more bobbing? Try it!

@IntegratedQuantum
Copy link
Member

I agree with @ikabod-kee that the focus point should be stable, and not move. Our eyes do this as well when we walk around. This should also be better for people with motion sickness.

As for how this could be implemented:
Instead of just moving the camera it also needs to be rotated such that it still points at the same position in 3d space as it would without bobbing. This position can be determined with a raycast from the camera, just like it's already done for block selection.

@ikabod-kee
Copy link
Collaborator

I agree with @ikabod-kee that the focus point should be stable, and not move. Our eyes do this as well when we walk around. This should also be better for people with motion sickness.

As for how this could be implemented: Instead of just moving the camera it also needs to be rotated such that it still points at the same position in 3d space as it would without bobbing. This position can be determined with a raycast from the camera, just like it's already done for block selection.

I would personally just separate the camera from the raycast.

@AlexDavies8
Copy link
Author

I've changed it so that the selected block isn't affected by the bobbing. Also, we no longer have view bobbing if you are stuck on a wall (view only bobs when you are actually moving, instead of it being based on input). The magnitude of the motion also increases slightly when moving faster as the bobbing motion felt weaker when sprinting compared to walking (guessing some kind of optical illusion or weird way our brains see motion).

@ikabod-kee
Copy link
Collaborator

I will check it out!

@ikabod-kee
Copy link
Collaborator

The bobbing effect seems very different now. It's as if you're walking with a limp now instead of step by step, which doesn't feel very satisfying. The bug fixes are very good though!

@ITR13
Copy link
Contributor

ITR13 commented Sep 5, 2024

The bobbing effect seems very different now. It's as if you're walking with a limp now instead of step by step, which doesn't feel very satisfying. The bug fixes are very good though!

Also agree that the current implementation feels weird.

Copy link
Collaborator

@ikabod-kee ikabod-kee left a comment

Choose a reason for hiding this comment

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

Change view bobbing to look more like walking, and preferably less roll.

@ikabod-kee ikabod-kee added help wanted extra attention is needed contributor friendly this issue is limited in scope and/or knowledge of Cubyz internals, good for newcomers labels Sep 8, 2024
@ikabod-kee
Copy link
Collaborator

Any chance you'll get back to this PR? @AlexDavies8

@AlexDavies8
Copy link
Author

Yeah, sorry, was away for the weekend so couldn't work on it for a few days. I'm planning on taking a better look at reworking the movement to feel more natural tomorrow. :)

@ikabod-kee
Copy link
Collaborator

Excellent :)

Copy link
Member

@IntegratedQuantum IntegratedQuantum left a comment

Choose a reason for hiding this comment

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

While reviewing I found that many of your math expressions are unnecessarily complicated and could be simplified by applying some trigonometric identities.

Additionally one thing I would like you to think about: You have set a limit of 1.2 to bobMag.
This seems like it would cause further problems down the line. In the game I think it would be nice to have variable player hitboxes. Because of that I would like to have a generic limit to bobMag that guarantees that the camera won't ever go outside of the players bounding box.

src/game.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
@@ -556,7 +569,7 @@ pub const MenuBackGround = struct {
// Draw to frame buffer.
buffer.bind();
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT);
main.renderer.render(game.Player.getEyePosBlocking());
main.renderer.render();
Copy link
Member

Choose a reason for hiding this comment

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

It seems that your method will now always apply bobbing to any render call.
This call however requires a stable camera, otherwise the recorded background image will contain seems.

Copy link
Author

Choose a reason for hiding this comment

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

I'm not quite sure what you mean here in terms of background seams, but yes, view bobbing will apply to all render calls that also render the world, although shouldn't happen on the title screen as that's a different code path. The only thing I can think that could be done differently would be to let the camera store its own position, so no player-related data needs to be passed to the renderer, and then handle the special case of the block selection somehow as we don't want to have view bobbing affect it.

Copy link
Author

Choose a reason for hiding this comment

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

Actually, decoupling the player and the camera position might be a good idea generally, as it would allow for third person/spectator and other camera effects to be handled in some update loop instead of directly in the rendering code.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually, decoupling the player and the camera position might be a good idea generally, as it would allow for third person/spectator and other camera effects to be handled in some update loop instead of directly in the rendering code.

Hard agree.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not quite sure what you mean here in terms of background seams

If you press Ctrl+print screen, then the game records a background image at your location. This is done by rendering the screen 4 times with a 90° angle in between. If your camera is angled from view bobbing, then this means that these 4 images are rotated, and don't fit together seamlessly.

Copy link
Member

Choose a reason for hiding this comment

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

This is still broken. If I record a background image while moving then it contains seams between the recorded images. Here take a look:
client_1146

@IntegratedQuantum
Copy link
Member

Oh and also please fix the merge conflict.

@AlexDavies8
Copy link
Author

AlexDavies8 commented Sep 11, 2024

Additionally one thing I would like you to think about: You have set a limit of 1.2 to bobMag. This seems like it would cause further problems down the line. In the game I think it would be nice to have variable player hitboxes. Because of that I would like to have a generic limit to bobMag that guarantees that the camera won't ever go outside of the players bounding box.

It's clamped to be equal (roughly) to the magnitude caused by sprinting (just realised this is actually the wrong number, is fixed now), so going faster won't cause the camera to freak out. However, even at max view bobbing strength, it would only risk exiting the bounds if it was clamped at something pretty high like 4. I could probably enforce the limit earlier on, though, so it's clearer why it exists. It shouldn't be hard to scale it by the size of the player's hitbox either - the height would probably be best.

@AlexDavies8
Copy link
Author

Addressed feedback as much as I can without decoupling the camera position from player position.

src/game.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
src/renderer.zig Outdated
@@ -199,9 +212,9 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
const meshes = mesh_storage.updateAndGetRenderChunks(world.conn, playerPos, settings.renderDistance);

gpu_performance_measuring.startQuery(.chunk_rendering_preparation);
const direction = crosshairDirection(game.camera.viewMatrix, lastFov, lastWidth, lastHeight);
const direction = crosshairDirection(baseViewMatrix, lastFov, lastWidth, lastHeight);
Copy link
Author

Choose a reason for hiding this comment

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

Is there a reason we are using crosshairDirection instead of just game.camera.direction? game.camera.direction seems to do the same without having to extract the direction from the view matrix.

Copy link
Contributor

Choose a reason for hiding this comment

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

#323
Try moving the crosshair in menu mode. Check if block selection is still accurate after removing this code.

@AlexDavies8
Copy link
Author

Finally got around to decoupling the camera from the player. It turned out to not be that much work. I've also moved the camera to it's own file and put the viewbobbing in there instead of inside of the Player struct to keep it cleaner. In the future, the logic for third person/first person camera control, or camera shake (such as on taking damage or maybe is there's some kind of explosion) could also go in this file.

To me this feels a lot easier to work with. It might also be good to redo some of the block selection stuff, as it seems like we are selecting the block during rendering and then reusing that result to place/remove blocks. To me, that is game logic, and should be done before rendering inside of the update loop, and then the renderer doesn't need to update the selected block itself. I haven't done that here, but I have swapped over to using camera.direction instead of crosshairDirection as it removes the need for quite a few temporary variables, and we calculate the look direction of the camera when updating the matrix anyway, so we are saving a tiny bit of computation each frame as a bonus.

@ikabod-kee
Copy link
Collaborator

Legend! Hope this PR can get concluded :)

@ikabod-kee
Copy link
Collaborator

Also I think the crosshair was a seperate thing because the crosshair is movable (for some reason?)

Copy link
Member

@IntegratedQuantum IntegratedQuantum left a comment

Choose a reason for hiding this comment

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

It's difficult to review this PR due to all the unintentional formatting changes. Please revert them.
Also again please fix the merge conflicts.

src/game.zig Outdated
// Maximum magnitude when sprinting (2x walking speed)
Player.bobMag = @sqrt(@min(Player.bobVel, 2)) * settings.viewBobStrength;
// Maximum magnitude when sprinting (2x walking speed). Magnitude is scaled by player bounding box height
Player.bobMag = @sqrt(@min(Player.bobVel, 2)) * settings.viewBobStrength * Player.outerBoundingBoxExtent[2];
Copy link
Member

Choose a reason for hiding this comment

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

It's not that simple, the camera is not at the center of the bounding box, it can be anywhere inside the eyeBox.

Copy link
Author

Choose a reason for hiding this comment

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

I'm still confused about what you mean about the eyeBox in relation to view bobbing. Scaling by the bounding box height should scale the view bobbing by player height, so scaling the player up or down should cause the view bobbing to appear the same relative to the player's size. Is there a plan to have characters with tiny legs and a huge hat or something, where the eyes and view bobbing should be ow but the bounding box tall?

Copy link
Member

@IntegratedQuantum IntegratedQuantum Sep 21, 2024

Choose a reason for hiding this comment

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

Scaling the bobbing by player height is fine, but
Let's say you sprint jump through a narrow tunnel.
I need you to guarantee that under no circumstances the camera will clip into the terrain.
The camera can be anywhere inside the eyeBox The eyeBox should always be smaller than the collision box. But your code adds a value to that cameraPosition, so you might push it outside the eyeBox.
Please ensure that the resulting position is never outside the collision box, which could make it clip into the terrain. It probably shouldn't even get too close to the collision box, because OpenGL doesn't render triangles at depth 0.

Now you have probably tested this scenario and everything works fine, but all these parameters, like the hitboxes and how often the camera actually gets close to the bounds of the eyeBox, may change.

src/game.zig Outdated Show resolved Hide resolved
@@ -556,7 +569,7 @@ pub const MenuBackGround = struct {
// Draw to frame buffer.
buffer.bind();
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT);
main.renderer.render(game.Player.getEyePosBlocking());
main.renderer.render();
Copy link
Member

Choose a reason for hiding this comment

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

I'm not quite sure what you mean here in terms of background seams

If you press Ctrl+print screen, then the game records a background image at your location. This is done by rendering the screen 4 times with a 90° angle in between. If your camera is angled from view bobbing, then this means that these 4 images are rotated, and don't fit together seamlessly.

src/camera.zig Outdated Show resolved Hide resolved
src/game.zig Outdated Show resolved Hide resolved
src/renderer.zig Outdated Show resolved Hide resolved
@AlexDavies8
Copy link
Author

Fixed the formatting stuff, think I did it by accident while merging. The background image isn't affected by view bobbing as the camera now has the view bobbing applied in the renderer. At the moment this is essentially hard-coded to the renderer, but if there are more effects in the future such as camera shaking such as on taking damage or explosions etc, it might be better to move this to some kind of function on the camera such as applyRenderTransforms and removeRenderTransforms.
It might also make sense to switch the camera physics stuff to apply as one of these render-only transformations if we don't want them to affect the currently selected block.

@IntegratedQuantum
Copy link
Member

The background image is still broken, and there's also ensuring that the camera stays inside the bounding box.
The rest is looking good, so we are almost done here.

It might also make sense to switch the camera physics stuff to apply as one of these render-only transformations if we don't want them to affect the currently selected block.

We definitely want the camera physics to affect block selection, otherwise it would be completely broken when climbing stairs, the camera physics is important for smoothing out movement.

@AlexDavies8
Copy link
Author

Finally got around to fixing the last little bits. The view bobbing shouldn't be able to escape the eyeBox anymore. It will scale down the view bobbing if the camera is already near the edge (such as due to camera physics), and will clamp the final view bobbing to always remain inside eyeBox to catch the case where the view bobbing alone would be outside the eyeBox.
The seams on the background image should be fixed too. It might be worth disabling the block selection when taking the image as well in the future.

@IntegratedQuantum
Copy link
Member

IntegratedQuantum commented Sep 26, 2024

It appears to be broken:

video-2024-09-26_19.23.09.mp4

@AlexDavies8
Copy link
Author

Oops 😅, forgot to reset view bobbing strength after testing out the eyeBox clamping. Should be fixed now.

@IntegratedQuantum
Copy link
Member

Please do more thorough testing in the future. Stairs and stepping in general is broken:

video-2024-09-27_20.15.50.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants