-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Make VariableCurve
into curves
#13105
base: main
Are you sure you want to change the base?
Conversation
Curve
with bevy_animation
Curve
with bevy_animation
Hey cool stuff. However I think it would be important to keep a baked animation data at all times. With curves it's really conveniant to work and modify animations which I would love but to actually play them having to compute curve values every frame would be loss of performence compared to baked animation. |
This is pretty much a direct drop-in replacement for how animation currently works in Bevy (which is to say, there is no baking). It also doesn't really preclude things like baking |
I believe right now the transform values are lerped between previous and next key which will always be the case because of variable frame durations. The lerp function comes from the glam crate which is using SIMd making this operation very fast. |
Actually, I think that One advantage of this is that if we do ever actually want to bake anything, the |
I was looking at lib.rs in |
Ah; |
Ok I see, we should probably look into code optimization on this topic later. Even the tweened keyframe function is doing a few unecessary copies :
The keyframe update functions should be very fast compared to data management functions which can take there time. But yeah lots of things to do ^^ Having curves is already a huge plus. Would be interesting to reimplement all the actual curve evaluations in SIMd as well |
Curve
with bevy_animation
VariableCurve
into curves
Note: This PR is on top of #12932. About 2000 lines of code in this branch are just from that PR.
Objective
Presently, the main notion of curve in
bevy_animation
isVariableCurve
, which is essentially a way of organizing an imported glTF animation. This RFC demonstrates a reorganization of this data so that eachTransform
component andMorphWeights
curve is actually aCurve
, with its glTF interpolation modes reified by curve structs that implement them on the underlying data buffers.This has several advantages:
Solution
VariableCurve
, along with the code that loads it and uses it, has been completely overhauled.VariableCurve
is still an enum, but it is split up in a different way:Each of the
Transform
component curve types here is actually aCurve
, but they are still enums, broken down by mode of interpolation; for example, here isRotationCurve
:Some of the curve representations that appear here are new, such as
SteppedKeyframeCurve
andCubicKeyframeCurve
— these belong tobevy_animation
, and are built on the data structures frombevy::math::curve::core
, which handles the data storage and access patterns. Others, likeUnevenSampleAutoCurve
andConstantCurve
, are taken "off-the-shelf" from the Curve API.Its implementation of
Curve<Quat>
essentially just matches over the variants. (The last one requires special handling to do quaternion normalization, but that's about it.)Allocation-free
Curve<Vec<T>>
Since the definitions implicit in the Curve trait would require that anything that looks like a
Curve<Vec<T>>
allocates to produce owned output, this PR introduces an offshoot trait which mitigates this problem —IterableCurve
:This is used in concert with the core data structures from the Curve API to sample from keyframes valued in morph weights without ever allocating, all backed by a contiguous buffer of output data.
Performance
This is probably one of the biggest concerns about substantial changes to
VariableCurve
, so let me be proactive in addressing this.First of all,
VariableCurve
has not changed in size (still 64 bytes); this is because the backing data for every curve is at most a pair of vectors — 48 bytes in total, plus 16 bytes for enum discriminants. This is important for caching reasons.Secondly, proactive measures have been taken to ensure that the curves are designed with good cache locality properties, internally using a
Vec<f32>
for keyframe times paired with a contiguous buffer of sample dataVec<T>
which is sliced up to actually perform sampling. One nice thing is thatbevy_animation
is not doing any very fancy gymnastics here; it's mostly just using thebevy_math::curve::core
APIs as someone would in user-space. TheIterableCurve
abstraction mentioned above allows these niceties to extend to the case of morph weights without allocation concerns.Finally, preliminary performance data from tracing looks pretty good (huge grain of salt — just my machine, on this one example, etc.). Here is a fairly typical example from
![Screenshot 2024-06-12 at 2 57 51 PM](https://private-user-images.githubusercontent.com/2975848/339106800-0786e71e-627e-4f6d-8c0d-6cf01bab42de.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjExOTUwNzksIm5iZiI6MTcyMTE5NDc3OSwicGF0aCI6Ii8yOTc1ODQ4LzMzOTEwNjgwMC0wNzg2ZTcxZS02MjdlLTRmNmQtOGMwZC02Y2YwMWJhYjQyZGUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDcxNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA3MTdUMDUzOTM5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZWI4OTQwZjI1MjFlN2ViZmM5ZjI4ODZkZjlkNGUxYzJiZmExNDFhNWUwZTA3MDVlNzU3NzM5MzU3NTZiOGI5YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.yjbDCb1ec0NGKQQW7fxn4PeSJoldgp24864nCviyr2I)
many_foxes
running single-threaded on my M1 Macbook Air:(
animate_targets
— The yellow histogram is this branch, while the red branch is main. )Under these circumstances, I see a consistent, modest performance improvement in the ballpark of ~10%.
One thing that I really want is a broader base of examples to pull from for performance benchmarking our animation systems, to get a better idea of the potential impact under realistic circumstances.