So I'm trying to create an array of hexagonal rooms which will have a door wherever 2 faces of the hexagon instersect.
How can I go about doing this?
I'm very new to geometry nodes :p
Thanks for any help!
So I'm trying to create an array of hexagonal rooms which will have a door wherever 2 faces of the hexagon instersect.
How can I go about doing this?
I'm very new to geometry nodes :p
Thanks for any help!
This is a scalable and quite large solution.
Start by generating a grid that will be laid over the hexagons like this:
To generate this grid, we need 3 grid-columns for the first column of hexagons and 2 further grid-columns for every other column of hexagons. Let c be the number of hexagon columns, then we need 2*c + 1 grid columns.
We need 5 grid-rows for the first row of hexagons and 4 further grid-rows for every other row of hexagons. Since every second column of hexagons is shifted by 2 grid-rows, we need 2 further grid-rows, so that we can have the same number of hexagons in the shifted columns.
The size of the grid will be calculated based on the size of one tile. We expect the tiles to be aligned parallel to the x-axis with two of its edges.
We start with calculating the width and depth of the bounding box of one tile. To get the width of our grid, we need to multiply the width of one tile by the number of columns. We need to multiply the result by 0.75, because every second column is shifted and so we will have the width of one tile plus the length of one edge. The height is computed by multiplying the height of one tile by the number of rows. We have to increase the row number by 0.5 before, because every second column is shifted by half a row.
And here is the complete grid generation:
This means, the center of the hexagons is at positions (1, 2); (1, 6); (1, 10); … and the next column is shifted by 2 in y, so that it continues with (3, 4); (3, 8); (3, 12); … Thus, we can identify grid coordinates with the following rules:
(x-1) modulo 4 = 0 AND (y-2) modulo 4 = 0 and y < (grid-row-count – 1) (x+1) modulo 4 = 0 AND y modulo 4 = 0 AND y > 0
If you take the center of a room, then the offset coordinates for the walls are (0, +2) N; (+1, +1) NE; (+1, -1) SE; (0, -2) S; (-1, -1) SW; (-1, +1) NW
The idea is, to use the ID attribute to mark the different points. The center of every room will be marked with a 4. And when creating a room, we will increase the value of every wall-point by 1. The result will be:
1 = wall
2 = door
4 = floor
The index of a grid is organized in columns. It starts with 0 at the lower left corner, increases with y and continues at the lower end of the next column. Therefore, we need a way to convert between index and grid coordinates. We need the number of grid-rows to do this:
x = floor( index / grid-row-count)
y = index modulo grid-row-count
Let’s create a group node Index -> Grid Coordinates for this task:
By defining the outputs as Integer, they will be rounded down automatically. Thus, we don’t need to add a Math Floor node
Next, we would like to randomly mark points of room centers. Therefore, we need to select all points, that correspond to a room center. How can we do this?
Let’s start by implementing the rules for the grid positions of rooms, that were defined above. Then we can simply put the Index -> Grid Coordinates node in front:
We wrap this in a group node to keep the overview.
Now, since we can select room points, we can select randomly from this selection and mark the points as rooms like this:
Next, we would like to mark every wall of the room by increasing the ID of the corresponding point by 1. But how can we do this? The following steps may seem a little unintuitive. This results from the fact, that you need to think from the end, when using geometry nodes.
For changing the ID of a point, we need the Set ID node. This changes the ID based on a selection. If we use the Index node in the context of this selection, it will be the index of the point that is changed by the Set ID node – in our case the index of the point of the wall.
A point relates to a wall, if the corresponding point of the room center is marked with 4. To read the ID of the room center point, we can use a Transfer Attribute node. But we need the index of the room center point, in order to read its ID.
Starting at the index of a wall, we can calculate the index of the room center point based on the grid vectors, that we defined in Offset coordinates of the walls. We receive the vectors from the walls to the center of a room by multiplying these vectors with -1. Then we need to turn this into a delta index. Therefore, we define a group node Grid Coordinates -> Index:
Using this, we can we define a group node Is Wall, that selects points based on the vectors, that point from the wall to the center of a room:
Input of this node is the vector pointing from the point with the current index. Using the above defined Grid Coordinates -> Index node, we convert this into a delta index and add it to the index of the current point. Then we use this index to read the ID of the target point. We select the current point, if the ID of the target point is equal to our Room Marker, which we defined as 4.
We use this node to mark the walls like this:
We use one instance of the Is Wall node for every wall position and increase the ID of the corresponding points. The walls are split into two groups, so that the opposite walls are not processed together. We do this, because we want the walls, that belong to two rooms, are processed for every room and thus marked with the number 2.
Now every room center point is marked with 4, every wall of a single room is marked with 1 and every wall that touches two rooms is marked with 2.
We can use this, to instantiate the floor and different types of walls.
I have a suggestion...
Essentially, I use this technique here to create a hexagonal grid:
How can I create a hexagonal structure with Geometry Nodes?
However, I rotate it by $90°$ and triangulate the mesh, which gives me the following pattern:
I then delete some points from this pattern using the node Random Value (Boolean):
I then instantiate hexagons at these points:
If I then split their edges, I can mark the edges that are crossed by the previously created pattern.
In order to then instantiate either a wall or a wall with a door at these points with the correct rotation, I still need the rotation.
Therefore I convert these edges into curves and subdivide them. The middle point of these curve segments has now the required rotation, at which I can now wonderfully instantiate my walls or whatever.
In this example, I also prepared the elements as curves, which I extrude in this node tree and use as an instance:
If you want to do something like this:
then i have a laborious solution for you.
The blue points are the "doors".
Unfortunately i know only a very laborious way.
If GN will get a loop, it becomes a lot easier.
So what i basically do here is this:
First i create the hexagon grid with circles of 6 vertices and move them so that they fit in the grid. Then i create another circle inside these hexagon which is rotated on z-axis and a bit smaller so i get the positions of the doors (basically in the middle of the edges of the bigger hexagon).
To find the doors i move one hexagon with doors up and raycast down to all other doors. If it hits another door, the door stays, all other will be deleted. Because i have no loop in GN i have to repeat that step by copying my node group and connecting it to my join geometry node and i have to increase the index in every node.
node setup:
This method works but it is not really good. You don't need a nodegroup for every index because e.g. if just two hexagons intersect then only one nodegroup with the one of the intersecting indizes is enough to find the door.
ok, here one complete example...