1
$\begingroup$

I'm currently working on a maze generator project using Geometry Nodes and Simulation Nodes, inspired by Daniel Shiffman's tutorial and the corresponding code. I've made good progress so far but have encountered a challenge when trying to update attributes based on a condition, similar to the removeWalls function in the sketch.js example.

Here's the specific problem I'm facing:

I have a grid of cells, and for each cell, I've initialized four boolean attributes: topWall, rightWall,bottomWall, and leftWall. These attributes represent whether walls exist in each direction and are initially set to True for all cells.

I've also stored the coordinates of neighboring cells in attributes for each cell. This allows me to look up the attributes of neighboring cells easily.

Now, my goal is to determine which cell is the current active cell and which one is the next cell. Based on this determination, I need to remove the walls between these cells.

I've successfully removed walls from visited cells gradually over time as the simulation runs. However, the challenge arises when I need to remove walls only between the active/current cell and the next cell. I can't update by directly plugging the condition into the value socket of my boolean attributes every frame because the condition for wall removal may or may not be met, causing the attribute values to fluctuate.

removing all walls when visited

My idea to address this issue is to only store the updated attribute when the condition for wall removal is met. If the condition isn't met, I want to retain the attribute values from the previous simulation cycle. The problem is that the Switch node doesn't accept fields as input.

remove walls based on condition

I have to do this for all neighbor pairs of course: find which neighbor cell is the next cell

I believe the solution to this problem might be relatively straightforward, but somehow I cannot wrap my head around it. Also, I am not sure how ell this question is suited for this forum. Any guidance or suggestions on how to manage attribute updates based on conditions in Geometry Nodes would be greatly appreciated.

Here is the blend file

$\endgroup$
5
  • $\begingroup$ Hehe welcome to the wonderful world of maze generation. I have some experience in this domain, having released an addon some time ago. This question might be a bit too broad for this site unfortunately, you might try your luck over on blenderartists.org if noone bites here. I myself am waiting for loops in GN rather than simulation zones, it seemed better suited for a maze generation algorithm. $\endgroup$
    – Gorgious
    Nov 14, 2023 at 16:50
  • $\begingroup$ It won't solve your problem but a simplification you can use instead of using 4 different attributes for connection to neighbors is using a bitflag integer, eg 0 = no connection, 1 = connection to north, 2 = connection to east, 4 = south, 8 = west. So a value of 13 for example means the cell is connected to west, south and north. I may suggest a more simple algorithm to get your feet wet like the binary tree weblog.jamisbuck.org/2011/2/1/… $\endgroup$
    – Gorgious
    Nov 14, 2023 at 16:57
  • $\begingroup$ Thank you! Yeah I agree, maybe too much/broad for here. Was just exercising to port code to geometry nodes, but sometimes it is really hard to find work arounds. Thank you for your suggestions! $\endgroup$
    – Tim R.
    Nov 14, 2023 at 17:04
  • $\begingroup$ if you provide the blend file - i will try to help you. But i don't like to "theoretical" help because then you cannot prove by detail/blend file, that it helps. $\endgroup$
    – Chris
    Nov 14, 2023 at 17:13
  • $\begingroup$ Thank you very much! I didn't realize it's possible, sorry. I edited the original post. But This should also work: <img src="https://blend-exchange.com/embedImage.png?bid=Qj42A8MP" /> $\endgroup$
    – Tim R.
    Nov 14, 2023 at 17:31

1 Answer 1

6
$\begingroup$

result

If you use the structure of the mesh to store the variables, while keeping the current index separate from the mesh data, things become simpler $\tiny\text{I think...}$.

We start with some mesh, like a grid, in which each face will be a cell, and edges will be walls.

First we choose a random face to start and mark it as visited:

Mark all edges initially as walls:

A good thing to have is precomputed neighboring faces indices so there's easy access to to them. For a face, we can store each neighbor's index on each corner of the face, since the number of corners and neighboring faces is the same (ignoring borders).

To store the indices of neighbors we need first to get those values. With the Edges of Corner node we can get the next edge index (next is the edge after the corner in face winding order), then we use the Corners of Edge to get the corner of the neighboring face (if the first corner is the current corner, switch to the next corner), from that we just use the Face of Corner node to get the index of the neighboring face.

Visualisation:

On node tree:

Store also the index of the edge between the face and it's neighbor:

Now we start the Simulation Zone:

Its inputs are:

  • Unvisited faces (Integer) : Number of faces not visited, starts as the number of faces - $1$ (for the one that was chosen for starting).
  • Geometry (Geometry) : The mesh being operated.
  • Stack (Geometry) : Store previously visited indices as points with ID set to the index. Starts empty.
  • Current (Integer) : Index of the current cell, the one chosen randomly at the start.

First in the simulation we only want it to run if there are still unvisited cells, so check if the number of unvisited faces is $0$ to skip the simulation:

To get the non visited neighbors of the current face, get only its face corners and, sampling from the mesh the 'visited' attribute, delete the ones that point to visited faces:

Now we need two branches of nodes, one for when there's unvisited neighbors, and other for when there isn't.

For when there is, get the stored neighbor index of a randomly selected unvisited neighbor and mark it as visited, this will be the new current. From the same, get the stored edge index for the edge between and unmark it from being a wall. Also, store the old current on the stack as the ID of a new point:

For when there is no unvisited neighbors, remove the most recent from the stack and get its face index stored in the ID, that is the new current. The mesh remains unchanged:

Finally we switch between the values of when there's unvisited neighbors and when there isn't by checking the amount of unvisited neighbors, we also decrease the amount of total unvisited faces only if there were unvisited neighbors:

After that you can use the attributes to select which edges or faces will get instances, material or whatever you want.

Full node tree:

Edge cases: The reason there's no need to check for border edges is that the neighbor storing method stores the index of the actual face when there's no neighbor for a corner, but in the simulation when getting the unvisited neighbors it is discarded since the current is already selected.

$\small\text{Blender 4.0}$


This method works on any mesh that has a single mesh island where all edges have one or two faces.

$\endgroup$
2
  • $\begingroup$ Nooo way! Thank you sooo much! This is so much more than I was hoping for. Even the effort you put into this answer besides the blend file itself! I appreciate it very much! :) $\endgroup$
    – Tim R.
    Nov 15, 2023 at 7:25
  • $\begingroup$ I can't upvote yet, but would love to give a hundred! Thank you! $\endgroup$
    – Tim R.
    Nov 15, 2023 at 7:31

You must log in to answer this question.

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