diff --git a/code/core/elements.py b/code/core/elements.py index acc7ef5..accb1f4 100644 --- a/code/core/elements.py +++ b/code/core/elements.py @@ -1772,6 +1772,8 @@ def Xform "explosion" ( layer_identifier = "ref_layer.usd" stage_fps = 24 stage_identifier = "root_layer.usd" +frame_start = 1001 +frame_end = 1025 # Create layer reference_layer = Sdf.Layer.CreateAnonymous() @@ -1780,9 +1782,14 @@ def Xform "explosion" ( prim_spec.specifier = Sdf.SpecifierDef prim_spec.typeName = "Cube" attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double) -for frame in range(1001, 1005): - value = float(frame - 1000) +for frame in range(frame_start, frame_end + 1): + value = float(frame - frame_start) + 1 + # If we work correctly in seconds everything works as expected. reference_layer.SetTimeSample(attr_spec.path, frame * (layer_fps/stage_fps), value) + # In VFX we often work frame based starting of at 1001 regardless of the FPS. + # If we then load the 25 FPS in 24 FPS, USD applies the correct scaling, but we have + # to apply the correct offset to our "custom" start frame. + # reference_layer.SetTimeSample(attr_spec.path, frame, value) # FPS Metadata time_samples = Sdf.Layer.ListAllTimeSamples(reference_layer) reference_layer.timeCodesPerSecond = layer_fps @@ -1793,8 +1800,12 @@ def Xform "explosion" ( # Create stage stage = Usd.Stage.CreateInMemory() -# Without scale +# If we work correctly in seconds everything works as expected. reference_layer_offset = Sdf.LayerOffset(0, 1) +# In VFX we often work frame based starting of at 1001. +# If we then load the 25 FPS in 24 FPS, USD applies the correct scaling, but we have +# to apply the correct offset to our "custom" start frame. +# reference_layer_offset = Sdf.LayerOffset(frame_start * (stage_fps/layer_fps) - frame_start, 1) reference = Sdf.Reference(reference_layer.identifier, "/bicycle", reference_layer_offset) bicycle_prim_path = Sdf.Path("/bicycle") bicycle_prim = stage.DefinePrim(bicycle_prim_path) diff --git a/docs/src/core/elements/animation.md b/docs/src/core/elements/animation.md index 39f4c8d..4bc79ee 100644 --- a/docs/src/core/elements/animation.md +++ b/docs/src/core/elements/animation.md @@ -222,6 +222,12 @@ Therefore when writing layers, we should always write these layer metrics, so th the original intended FPS were and our caches work FPS independently. ~~~ +~~~admonish warning +In VFX we often work starting from 1001 regardless of the FPS as it is easier for certain departments like FX to have pre-cache frames to init their sims as well as it also makes it easier to write frame based expressions. That means that when working with both 25 and 24 FPS caches, we have to adjust the offset of the incoming cache. + +Let's say we have an anim in 25 FPS starting off at 1001 that we want to bring into a 24 FPS scene. USD as mentioned above handles the scaling for us based on the metadata, but since we still want to start at 1001, we have to offset based on "frame_start * (stage_fps/layer_fps) - frame_start". See the below commented out code for a live example. That way we now have the same 25 FPS cache running in 24 FPS from the same "starting pivot" frame. If we work fully time based, we don't have this problem, as animation in the 25 FPS cache would have its time samples written at larger frames than the 24 FPS cache and USD's scaling would auto correct it. +~~~ + ```python ( timeCodesPerSecond = 24