i ended up here trying to do rotations w/ Godot quaternions like this:
var target: Transform3D = ...
target.quaternion *= Quaternion(from: Vector3, to: Vector3)
the result i was getting was pretty wacky and seemed inexplicably to carry some extra rotation along the to
axis
so i started digging...
handle rotations from one Vector3
to another Vector3
this way in the snippet works more as expected versus applying it w/ Godot quaternions eg. via Quaternion(from: Vector3, to: Vector3)
to be sure, simply changing the way at the end the rotation is derived and applied (w/
axis
andangle
) to instead go through their quaternions (ie.target.quaternion *= Quaternion(axis, angle)
) gets us back to the wrong result again.
so what's going on - what makes the non-quaternion implementation work correctly?
[π Node3D.global_rotate(axis: Vector3, angle: float)
...]
- https://github.com/godotengine/godot/blob/ba54c34551d1bda5139515d74e7d614ccbc43cea/scene/3d/node_3d.h#L250
- https://github.com/godotengine/godot/blob/ba54c34551d1bda5139515d74e7d614ccbc43cea/scene/3d/node_3d.cpp#L884
ok so its just using Basis
to handle the rotation
[π Basis.rotate(axis: Vector3, angle: float)
...]
- https://github.com/godotengine/godot/blob/ba54c34551d1bda5139515d74e7d614ccbc43cea/core/math/basis.cpp#L334
- https://github.com/godotengine/godot/blob/ba54c34551d1bda5139515d74e7d614ccbc43cea/core/math/basis.cpp#L330
[π Basis(axis: Vector3, angle: float)
...]
https://github.com/godotengine/godot/blob/master/core/math/basis.cpp#L826
so it uses trigonometry to derive...
[π Basis
multiplication...]
then it uses matrix multiplcation to apply...
for comparison, what's going on w/ the corresponding quaternion functions that seem bugged?
[π Quaternion(axis: Vector3, angle: float)
...]
[π Quaternion
multiplication...]
- https://github.com/godotengine/godot/blob/16a93563bfd3b02ca0a8f6df2026f3a3217f5571/core/math/quaternion.cpp#L49
- https://github.com/godotengine/godot/blob/ba54c34551d1bda5139515d74e7d614ccbc43cea/core/math/quaternion.cpp#L59
now full circle back to initial problematic quaternion function that kicked off this whole discovery...
[π Quaternion(from: Vector3, to: Vector3)
...]
these two are not equivalent:
target.basis *= Basis(axis, angle)
target.quaternion *= Quaternion(axis, angle)
the former produces the correct result, while the latter does not.
turns out their quaternions are fine and it was a mistake w/ applying them, so disregard conclusions made above!
instead of this:
quaternion *= Quaternion(axis, angle)
it should've been:
quaternion = Quaternion(axis, angle) * quaternion
quaternion multiplication is not commutative https://chat.openai.com/c/16e051c8-14d3-4a4d-923e-f6330cc1b707 and i would've have realize this until digging into the source files above π₯² gg friends.