0
$\begingroup$

I am following this tutorial on the new simulation nodes: https://www.youtube.com/watch?v=RJbLiFTNHnI. At around the 12 minute mark, I have some confusion. In particular, as to why some data passed into the simulation zone seems to get added on every iteration, and some does not. Here is my node setup, note that I have removed the 'Join Geometry' node to make a more simple version where there it only one, initial, instantiation of points: enter image description here

There are two places in this node setup where the velocity is manipulated, which I label here as '1' and '2': enter image description here

At '1', the velocity is incremented by a constant amount on each iteration, recreating the effect of a constant force, such as gravity.

At '2', this vector addition is used to ensure that when we are creating points with each iteration, all these points get random initial velocities, rather than just the points created on the first iteration.

Recall, however, with the 'Join Geometry' node omitted, there is only one instantiation of these points. It seems, in my ignorance, that these points should get the random vectors provided from the 'Capture Attribute' node added to their velocities on each iteration, in the same way that the velocity is modified to simulate gravity. This is not the case, though.

Why?

Thank you in advance.


Extra detail in response to comments:

Example node group again: enter image description here

I will mute one of the vector add nodes: enter image description here

When I play the animation, all particles move in the direction indicated, as we are adding the vector constant at the bottom of the node structure on each iteration: enter image description here

Now let's mute the other one instead: enter image description here

On playing the animation, I would expect the particles to expand along the vectors defined by the random value vector at the bottom left; I would expect the remaining vector add node to also be executed on each loop. Instead, the particles do not move at all.

$\endgroup$
5
  • $\begingroup$ he said in the video, that all nodes before the zone (connected via the green lines) will only executed once (!) so does the capture node. Just plugin the random value directly in your add node. Hope that helps. $\endgroup$
    – Chris
    Jul 4, 2023 at 5:46
  • $\begingroup$ Might be a good opportunity to add a 5th post to my series on how to read and reason about geonodes trees 🤔 $\endgroup$ Jul 4, 2023 at 12:04
  • $\begingroup$ @Chris yes I understand that, for example, the capture attribute only gets executed once. However, why does the add node I label as '2' only execute once. By contrast, the node labelled '1' gets executed every time. Similarly, the 'join geometry' node, if the output were connected as per the video, would also execute on each loop iteration. $\endgroup$
    – d401tq
    Jul 4, 2023 at 17:32
  • $\begingroup$ Why do you think the "2" node only executes once? It actually executes twice as often as "1". $\endgroup$ Jul 4, 2023 at 17:35
  • $\begingroup$ Added extra detail in question. $\endgroup$
    – d401tq
    Jul 4, 2023 at 17:47

1 Answer 1

5
$\begingroup$

Here we go again… This is my 5th post in the series on how to read Geometry Nodes trees, here's links to the previous posts that I recommend reading first (they are long, but it is the best way to actually understand what's going on instead of pulling your hair on why nodes don't do what you want them to do; I really wish someone wrote something like that when I was starting with geonodes):

