0 like 0 dislike

I have a single infinite particle I want to move around randomly in a radius. Created a turb field and in the evolver script I put: 

Position = Turb_1.sample(Position);

Works as expected except I can't TimeScale in the Turb itself. I tried 0.1, 0.001... nothing. Is this a bug or am I doing something wrong?

Thank you!

by gtapperdesign (1k points)

1 Answer

0 like 0 dislike

Hi Greg,

Unless you're forcing 'Position' to another value earlier in the evolve script, such as "Position = rotate(scene.axisSide(), scene.axisUp(), scene.Time)", using the turbulence like this to move the Position is unstable.

you should either do:

Position += Turb_1.sample(Position) * dt; // move the position along the turbulence, treating the turbulence as a velocity-field

or (which is what seems to be what you're after)

Position = Turb_1.sample(StartPosition);

or, rephrased:

DrawPosition = Turb_1.sample(Position);

This should solve your main problem of "TimeScale" not working (which produces a particle that seems to just jitter around randomly)

(I can elaborate on the reason why doing "Position = Turb.sample(Position)" each frame is unstable if you're interested).

by Julien (35.2k points)
Yeah, I'd love to know more about why it's unstable. Hopefully helps prevent running into a turb issue in the future.

<Position = Turb_1.sample(StartPosition);> makes more sense anyway since I want it to stay around a single point, where sample(Position) would move in the range from the new point... I'm not even sure how sample(Position) worked now that I think about it.
Consider the case when the timesteps between frames are infinitely small (like, 0, as if it was paused (except popcorn doesn't call the updates when it's paused, but for the sake of the example, consider it does))

Repeatedly doing Position = Turb.sample(Position), with a dt of 0 (sim paused), will still change "Position", whereas you don't want it to, you want to move smoothly around "Position", small 'dt's should produce small changes, large 'dt's should produce large changes, as more time has passed, and a dt of zero should produce no change. Here we can trivially know it's broken with that extreme "zero dt" example, because it will obviously change, whereas it obviously shouln't.
I find using those kind of extreme mental examples to fail-proof a concept to be extremely helpful. ask yourself "how does this part of my script behave in those two extreme conditions?" like, a timestep of 0 seconds, and a timestep of 10 seconds. Even though it won't happen in a real world scenario, it quickly gives an idea of the "limits" of your function, and you can quickly check it matches what you're expecting.

Now, doing Position = Turb.sample(Position) will sample the turbulence at a different point every single time, because the turbulence field isn't an identity field, when you sample it at 'x', it doesn't return 'x', it returns a different value, so that means that with the aforementioned script, every single call to 'sample' will return a different value, which will be then fed to the next 'sample', which will return a different value, etc, etc.

This effectively produces a per-frame totally non-coherent random jittering.

Here's a more "geometric" / visual representation of what happens:
imagine you're standing on a terrain.
The slope of the terrain can be seen as a 2D turbulence field, similar to the 3D turbulence field sampled by the turbulence sampler.
you're at location "x", you then look at the terrain slope vector, take that value (which is a direction), and say "okay now I'm gonna go at the world location whose coordinates match this direction vector I just sampled".
Then once you're there (probably a totally different location), you sample the terrain slope again, which gives a totally different vector, you then reinterpret that vector coordinates as a world location, and go there, where you sample the slope again, which gives another different vector, etc, etc..
and you end up jittering around your terrain, just like the particle jitters around the turbulence field :)