Open Remi123 opened 8 months ago
We can also rename get_twist
to get_rotation_around(axis:Vector3)
, but the swing doesn't have a good name that I can think off, since it's mostly the rest of the rotation from the twist.
What kind of twist-swing decomposition is this? twist-after-swing or swing-after-twist?
static func get_swing(q : Quaternion, axis : Vector3) -> Quaternion:
var twist := get_twist(q,axis)
var swing := -(q.inverse() * twist)
return swing
This code is weird. Why the minus sign? Also, the quaternion multiplication seems to be wrong. In the case of swing-after-twist decomposition we have:
q = swing * twist
therefore
swing = q * twist.inverted()
@WojtekPachowiak The calculation presented in the proposal isn't erroneous, as it give the correct swing and twist. but it wasn't constant when multiplying them back together since quaternion have two valid representation. It wasn't possible to do something like this :
var v := Vector(...)
var q := Quaternion(...)
var swing := q.get_swing(v)
var twist := q.get_twist(v)
assert(swing * twist == q)
I've fixed this in the PR at https://github.com/godotengine/godot/pull/87285
Describe the project you are working on
3D platformer
Describe the problem or limitation you are having in your project
Godot provide a good interface to interact with Quaternion, However it can be difficult to retrieve the rotation around an arbitrary axis from a Quaternion. Fortunately, there exists an algorithm to do exactly that : The Swing-Twist Decomposition.
This separate the quaternion into two sub-quaternion, the swing and the twist. While the name aren't exactly descriptive, it use the twist to describe the rotation around the axis, and the swing as "the rest" of the rotation.
You can use this for a number of use case. I personally use it in my character code to align the velocity to the floor normal, and also extract the hips rotation to place it on a new root bone in case the animation have hips as the root bone.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Add two functions to Quaternion :
func get_swing(axis:Vector3)->Quaternion
andfunc get_twist(axis:Vector3)->Quaterion
.Most of the implementation uses reference parameter to decompose the quaternion into two, using the same function. While great and very slightly more performant if you need the swing, the twist is the main part of the function and should, in my opinion, be its own function.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
The code below is what I use, but those are static function, so the change will be added to the quaternion interface and be called like
myquaterion.get_twist(Vector3.UP)
If this enhancement will not be used often, can it be worked around with a few lines of script?
It's a very simple addition to the engine.
Is there a reason why this should be core and not an add-on in the asset library?
It's too simple to not add to core.