3
$\begingroup$

I'm trying to find a way to loop a geometry nodes simulation. It's a bunch of self-colliding objects, so I suspect the answer is going to be slightly hacky.

My most functional idea is to bake the simulation (which I've done) and then offset a copy of the baked simulation in time so the end of the animation looks like the start.

My issue is that I'm not quite sure how to offset the baked simulation. Ccould anyone help point me in the right direction?

$\endgroup$

2 Answers 2

3
$\begingroup$

Workaround

I don't think there's an option to do that efficiently... That's why I'm sad the simulations are designed this way, I'd much prefer a "save data" and "load data" nodes, which would allow to easily reproduce simulations, read $n$ frames backwards (or forward!) etc...

Here's the workaround: let's start with a simple simulation, on purpose not even using geometry in the simulation zone:

Now, you could just reset the simulated values to starting values on every $n$ frames if the effect of repetitiveness is what you're after - that's however already achieved in the node tree I presented. So the other reason why you would want to reuse a simulation zone cache memory usage. You could do it like this (be sure to read the caveats below):

The animation above is 40 frames long. So in the .blend file I also set the Loop Length to 40. This makes the same animation:

But what if I change the the Loop Length - then you will be able to see the setup really repeats the simulation (and since the only thing using Loop Length inside the simulation zone, controls he Skip, you know the simulation is not rerun, it's just the once generated data that is being reused):

Performance caveats

  • Using geometry to store the data adds some overhead - point clouds have point coordinates for example - here I tried to minimize the overhead by storing data inside the vertex positions instead of new attributes. Still, the $z$ coordinates and radii are wasted.
  • On each frame you store also all previous frames, so on each frame, the cache size used just for this frame is the frame number. This means, that the cache size quickly explodes: on frame #1 you store just itself, so 1 frame. On frame #2 you store 2 frames, so the cache grows from 1 frame to 3. On frame 3 you store 3 frames, so the cache grows from 3 to 6 frames. So it clearly is a triangle, where the base and height of the triangle is the number of simulated frames, and the "area" of the triangle represents the cache used - every next frame uses much more resources.

The actual cost

The black vertical lines represent the resource usage. I've put the word "area" in quotes, because it's not exactly the area because discrete steps are used. You can calculate the number by taking the formula for Triangular number

$${\displaystyle T_{n}=\sum _{k=1}^{n}k=1+2+3+\dotsb +n={\frac {n(n+1)}{2}}={\frac {n^{2}+n}{2}}={n+1 \choose 2}}$$

>>> def when_worth_it(simulated_frames):
...     print(f"When simulating {simulated_frames} frames, the optimization pays off after {sum(i for i in range(simulated_frames+1))} animation frames.")
...     
>>> when_worth_it(1)
When simulating 1 frames, the optimization pays off after 1 animation frames.

>>> when_worth_it(2)
When simulating 2 frames, the optimization pays off after 3 animation frames.

>>> when_worth_it(3)
When simulating 3 frames, the optimization pays off after 6 animation frames.

>>> when_worth_it(4)
When simulating 4 frames, the optimization pays off after 10 animation frames.

>>> when_worth_it(40)
When simulating 40 frames, the optimization pays off after 820 animation frames.

So in this case, for the optimization pays off after 820 frames...

Other usages

Of course there are also different reasons to employ this technique. Imagine a parrot that repeats a sound multiple times after the inspiration became silent. So if the input at some point stops, but you want to repeat this behavior in the geonodes object, you would use a technique like this.

Also some heavy computations could be a reason to spend memory to not need to recalculate on each frame.

What if you started by using geometry

Then just before Simulation Output use Store Named Attribute to save current frame number, and join that geometry with previous geometry. Just after Simulation Input separate the geometry by using current frame minus one as a selection. Outside the simulation zone, separate the geometry by using the current frame modulo Loop Length.

$\endgroup$
2
$\begingroup$

enter image description here

Bake node should ideally have "offset" for time control like Alembic mesh sequence modifier.

I think the workaround I could think off, is to "bake still" or "bake animation" with custom range X to X. Then you use Index Switch to flipbook each mesh.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .