Serial Loops [Proposal]

Oh yep, sorry I actually jumped to a conclusion sorry. What I was going on about was a function in the loop that allows to join every iterations result into 1 at the end. I saw “output previous” and put two and two together, that’s my bad.

And while I know this isn’t feature request, I think the serial loop should probably have a function like that. It’s not always used in simulations but often enough in procedural modelling. UI wise maybe a checkbox or drop down to choose the behavior.

That’s probably something better oriented to the parallel loops or lists in the future in my opinion. You can probably do that with this proposal already with the join geometry node anyway. But don’t expect it to be fast!

Awesome! Is there a way to get the current iteration integer within the loop with this design

3 Likes

Yes I was going to bring this up with a mock-up later, but I’m too busy atm. But accessing the iteration number to can work some real wizardry on things. Allowing different values for things on each iteration can make complex things very fast.

1 Like

This is possible by adding an integer item in the loop and add 1 in every iteration.

This is possible by adding an integer item in the loop and add 1 in every iteration.

That’s just building a for loop your self. If i have to keep track of the iteration count my self, I may as well add that one compare node in the end and do all of the work to make a for loop.

With the various loop styles, i’m starting to suspect the proposed node is too complicated and the “helping” that we are trying to do isn’t really helping as much and is just getting in the way.

I feel it may almost be better just to have something like this as a base building blocks

Enter determines if the loop is entered, if false the input Geometry is passed through to the output
Exit determines if the loop is exited

enter and exit are not as ambiguous as break and output previous and it allows people to build

  • for style loops
  • do { .. } while(x) loops
  • while (x) { ... } loops (somewhat clumsy since you have to implement the test twice, both for enter and exit conditions)

sure it be easy to make an infinite loop but i feel max_iterations was just a band-aid at best for a that problem (to be solved outside of this proposal) anyhow. It’s only helping me half way with a for loop, it doesn’t protect for the locking up blender problem, so … why does it deserve to be there? It seemingly brings very little to the table.

4 Likes

It may be a language thing but I don’t understand your objection to the max iterations socket. It’s very practical for when you don’t need to control dynamically the number of repetitions, which I’d expect to be a very common situation. If you look at the example Jacques showed with the simulation demo, for that situation and many it’s useful to define beforehand how many repetitions you want. Sure, there’s a version of that which keeps repeating until finding a perfect or perfect enough result and then breaks the loop, but many times that’s not needed, and it’s more cumbersome to manually break the loop.

The design I proposed is a generalized solution, any kind of loop can be expressed with it. They are building blocks to be build upon.

With that in place, we can certainly offer some specialization nodes like straight forward for loops that does have max_iterations (and should also have iteration) values. But those are specializations should not be part of the core implementation.

1 Like

I’m still not convinced on the benefit of having an explicit “Output Previous” option there.

Following that mantra of “Making simple things simple, complex things possible” I think we can try just supporting the basic Break first (which still returns the final result of the current loop evaluation).

Leaving the ability to stop before for artists to do at first with a Switch node. If that turns out to be a rather common case, we then can add this feature.

2 Likes

How would that work? :thinking:
I think having an iter int in the “Serial loop input” output would be quite handy (has been done elsewhere)

I don’t see much trouble in doing it manually

2 Likes

Is it actually the same though just to join? I might be derping pretty hard, but I think there are circumstances where that won’t work properly, like such:


Just an icosphere copying itself onto its own point, then again, silly fractal stuff.
In this case if I join the original geometry with the result of the tree, then duplicate the geometry nodes modifier (the current loop manual workaround) I will get nasty intersection on the inside:

Because naturally the next iteration has the original geometry and the whole tree, so the instance on points node will produce more copies than really wanted, ideally you just want the copies only from the instanced stuff on each iteration, only “growing” the stuff on the outside, and nothing on the inside pilling up. The wording here is is sort of hard to follow so as reference the desired look is more like this:

This is possible like so:

The instance on points node just leads directly to a new instance on points node, never touching the original input geometry, then you just join it each time with the output. Gah, this is tough to read but hopefully easier to see just following the pictures.

Anyways this works, but it’s no loop-able by duplicating the geometry node modifier right? It needs to be done in the same graph, unless Blender could have multiple geometry streams connected into the Group Output node so they could individually carry over. That’s why an option like “join each iteration” is needed, otherwise such operations wouldn’t possible, at least not through convenient means.

I could just be a big dumb dumb, I’m pretty tired from overwork, but I think this pans out, correct?

Perhaps it is worth having the iteration number exposed by default? After all it is quite standard and useful in many cases, so I see benefit in not having to increment manually

7 Likes

Yep I think it would be an unnecessary annoyance to set this up manually all the time…

1 Like

Will there be options like “Loop over domain” instead of “Max Iterations”. So you plug in geometry, select loop over domain, then the “Max Iterations” option is replaced with a drop down to select which domain (Points, faces, curves). I think that’s fairly intuitive and easy to understand.

As mentioned in the design,

Note, the goal is not to provide a solution to e.g. iterating over every point one by one. While it’s technically possible, serial loops are a very inefficient way to do this. That’s what lists and parallel loops will be for in the future.

the goal of this design isn’t per-geometry-element loops. People will do this anyway, but serial loops are just a very bad solution to that problem performance-wise. Those use cases will be addressed separately by parallel loops or list sockets (design discussion is still ongoing, personally I think lists will be the best solution, since it’s probably easier to work at a higher level of abstraction and have better performance).

6 Likes

My only feedback is: please add loop index as a default input, as this will be something we’ll use constantly :angel: :angel: :angel:

Hmm why not simply counting the elements in questions and feeding the integer in the loop itter nbr?

1 Like

Can you give an example of a use case where you would use that?

Can you give an example of a use case where you would use that?

Sure, here’s an example: doing math operations that use the iterator index. This is a fundamental concept in loop operations across multiple contexts, not just in programming but also in node-based systems like Geometry Nodes in Blender. The use of the index in math operations can provide enhanced control over the behaviour and attributes of objects within the loop.

Do you need example on why mathematical equation are useful in geometry node as well? I could give you some example on why math is useful of course :slight_smile:

“why on earth would we need this”

for i in range(nbr):
   ... 

“when we can do this”

int i = 1
for _ in range(nbr):
     i+=1
     ... 

is that really the question? i don’t see why there’s any resistance on including the iterator within the loop interface itself. it feels like re-inventing the wheel

4 Likes