Page MenuHome

Alembic: F-Curve cache modifier to lookup arbitrary property animations.
Needs RevisionPublic

Authored by Kévin Dietrich (kevindietrich) on Oct 30 2016, 6:39 AM.



The main goal of this F-Curve modifier is to support cached animations
of camera focal length and is generalized to support looking up
animations of any single float property of the Alembic object pointed by
the modifier. Perhaps in the future we could also support array
properties, in which case the current scene frame would be the index in
the array.

The Alembic Import operator should automatically add a keyframe and F-
Curve cache modifier to imported cameras if they have an animated focal

A cache is used to gather F-Curves modifier using cache files. This is
to make it easier to manage pointers rather than iterating on all possible F-
Curves of a given object when updating a CacheFile data-block to figure
out whether or not it is using said CacheFile. Though it is not the
ideal solution, and should be handled by some depsgraph mechanism.

Diff Detail

rB Blender
Build Status
Buildable 255
Build 255: arc lint + arc unit

Event Timeline

Kévin Dietrich (kevindietrich) retitled this revision from to Alembic: F-Curve cache modifier to lookup arbitrary property animations..
Kévin Dietrich (kevindietrich) updated this object.
Joshua Leung (aligorith) requested changes to this revision.Oct 30 2016, 7:49 AM
Joshua Leung (aligorith) edited edge metadata.

I'm missing a bit of detail here about the nature of the cache. One thing to be very careful about if you do implement a list of pointers to FCurves is that those references can get invalid/not linked correctly after doing:

  1. Undo
  2. Some combination of library linking madness

For what you're doing here, it might be more direct to just call: verify_adt_action() followed by verify_fcurve()
So, something like:

bAction *act = verify_adt_action(&bcam->id, true);
FCurve *fcu = verify_fcurve(act, NULL, path, -1, true);

EDIT: Was there any reason why you had it add a keyframe, because it isn't really necessary to have a keyframe to be able to add FModifiers.


Better to use a constant or sizeof(cache_mod->property) instead of hardcoding this here?


Er... what's going on here with the comments? Is this to get around some complier warnings about unused vars?

I'm not sure about the C++ side of things, but usually we use the UNUSED() macros around these kinds of vars.


Hardcoded sizes again


So does this cache span across datablocks, or is it just a per-datablock kind of setup?

If cross datablock, you have to be careful about issues to undo/linking stuff if you store pointers to those FCurves anywhere...


This label seems vague: What is it that the object path/properties fields set?

I'm guessing something like: "Source Data:" might make more sense in this case then?


You could use BLI_findstring() here too


You could use BLI_findstring here instead of doing this loop (it does it for you). So something like:

AlembicObjectPath *path = BLI_findstring(&cache_file->object_paths, data->object_path, offsetof(AlembicObjectPath , path));
This revision now requires changes to proceed.Oct 30 2016, 7:49 AM
Kévin Dietrich (kevindietrich) edited edge metadata.
Kévin Dietrich (kevindietrich) marked 6 inline comments as done.
  • Handle review points:

As said in inline comments, there is no global cache, but each CacheFile data-block has its own cache. So there shouldn't be too much issues regarding undo and library linking? It's really here to fill a dependency graph gap, where you don't know which F-Curve modifier depends on which CacheFile.


I coded that like I would do it in the UI, that is first adding a keyframe and then going to the graph editor to add the F-Curve modifier. Thus there is a keyframe. (And I didn't know you could do it without one.)


The comments were indeed for quieting warnings, but those variables were only necessary to add a keyframe, they are removed now.


Each CacheFile data-block has its own little cache, only internal stuff, no sharing. I'll clarify the comment about this.


This label is to align with the Mesh Sequence Cache modifier and Transform Cache constraint UI. Basically since those modifiers and constraints display both the UI for the CacheFile data-block they point to and their own properties, I added these labels (along with boxes) to hint the user about which settings affect the cache files and which ones affect the modifiers and constraints individually.

So "Modifier Properties" are the properties of the F-Curve modifier, not necessarily the source data (from the Alembic file).

Here's some visual:

Ah that clears things up a lot :D

I'll take another look later when I'm back on my computer

@Joshua Leung (aligorith): any news on this?


This is not so nice. We need the FPS value from the scene here, not sure how to get it from the f-curve modifier (if even possible), so it is hardcoded to 24.0f for now...

This revision now requires changes to proceed.Feb 11 2018, 2:26 PM

@Sybren A. Stüvel (sybren): does this fit into your plans? [also regarding work on USD]

@Sybren A. Stüvel (sybren): does this fit into your plans? [also regarding work on USD]

The plans I describe in T69046: Cache loading via animation system are inspired by this diff. Here Kévin shows the shortcomings of the current animation system:

  • For each non-transform property animated by Alembic, an FCurve modifier is needed. This doesn't support updating the Alembic file after loading it, as these FCurve modifiers are only created at import time (and not just when reopening the blend file).
  • Having an FCurve modifier (which is a DNA datablock) for every animated property may get CPU-heavy when many properties are animated.
  • Alembic placed multiple camera properties into one Alembic schema. This schema has an isConstant() method that indicates whether the data is constant or animated, but since this schema contains multiple properties, it's still unclear which exact property is animated. To figure this out, Kévin wrote code to analyse the entire Alembic file to see whether values changed. This works, doesn't scale to large files with many (potentially) animated properties.

It is because of this that I want to have a more direct way to load/animate properties from a cache file. Having cache files as a 1st class citizen, rather than something that's only loaded via constraints and modifiers, seemed like a good approach to me.