Skip to content

Conversation

SHARANcanCODE
Copy link

Description

This PR fixes issue #4160 where rendering a scene multiple times with caching enabled results in incorrect placement of objects that use always_redraw with ValueTrackers.

Problem Analysis

The issue was a variation of #550 where cached animations affected the global timestamp. When caching is used:

  1. Animations are skipped to improve performance
  2. However, scene.time is still incremented by the full animation duration
  3. ValueTrackers and other time-dependent objects remain at their initial state
  4. When always_redraw functions are evaluated, they use these incorrect initial values instead of the proper final values
  5. This causes objects to appear in wrong positions on subsequent cached renders

Root Cause

In the OpenGL renderer play method, when animations were skipped due to caching, the code would bypass scene.play_internal() but still increment self.time. This left all ValueTrackers and animated mobjects in their initial state while the scene time was at the end state.

Changes Made

  • Added proper final state interpolation when animations are cached and skipped
  • When skip_animations is True, call scene.update_to_time(scene.duration) to ensure all animations reach their final state
  • Call scene.update_mobjects(0) to update all mobjects after interpolation
  • Preserves the performance benefits of caching while ensuring consistent object placement

Testing

  • Verified that the fix properly interpolates animations to their final state when cached
  • Tested that normal (non-cached) animations continue to work as expected
  • The original failing scene should now render consistently on first and subsequent runs

Fixes

Closes #4160

Example Usage

The following code (from the original issue) should now render consistently on multiple runs with caching enabled:

class Sin2(Scene):
    def construct(self):
        ax = Axes(x_range=(-2, 2, 1), y_range=(-2, 2, 1), x_length=6)
        trigo_circle = Circle(radius=1.5)
        self.add(ax, trigo_circle, Dot(color=RED).shift(1.5*RIGHT))

        theta = ValueTracker(0)

        neg_point = always_redraw(
            lambda: Dot(
                trigo_circle.point_at_angle(-theta.get_value()),
                color=YELLOW
            )
        )

        neg_arc = always_redraw(
            lambda: Arc(radius=1.4, angle=-(theta.get_value() % TAU), stroke_width=2,
                color=YELLOW
            )
        )

        pos_neg = always_redraw(
            lambda: Tex(
                "^{-i \\theta}$",
                color=YELLOW
            ).move_to(0.6*neg_point.get_center())
        )

        self.add(pos_neg, neg_point, neg_arc)
        self.play(theta.animate(run_time=5).set_value(TAU))
        self.play(theta.animate(run_time=2).set_value(TAU+2.4))
        self.wait()

Deep Sharan added 3 commits August 31, 2025 20:56
…rs_to_display'

- Add missing default_numbers_to_display() method to NumberLine class
- Method returns tick range excluding numbers in numbers_to_exclude list
- Resolves issue where get_number_mobjects() would fail with AttributeError
- Fixes ManimCommunity#4244
…animations

- Add shape validation before interpolation in OpenGL mobject
- Handle shape mismatches gracefully by resizing target arrays
- Implement fallback mechanism using mobject2 data when interpolation fails
- Prevents ValueError crashes during very short run times or skip_animations=True
- Fixes ManimCommunity#4240
- When animations are cached and skipped, ensure proper final state interpolation
- Call scene.update_to_time(scene.duration) to set animations to their end state
- Update all mobjects after interpolation to reflect final animation values
- Ensures ValueTrackers and always_redraw functions have correct values on cached renders
- Fixes ManimCommunity#4160
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🆕 New
Development

Successfully merging this pull request may close these issues.

ManimCE 0.19.0 - caching issue
1 participant