Tilt a UniversalCamera when rotating left/right with keyboard

Hello,

I’m trying to make ‘first person’ game that you control with the keyboard. It must feel a bit like an airplane, flying over land, with a tilting horizon when you rotate.

I set keysRotateLeft and keysRotateRight to the left and right arrow keys:
https://playground.babylonjs.com/#GG8V1C

This works fine, but I would like to add a ‘tilt’ effect, when you move left or right. The tilt should be a maximum of say 10 degrees and should animate slowly to a horizontal horizon again when the left or right key is not pressed anymore.

I tried a FlyCamera which has a rollCorrect and bankedTurn properties, but this camera has no keysRotateLeft and keysRotateRight, and I could not get it to do what I want.

Any ideas how to achieve this?

let me add our amazing “camera man” @PolygonalSun to the thread

You might be able to do something like what the FlyCamera does but for the FreeCamera (PG Example):

var rotationChange = BABYLON.Quaternion.Zero();
var currentRotation = BABYLON.Quaternion.Zero();
var rolledMovement = 0;
...
BABYLON.Quaternion.RotationYawPitchRollToRef(camera.rotation.y, camera.rotation.x, camera.rotation.z, currentRotation);

    scene.onKeyboardObservable.add(eventData => {
        const type = eventData.type;
        const keyCode = eventData.event.keyCode;

        if (type === BABYLON.KeyboardEventTypes.KEYDOWN) {
            BABYLON.Quaternion.RotationYawPitchRollToRef(camera.rotation.y, camera.rotation.x, camera.rotation.z, currentRotation);
            if (keyCode === 39) {
                moving = true;
                if (rolledMovement > -Math.PI / 18) {
                    rolledMovement -= 0.02;
                    BABYLON.Quaternion.RotationAxisToRef(BABYLON.Axis.Z, -0.02, rotationChange);
                }
                else {
                    BABYLON.Quaternion.RotationAxisToRef(BABYLON.Axis.Z, 0, rotationChange);
                }
                currentRotation.multiplyInPlace(rotationChange);
                currentRotation.toEulerAnglesToRef(camera.rotation);
            }
            else if (keyCode === 37) {
                moving = true;
                if (rolledMovement < Math.PI / 18) {
                    rolledMovement += 0.02;
                    BABYLON.Quaternion.RotationAxisToRef(BABYLON.Axis.Z, 0.02, rotationChange);
                }
                else {
                    BABYLON.Quaternion.RotationAxisToRef(BABYLON.Axis.Z, 0, rotationChange);
                }
                currentRotation.multiplyInPlace(rotationChange);
                currentRotation.toEulerAnglesToRef(camera.rotation);
            }
        }
        else {
            BABYLON.Quaternion.RotationYawPitchRollToRef(camera.rotation.y, camera.rotation.x, camera.rotation.z, currentRotation);
            BABYLON.Quaternion.RotationAxisToRef(BABYLON.Axis.Z, -rolledMovement, rotationChange);
            currentRotation.multiplyInPlace(rotationChange);
            rolledMovement = 0;
            currentRotation.toEulerAnglesToRef(camera.rotation);
        }
    });

Basically, you’d need to use some quaternions to rotate your camera. Once you hit your desired angle, you’ll still need to update your rotation so that it remains at the same angle but relative to the direction you’re facing. For returning back to an upright position smoothly, you may need to create some value to hold the upright position and use something like scene.beforeRender to gradually reset the position. Hopefully, this can provide some inspiration.

Thanks a lot!
This looks a lot more like what I’m trying to achieve.

I changed your code a bit to have a more smooth keydown-event, which I got from another playground example:
https://playground.babylonjs.com/#GG8V1C#2

I’ll try to make the soft return to a normal horizon myself.
I have no idea how those quaternions work though :slight_smile:

Nobody knows I guess !!! I still look at them like a magic show and I want to keep the mystery :slight_smile: