Ok just for the sake of discussion here's a homemade lookat()
without quaternions:
func lookat(from: Vector3, to: Vector3, up: Vector3 = Vector3.UP) -> Basis :
var basis: Basis
basis.z = (from-to).normalized()
basis.x = up.cross(basis.z).normalized()
basis.y = basis.z.cross(basis.x).normalized()
return basis
We can test it by comparing its output with what Node3D::look_at()
does:
# some random from and target
randomize()
var from = Vector3(rand_range(-100.0, 100.0), rand_range(-100.0, 100.0), rand_range(-100.0, 100.0))
var target = Vector3(rand_range(-100.0, 100.0), rand_range(-100.0, 100.0), rand_range(-100.0, 100.0))
# test node's look_at()
var node = Spatial.new() # or Node3D.new() for Godot 4
get_tree().get_root().add_child(node)
node.translation = from
node.look_at(target, Vector3.UP)
print(node.transform.basis)
# test our lookat()
print(lookat(from, target, Vector3.UP))
Results are the same:
((-0.575881, 0.566949, 0.589007), (0, 0.720469, -0.693488), (-0.817534, -0.399366, -0.414904))
((-0.575881, 0.566949, 0.589007), (0, 0.720469, -0.693487), (-0.817534, -0.399366, -0.414904))
((-0.531516, -0.637291, 0.557988), (0, 0.658744, 0.752367), (-0.847048, 0.399895, -0.350133))
((-0.531516, -0.637291, 0.557988), (0, 0.658744, 0.752367), (-0.847048, 0.399895, -0.350133))
((-0.892539, 0.08448, 0.442987), (0, 0.982297, -0.187329), (-0.45097, -0.167198, -0.876739))
((-0.892539, 0.08448, 0.442987), (0, 0.982297, -0.187329), (-0.45097, -0.167198, -0.876739))