Strafing vector from side to side

Hi team !
In chapter 9: Camera Movement

In the orange mark, I see you set “-forwardVector.x”.
But I don’t understand the difference yet if I set “forwardVector.x”.
Screen Shot 2022-06-15 at 18.06.12

The result of the vector is the same when I manipulate the move.
Hope you explain to me

@Caroline any suggestions?

1 Like

Hi @nghiaphamsg

You won’t notice a difference unless you rotate using the left and right arrow keys.

If you change the sign to forwardVector.x, then rotate using the right arrow key, when you press A, you will go in the wrong direction.

When you first start the app, the forward vector is 0, 0, 1. So it makes no difference whether 0 is positive or negative. But as soon as you press the left or right arrow key, the forward vector changes, and the sign becomes important.

2 Likes

Thank @caroline

I understood after combining arrow button.
Honestly, in this article, there are a lot of calculations that I think are quite complicated, if you can explain more, that would be great.

Like the code marked below, I understand this to be the part that limits the x-axis rotation from -90° to 90°. I tried to comment out the code so it can rotate 360 degrees but it’s not what I thought it would be. So, I feel like they’re being “LookAt flip”
Screen Shot 2022-06-17 at 20.47.45

Besides, I see an unnecessary point.
When scrolling, the yValue value tells us the amount we scrolled vertically
That mean “distance” depending on the mouse scroll yValue.
Screen Shot 2022-06-18 at 1.41.49

→ This xValue seems really unnecessary ?

The maxing of the x-axis is to do with simplifying the camera up axis when calculating the lookAt matrix in viewMatrix.

I decided that the camera should never be upside down, so the up vector will always be [0, 1, 0].

If you comment out the max line, and let rotation.x go beyond the bounds, then when the camera gets to beyond 90º, the camera’s up axis will need to go negative.

You can try this by commenting out the max line and changing var viewMatrix to:

  var viewMatrix: float4x4 {
    let matrix: float4x4
    if target == position {
      matrix = (float4x4(translation: target) * float4x4(rotationYXZ: rotation)).inverse
    } else {
      let up: float3 = rotation.x < -.pi / 2 ? [0, -1, 0] : [0, 1, 0]
      matrix = float4x4(eye: position, center: target, up: up)
    }
    return matrix
  }

Then when you take the camera up, looking down at the centre of the scene, when you get beyond negative 90º, up.y will change to be negative. The scene doesn’t flip now. This works until you get to negative 270º, when the scene will flip because up.y should now be positive.

I chose to simplify this by maxing out rotation.x, but you can do further math to ensure that you can do continuous rotation.

2 Likes

I think I included input.mouseScroll.x as that seemed to feel the best over my various mice and trackpads. I do remember that getting GCMouse to perform scrolling properly on all of them was quite difficult.

If you implement side to side scrolling, then you would of course remove input.mouseScroll.x, but I didn’t implement it. On a Magic Mouse, swiping side to side increases x, and swiping front to back increases y.

On reflection, and retrying my mice, maybe something has changed. I don’t think I would include input.mouseScroll.x now.

Thanks for bringing it to my attention.

2 Likes

I should add that implementing a complete input system is much more complex that presented here. This is simply an introduction to how you could start implementing a camera and input controller. You could write a book on the maths of cameras and mouse / keyboard / game controller movement alone :smiley: :exploding_head: .

1 Like

Hi @caroline
Thank you so much for explaining it to me.
Mathematically I also found a document to better explain the cameras in action.
I’ll leave the link here if anyone has the same problem as me

Once again I thank you for supporting me

2 Likes

That’s a good link, thank you for providing it here.

1 Like

Note: The code below to unlimit rotate on x axis (this section complements Mrs.Caroline’s code)

  var viewMatrix: float4x4 {
    let matrix: float4x4
    if target == position {
      matrix = (float4x4(translation: target) * float4x4(rotationYXZ: rotation)).inverse
    } else {
      let up: float3 = rotation.x < -.pi / 2 || rotation.x > .pi / 2 ? [0, -1, 0] : [0, 1, 0]
      matrix = float4x4(eye: position, center: target, up: up)
    }
    return matrix
  }
  mutating func update(deltaTime: Float) {
    let input = InputController.shared
    let scrollSensitivity = Settings.mouseScrollSensitivity
    distance -= (input.mouseScroll.x + input.mouseScroll.y) * scrollSensitivity
    distance = min(maxDistance, distance)
    distance = max(minDistance, distance)
    input.mouseScroll = .zero
    if input.leftMouseDown {
      let sensitivity = Settings.mousePanSensitivity
      rotation.x += input.mouseDelta.y * sensitivity
      rotation.y += input.mouseDelta.x * sensitivity
      if rotation.x > ((3 * .pi) / 2) {
        rotation.x = -.pi / 2
      }
      if rotation.x < ((3 * -.pi) / 2) {
        rotation.x = .pi / 2
      }
      // rotation.x = max(-.pi / 2, min(rotation.x, .pi / 2))
      input.mouseDelta = .zero
    }
    let rotateMatrix = float4x4(rotationYXZ: [-rotation.x, rotation.y, 0])
    let distanceVector = float4(0, 0, -distance, 0)
    let rotatedVector = rotateMatrix * distanceVector
    position = target + rotatedVector.xyz
  }

The code seems complicated, I’ll make a note here and optimize it later.
For those who want flycam style.

Thank for reading!

1 Like