Perfect, it works! I knew you'd be able to figure it out. I updated it to slerp the target angle, so the camera is smooth now. However, I found one bug. After about 10 seconds, if you look exactly forward, the camera gets locked in the identity matrix and won't move anymore. However, I just needed orthonormalize it and then it works fine (probably some sort of floating-point error, I guess). Here is the final working code.
extends Camera
export(float, 0, 100) var move_speed = 50
export(float, 0, 100) var look_speed = 50
export(float, 0, 100) var look_smooth = 50
var move_scale = 0.1
var look_scale = 0.00001
var smooth_scale = 0.001
var threshold = 0.00001
var target_basis = Basis.IDENTITY
var mouse_locked = false
func _process(delta):
var move_dir = check_buttons()
translate(move_dir * move_speed * move_scale * delta)
transform.basis = transform.basis.slerp(target_basis, look_smooth * smooth_scale)
func _input(event):
if event is InputEventMouseMotion and mouse_locked:
var mouse_delta = -event.relative * look_speed * look_scale
var delta_y_max = (-target_basis.z).angle_to(Vector3.UP * sign(mouse_delta.y) )
mouse_delta.y = clamp(abs(mouse_delta.y), 0.0, delta_y_max - threshold) * sign(mouse_delta.y)
var horz_quat = Quat(target_basis.xform_inv(Vector3.UP), mouse_delta.x)
var vert_quat = Quat(Vector3.RIGHT, mouse_delta.y)
target_basis *= Basis(horz_quat * vert_quat)
target_basis = target_basis.orthonormalized()
if event.is_action_pressed("click"):
mouse_locked = not mouse_locked
if mouse_locked:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
func check_buttons():
var dir = Vector3.ZERO
if Input.is_action_pressed("forward"):
dir += Vector3.FORWARD
if Input.is_action_pressed("back"):
dir += Vector3.BACK
if Input.is_action_pressed("left"):
dir += Vector3.LEFT
if Input.is_action_pressed("right"):
dir += Vector3.RIGHT
if not dir.is_equal_approx(Vector3.ZERO):
dir = dir.normalized()
return dir
So we have it now, a camera with only Quaternions. Leonhard Euler can eat it.