Godot Version
4.4
Question
Hello. I’m working on an FPS camera, and I want to use a quaternion for transform.basis. The code works, but I don’t understand at all how do I clamp the X-axis rotation in the basis “x_bas”?
var x_bas = Basis.IDENTITY
var y_bas = Basis.IDENTITY
func camera_look(event: InputEventMouseMotion):
var mouse_delta:Vector2 = -event.relative * sensitivity
x_bas *= Basis(Vector3.UP, deg_to_rad(mouse_delta.x))
y_bas *= Basis(Vector3.RIGHT, deg_to_rad(mouse_delta.y))
transform.basis = Basis(Quaternion(x_bas.orthonormalized() * Quaternion(y_bas.orthonormalized()))
P.S. I use an online translator, I apologize if my text is written illiterately.
Seems like you shouldn’t be using quaternion mathematics for this axis-bound rotation. Why not just use rotation.x
and rotation.y
? Godot will end up storing the rotation information in a Basis anyways.
1 Like
I’ve tried different rotation methods. I used rotate and rotate_object_local, and the problem was that “rotation.x = clamp…” was ignored when the mouse was moving vertically quickly. After looking at the answers in this topic and this one, I came to the conclusion that it is better to use quaternions. I do not know how successful and correct my decision is, but so far the camera is moving as it should, except that I do not know how to limit it in the vertical axis.
What I’ve done for that kind of thing is calculate the new position via quaternions, then call get_euler()
on it and only apply it if it’s not out of range:
var new_rot = (calculate_new_rotation()) * rotation
var euler = new_rot.get_euler()
if _eulers_within_bounds(euler): rotation = new_rot
Where _eulers_within_bounds()
does whatever checking you need for rotation constraints. I’ve put it as a local function for clarity, but in my code it’s just checking that euler.x
and euler.z
are within +/- (PI * 0.5)
inline.
1 Like
So, I found a solution to my original problem.
var x_bas = Basis.IDENTITY
var pitch_angle = 0.0
func camera_look(event: InputEventMouseMotion):
var mouse_delta: Vector2 = -event.relative * sensitivity
x_bas *= Basis(Vector3.UP, deg_to_rad(mouse_delta.x))
pitch_angle = clamp(pitch_angle + mouse_delta.y, -90.0, 90.0)
var y_bas = Basis(Vector3.RIGHT, deg_to_rad(pitch_angle))
transform.basis = x_bas * y_bas.orthonormalized()
This will prevent the camera from tilting below or above 90 degrees. And there was really no need to use quaternions, because godot uses them anyway. As I understand it.
Thank you all for the answers!
Yes, it occurred to me, but I didn’t figure out how to implement it. For some reason, I thought that quaternions cannot be converted to Euler angles. Thanks!
No need to have camera rotation be in a basis.
I did that once, and it’s really not fun.