So now let's look into your tree:

  • Join Geometry node is muted. Even if it wasn't, nothing is connected to it from the right. And since nodes are evaluated from the right side, nothing executes this node, and so even if unmuted, this node won't run.
  • Since Join Geometry doesn't execute, it also doesn't execute the Capture Attribute node. However, there is something else connected to this node. I decided to cross this link with yellow color, because I'm defensive against "ackchyually" pedants, but if you disregard side effects like performance (node taking time to execute), you can think of it as not running: please refer to the third link above, which explains that in order to read the anonymous attribute, you need to have access to the table stored in the geometry going out of the Capture Attribute. Think of it this way: having a password to encrypted data is only half of the requirement to read the data - you also need to have the encrypted data to begin with!
  • (1) The execution starts with either Group Output or Viewer.
  • (1) requests 🟢 Geometry from (2) Simulation Output.
  • (2) Sim Out requests 🟢 Geometry from (3) Set Position.
  • (3) Set Pos requests 🟢 Geometry from (4) Simulation Input.
  • (4) Sim Input either reads 🟢 Geometry from cache: current_frame-1, or if the first frame is being evaluated:
    • (4) Sim Input requests 🟢 Geometry from (5) Distribute Points on Faces.
    • (5) D. Pts on Faces requests 🟢 Geometry from (6) Group Input, gets it, and then for each frame in that geometry it requests $\color{#538257}{\bullet}$ Seed from (7) Scene Time: Frame (and since this inner bullet point list means we're in the first frame, we know this value is always 1). Then it generates random points, and saves the result to its right output socket Points 🟢.
    • (4) Sim Input reads the Points as 🟢 Geometry, and then for each element (point), it stores an anonymous attribute (just like a Capture Attribute or Group Output would¹) by setting the current context to currently processed element and then requesting the 🔹 Velocity from (8) Random Value.
    • (8) Random reads the ID of the current context (point; by default it's the point index), and returns it to the requestor.
    • (4) Sim Input finally gets the random value for the last point, finishes assembling the data, and now can return this data just as if it wasn't the first frame and it was reading from cache.
  • (4) Sim Input returns the requested 🟢 Geometry to (3) Set Pos.
  • (3) Set Pos iterates over all points:
    • Sets the context to the next point.
    • Requests 🔹 Offset from (9) Vector Math: Scale.
    • (9) Scale requests 🔹 Vector from (10) Vector Math: Add.
    • (10) Add requests 1st ↑🔹 Vector from Capture Attribute - problem is, the currently evaluated context (point) doesn't have this attribute stored, so all you're going to get is 0.
    • (10) Add requests 2nd ↓🔹 Vector from (11) Sim Input (I incremented the node number, because it's the 2nd time this node is accessed). Here the sim input works just like a Capture Attribute node¹.
    • (10) Add adds both vectors, but since the 1st ↑ is $<0, 0, 0>$, it effectively just passed the 2nd ↓🔹 Vector back to (9) Scale.
    • (9) Scale now also requests the scalar ⟐ Scale from (4) Sim Input, which is a constant, and within a single frame will be the same (and also if your framerate is constant and stable, will be the same throghout the animation). Assuming 25 FPS, it's always going to be 0.04.
    • (9) Scale now multiplies the vector by the scalar and returns it to the requesting (3) Set Pos.
    • (3) Set Pos offsets the currently evaluated point by the given vector and this inner bullet point list repeats, unless there's no more points, in which case continue reading below.
  • (3) Set Pos finished and returns modified data to (2) Sim Out.
  • (2) Sim Out stores obtained 🟢 Geometry in cache: current_frame, though it still needs to calculate the anonymous attribute (like a Group Output¹ would) for each element, so just like the Set Pos, it iterates:
    • Sets the context to the next element (here it's just points).
    • Requests 🔹 Velocity from (12) Add.
    • (12) Add requests 1st ↑🔹 Vector from another (13) Add (notice it's the same as (10) Add, but it could as well be a ✲ Ctrl⬆ ShiftD duplicated-with-links node and it would be equivalent). (From now on not a lot of interesting stuff, a lot of copy-pasting of already explained stuff, just happening elsewhere.)
    • (13) Add requests 1st ↑🔹 Vector from Capture Attribute - problem is, the currently evaluated context (point) doesn't have this attribute stored, so all you're going to get is 0.
    • (13) Add requests 2nd ↓🔹 Vector from (14) Sim Input (I incremented the node number, because it's the 3rd time this node is accessed). Here the sim input works just like a Capture Attribute node¹.
    • (13) Add adds both vectors, but since the 1st ↑ is $<0, 0, 0>$, it effectively just passed the 2nd ↓🔹 Vector back to (12) Add.
    • (12) Add requests 2nd ↓🔹 Vector from (15) Scale.
    • (15) Scale requests 🔹 Vector from (16) Vector. It's always a constant $<0, 0, -0.2>$.
    • (15) Scale now also requests the scalar ⟐ Scale from (4) Sim Input: Delta Time, which I already assumed is always 0.04.
    • (15) Scale now multiplies the vector by the scalar and returns it to the requesting (12) Add.
    • (12) Add sums up those two vectors and returns to (2) Sim Out.
    • repeat this inner bullet point list, unless there's no more elements, in which case continue reading below.
  • (2) Sim Out finally assembled all data, joins the anonymous attribute together with the geometry in the cache, as well as returns this (most recent, just obtained) 🟢 Geometry to the (1) Viewer.
  • In the next frame, nodes (5), (6), (7), (8) won't be evaluated, instead, just evaluated geometry will be accessed from cache by the Sim Input.

¹ - actually not 100% sure of that one, will test it eventually and modify this answer.

What have we learned?

  1. The node you marked as 2 not only will be evaluated, but it will be evaluated twice per iteration: (10), (13), twice as often as the node you marked as 1, which evaluates only once per iteration: (12).
  2. The node you marked as 2 does work, or at least to my understanding should work, where by "work" I mean that muting it should change the effect, because muting it will pass the first input (zeroes), while currently it passes the 2nd input (unchanged by adding zeroes to it).
  3. Not only Join Geometry is irrelevant to the setup, but also the Capture Attribute node.
  4. If you share your .blend file I might investigate further.
$\endgroup$
1
  • $\begingroup$ Thank you very much for the detailed answer. I think I have a better intuition for the data flow etc. within geometry nodes. I think better documentation from Blender on these formal conventions and what is going on under the hood would be great. $\endgroup$
    – d401tq
    Jul 5, 2023 at 2:15

You must log in to answer this question.

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