-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Additive blending of Quats looks suspect #13832
Comments
I also wonder how this works with adding multiple additive animations. (That is an intended use-case right?) To me it looks like we're trying to exponentiate group elements here. We have some group G (of translations, rotations, etc...) we are animating and we have a sample We then want to introduce a real-number weight parameter This points me to the idea that we're looking for an operation of group exponentiation
As far as I know, the sound way to mathematically define this is to: In the case of translations, the group of vectors is already the lie algebra, hence no visible mapping happens and we just do the vector scaling. TL;DR: From a math standpoint I believe that the code is wrong and the new proposal is sound. |
I think left-composing might be the correct option, because it applies the additive operation "after" the base one, which sounds more like the expected behaviour of "adding on top". But I can't speak for animation. |
Yes I'm convinced the current code is wrong as commented in the original PR #4482 and I had linked an animation article coming to the same conclusions as above that you need to slerp with identity. See also #4482 (comment) which I don't necessarily agree (I'm not sure) with but would have been worth an answer too. |
# Objective Fixes #13832 ## Solution Additively blend quaternions like this: ```rust rotation = Quat::slerp(Quat::IDENTITY, incoming_rotation, weight) * rotation; ``` ## Testing Ran `animation_masks`, which behaves the same as before. (In the context of an animation being blended only onto the base pose, there is no difference.) We should create some examples that actually exercise more of the capabilities of the `AnimationGraph` so that issues like this can become more visible in general. (On the other hand, I'm quite certain this was wrong before.) ## Migration Guide This PR changes the implementation of `Quat: Animatable`, which was not used internally by Bevy prior to this release version. If you relied on the old behavior of additive quaternion blending in manual applications, that code will have to be updated, as the old behavior was incorrect.
I believe this was previously noticed by @djeedai in the review of the
Animatable
trait rollout.I am not an expert in this subject, but here is my understanding.
Context
In additive animation blending, a sample from an animation clip represents a relative displacement rather than an absolute quantity; this is applied on top of other animations by combining the displacement with the absolute quantity "underneath". Like non-additive animation blending (which interpolates between two absolute quantities instead), this can be used in concert with a weight which indicates the strength of the sample's influence in the blend. For additive blending, this means that, as the weight tends to zero, the displacement also attenuates; with a weight of zero, the blend should have no effect on the existing quantity.
For example, additive blending of translational components works something like this:
The right-hand side of this is perhaps best conceptualized as:
In other words, the additively blended sample is interpolated with zero and then composed with the existing value.
The mismatch
Now, currently additive blending for Quat works like this:
What I would expect based on my understanding of additive blending is instead something like this:
Note that these are definitely not equivalent — when the incoming sample is
Quat::IDENTITY
, the latter never has any effect, while the former (with positive weight) will slerp the current rotation state towards the default orientation.Of course, it's possible this was an intentional decision and I'm missing something; this is just my understanding of things.
The text was updated successfully, but these errors were encountered: