three.jsrotationeuler-angles

How to handle independent camera elevation in Three.js


I have the following code that is run on every frame:

      const yRotationPerFrame =
        (scaleSensitivity(leftStick.x) * framePeriod) / 15
      const forwardVelocity = scaleSensitivity(leftStick.y, 5)
      const sidewaysVelocity = -scaleSensitivity(rightStick.x, 5)
      // const elevationAngle = -rightStick.y / 40
      // camera.rotation.x = elevationAngle
      camera.rotation.y -= yRotationPerFrame

      forwardVector.set(0, 0, forwardVelocity)
      sideVector.set(sidewaysVelocity, 0, 0)
      direction
        .subVectors(forwardVector, sideVector)
        .applyEuler(camera.rotation)
      setLinearVelocity({ x: direction.x, y: velocity.y, z: direction.z })

when I uncomment the line camera.rotation.x = elevationAngle , it kind of works but only for the meanwhile when there is no y rotation.

I tried with camera.rotation.x = elevationAngle but I was expecting it would work regardless of the camera.rotation.y number. Unfortunately that is not the case...


Solution

  • Here is the solution that I came up with and that solved the problem:

      const forwardVelocity = scaleSensitivity(leftStick.y, 5)
      const sidewaysVelocity = -scaleSensitivity(rightStick.x, 5)
      const elevationAngle = -rightStick.y / 40
    
      // Get the RigidBody's current rotation
      const rigidBodyRotation = ref.current.rotation()
    
      forwardVector.set(0, 0, forwardVelocity)
      sideVector.set(sidewaysVelocity, 0, 0)
      direction
        .subVectors(forwardVector, sideVector)
        .applyQuaternion(rigidBodyRotation)
    
      // Create a quaternion for the elevation angle (pitch)
      const elevationQuaternion = new Quaternion().setFromAxisAngle(
        new Vector3(1, 0, 0), // Rotate around the X-axis (pitch)
        elevationAngle
      )
    
      // Combine the RigidBody's rotation with the elevation quaternion
      const combinedRotation = rigidBodyRotation.clone()
        .multiply(elevationQuaternion)
    
      // Set the camera's rotation to the combined quaternion
      camera.rotation.setFromQuaternion(combinedRotation)
    
      // Set the angular velocity directly
      ref.current.setAngularVelocity({x: 0, y: -scaleSensitivity(leftStick.x, 25), z:0})
      ref.current.setLinearVelocity({ x: direction.x, y: velocity.y, z: direction.z })