Cave Generator in Houdini (part 2)

Article / 31 December 2025

Disclaimer: All things I share in this blog post are the fruit of my own labor and separate from my professional work at Cloud Imperium Games. Master Thesis project completed at Hamburg University of Applied Sciences (March 2024). This academic research tool was developed independently as part of my degree program, separate from any professional work.



This is part 2 of 3 blog posts
In this part of the article, I will discuss more on the on implementations of the theory on the first post in Houdini.  

link for part 1
link for part 3

Methodology

The previous post discussed the pattern that is found in real caves and they are used for generating cave levels in video games. Additionally, the methods to create cave levels in video games and their related works were explored. This chapter will focus on applying those theories in the development and implementation of the cave generator tool.

This chapter will begin with a brief introduction to the main development environment, Houdini. Afterwards, the implementations of the tool will be discussed in order to gain more understanding on how the cave generator tool is built. 


Houdini

If you dont know what houdini is and want to start using it, I would suggest first check the sidefx tutorial.
The tutorial set by Moeen Sayed and Simon V is also a solid start. For the real implementation between Houdini and Unreal, I used this tutorial

The implementation of the tool is divided into three main stages (as shown in the figure below). The first stage involves building and assembling the polygonal shapes that make a cave. The second stage focuses on merging the polygonal shapes, resulting in one shape. Finally, in the post-processing stage, various improvements such as noise effects on the walls and ceiling, adding vertex colors for textures, UV processing, etc will be applied. This last stage also includes the placement of dressing meshes, ranging from large boulders to small pebbles, in order to improve the cave's realism. The following subsections explains more into details of each of those stages. 

Figure 9. The division of the tool inside Houdini [18]


First Stage: Creating Base Layout of Caves in Houdini 

The initial creation of a cave begins with a simple tunnel from point A to B. The process requires users to guide the construction, with the tool then creating the cave around this guideline. Therefore, Houdini requires at least an input from users before starting to generate a cave in Unreal Engine. The curve was chosen as the primary input in this work because it is the most basic tool representing the path along which the cave will be developed. Users can easily modify a curve path by adding a new point or adjusting an existing one, and the tool will handle the rest. 

Creating a basic tunnel in Houdini is straightforward: by using a curve node to create curves and linking it with a sweep node, users can achieve a tube-like shape based on the curve input (see Figure 10). To facilitate smoother transitions at corners, a resample node is used, making the sweep node function more effectively. The resample node in Houdini recalculates the input curve and creates a new curve with evenly spaced points, which are then used for further refining the cave walls.

Figure 10

On another branch, the copy to points will be used to add polygonal cave like geometries. and lastly they will be merge

Figure 11


This method ensures that the produced cave walls will have the blocky shapes found in rock caves (see the article before this for reference). Additionally, these custom polygon shapes are designed with a flat base, ensuring that the floor of the generated cave remains flat for improved player traversal. This approach also introduces verticality to the cave's design. If a user wants their cave to go upwards or downwards, the floor will form a stair-like structure (see Figure 12), making the cave traversable even on a vertical axis.


Figure 12


Together with the output from the sweep node, the output from this copy-to-points node will be merged. Making sure the cave has an organic layout, while it is also always connected throughout the input. While the tool can create a simple tunnel with a cave-like appearance, it is not enough to meet the project's goals. Additional work is needed to create more complex cave layouts. Thus, methods to merge more shapes into the geometry will be introduced. 

Creating Random Rooms

In order to add more variety than a tunnel-like space, we need to add more variety on the tunnels by adding more "rooms". This creates pockets on the cave that makes it less tunnel-y. These rooms are necessary to avoid repetitiveness in the layout of the cave, and it needs to be intersected with the path of the input curve. 

The process of creating rooms involves putting a grid along the path of the curves. This grid will be the starting point for creating base layouts of the room and will be further processed by using the Cellular Automata or Noise algorithm. Both methods allow us to create random spots representing room layouts. 

I tried the cellular automata first. If you want to know how the implementation goes, you can watch this amazing video by Junichiro Horikawa or by Sebastial League. I got these as a result:

Since I'm using the world positions to calculate where the cellular is at each cell position, the grid can't be rotated. Actually, it still can, but it will need some extra calculation, which making this already expensive room creation more costly. On a bigger grid,s this will cost me some seconds, which in comparison to the next method, which using native noise nodes.

On the other hand, the noise method used the native attribute noise node from Houdini, giving the "patch" of colors. I make a plane-grid based on the curve points: it creates a plane from point a to b, with about 5-10 meters wide (random), then add attribute noise and create room-pocket floors. Other pockets other than in the curved path will be deleted.  

After implementing and testing both methods, the noise method was chosen for its built-in functionality in Houdini and its efficiency compared to the Cellular Automata method.

The tool then uses the extrude node to create room geometries along the input curve's path. These geometries will then be processed in the tool's second stage. Later in the Unreal Engine, users will have the possibility to offset the noise in order to randomize shapes. 

Using L-System for creating extra networks

The tool also utilizes an L-system to create a random network of caves without needing to create many curves. To replicate a “branchwork” pattern (see part 1), the following rules are used with the L-system node in Houdini:

  • Axiom: FA
  • Constant: + - [ ]F
  • Variable: ABCD

  • Rules: A=F[-FFFFB][+FFFFC], B=FF[-FFFFFD][+FFC], C=[-FFFFFD][FFFFF], D=[-FFF][+FFB]

This result in the following curves in houdini:


In order to get an effective result of a branchwork pattern, it is crucial that the created network branches outside of the cave, rather than simply following the curve directions. For this reason, rules that involve a lot of creating branching structures are selected. Additionally, Houdini's L-System node allows for the definition of branch direction angles.

This new network of curves will be placed at every point along the main input curves, creating additional curves within the cave without the need to create new curves manually. 

After the extra network is placed into the input curve pathways using the merge node, it will be treated as part of the original input curve. The network will then be passed into further processing, including going through a resample node and a copy-to-points node. This step is necessary to ensure that the caves, whether created from the main inputs or the L-System, have a consistent layout.

Later in Unreal Engine, users will get the options to change how much loop the network should have, the angle of branching, and the size of the network. This allows users to create complex cave layouts easily.

All these functionalities (adding rooms and extra networks) occur in the first stage of the tool. At the end of this stage, the main tunnel created from the curve inputs, along with random rooms and networks, is merged, resulting in a believable cave layout that mimics real-world caves. Figure 15 shows an example of the merged geometry of the generated cave in this first stage: The gray geometry represents shapes from the input curve, while the red and green parts represent geometries resulting from random room generation and extra networks, respectively.


Second stage: Using VDB functionality to bring all mesh together

Once all of the geometries are combined using a merge node, the cave is ready for further processing. The outputs of main inputs, random networks and random rooms need to be merged together in one interconnected mesh. While Houdini provides a boolean node to unify all the geometries, it often results in less than ideal outcomes such as polygon error or a non-hollow geometry. In order to avoid this, the VDB nodes are used. 

VDB stands for “Volumetric, Dynamic grid that shares several characteristics with B+ trees” [20]. It is one of the Houdini data types that represents voxels, which are essentially a grid of 3D pixels.  The VDB process in Houdini involves transforming the mesh geometry of the cave into a voxel representation. These voxels are then converted back into a polygon mesh for use in game environments. By using these methods, an interconnected one geometry will be created that has the same layout as the merged geometries input from the previous stage. 

One of the advantages of using VDB in this context is that it always produces hollow interior geometries. This is crucial for creating a cave level that is realistic and accessible. This VDB method ensures that the detailed layout of the cave is preserved and also ensures that whatever the shape on the input, it always has a hollow geometry. 



Third stage: Post-processing

In this final stage, the focus will be on refining the cave geometry through advanced post-processing in Houdini. This involves various steps to enhance the cave's overall appearance later in the game engine, Unreal Engine 5.


Adding noise to the cave shape

Even after the basic shape of a cave was achieved, further shaping of the cave shell is necessary in order to get a realistic look. For this purpose, the tool will implement noise on every polygon point, adding a secondary shape on the cave surfaces that complements the blocky shape that was created from the first stage of the tool. 

Before applying noise on the cave surface, the tool will divide the cave further in three sections: floors, ceilings, and walls. This division is needed to ensure that the cave floor remains flat while also helping on the placement of the dressing meshes in the later part of the tool. To achieve this division, the group node will be used. This node has the functionality of grouping a polygon part based on its polygon’s face orientation (normal direction). In this case, floors are defined by upwards-facing polygons, ceilings by downwards-facing ones, and the rest of the surface is defined as cave walls. 

After the division, the noise will be added selectively on the wall and ceilings by using an “attribute noise” node. On this node, Houdini provides its user with many types of noises such as Perlin, Manhattan cellular, Simplex, Worley, etc [21]. The Worley is chosen for this project because of its effectiveness in creating the most cave-like patterns, helping shape the cave into a more organic state.



Cleanup mesh, vertex colors, and convex hull

With the base shape for the cave ready, the cleanup process begins. This includes making entrances and exits by making holes at each end of the main curve, inverting the normals so the polygons face inward, unwrapping UVs for textures, creating Levels of Detail meshes (LODs), and fixing any polygon errors. This is achieved by using various predefined and custom nodes in Houdini.

After finishing all the cleaning up process, the cave mesh needs to be prepared for use in Unreal Engine 5. This includes the painting of random vertex colors on the cave polygons using attribute noise nodes. Adding color attributes into vertices in a mesh is a common method that is used in game development to prevent repetitive looks of a tiled texture. This is done by showing materials through the color mask of the mesh’s vertices. The vertex color applied has to be unique and randomized in order to achieve the purpose of avoiding repetitive textures.

In the example of Figure 18, the three distinct materials (smooth rock, sharp rock, cliff rock) are displayed based on their respective vertex color channels. The smooth rock materials on the red channel, the cliff rock materials on the green channel, and the sharp rock materials on the blue channel. For creating these vertex colors, the tool uses the Worley noise. This is the same noise algorithm used in shaping the cave, ensuring an organic and natural look across the generated cave.


An additional step is creating a convex hull mesh. This mesh is to ensure that the cave receives light only from specific sources, such as the cave's entrances. To simulate a realistic dark cave, it is necessary to add a mesh that covers the entire cave that protects it from external light sources. This is achieved in houdini with the help of a convex hull node. The tool takes the cave shell after merging it in VDB and creates an enclosing mesh around the input. The tool then deletes the parts at the cave's entrances using a Boolean node (see Figure 19).



Scattering Dressing Mesh

The final touch involves placing dressing meshes within the cave, using the completed cave shell as a guide. Since the division of cave shells (ceilings, walls, floor) has already occurred when adding noise, the tool uses this information to place dressing objects based on their locations.

The dressing meshes used in this project are manually created. Using Houdini for creating a base model, these meshes are further sculpted into realistic-looking boulders, rocks, and pebbles using 3D modeling software such as Zbrush and 3ds Max. The resulting dressing mesh includes four large-sized meshes (boulders), three medium-sized meshes (rocks), and two small-sized meshes (small rocks and pebbles). These meshes serve as a default dressing mesh for the tool and can be changed by users later on.


Different parts of the cave have their own dressing meshes that can be placed upon them. The ceilings and walls will have only large-sized meshes, while the floor will have medium and small-sized meshes. These meshes are placed with random rotation and 10-30% scale variations. 

The placement of meshes also requires a balance between not being too sparse, to avoid making the cave feel empty, and not placing too many, which prevents excessive overlap and expensive rendering costs. This is something that the tool will calculate with the help of Houdini nodes' functionalities, explained below.  

Scattering dressing meshes in Houdini starts with scattering points on the cave's geometry using the scatter-align node. This node enables the user to scatter points with a custom spacing value between the points, thus avoiding overlaps when later the tool places the meshes with the help of the copy-to-points nodes. Although some overlap is inevitable, this method is better than scattering points randomly.

On the floor, the tool examines the intersections of the boulders -dressing mesh- on the wall with the floor and creates a mask using the “mask by feature” node (Figure 21.c). The tool will then scatter points around the resulting mask and place the mid-sized meshes based on them. The very same process will be used when placing the small-size meshes using cave shells and mid-size meshes as the starting point for masking (Figure 21.e). This way, we make sure that the dressing mesh placements on the floor will always be in the hierarchical order big to small placement strategy (Figure 21.f).

Figure 21. Illustrating the tool’s scattering methods: initial cave shell (a), placement of big meshes
on ceilings and walls (b), mask creation on the floor (c), distribution of medium-sized meshes (d), mask
creation for small mesh placement (e), and final placement of small meshes (f). The author’s own Image taken
and edited with Screenpresso [27] and Adobe Photoshop [26].

To optimize rendering performance while scattering many dressing meshes in a cave, the tool uses the instancing method. This technique duplicates multiple meshes across various transform points without replicating the full data of each mesh. This saves a lot of memory because the engine is not storing the full details of every dressing mesh being copied, but only the original dressing mesh. In Houdini, for transferring the dressing mesh as an instanced object, the option “Pack and Instance” is needed to be activated on the copy-to-points node. This approach ensures that the tool remains lightweight during rendering in Unreal Engine, even with a high volume of dressing meshes.

After completing the implementation of all cave generation functionalities in Houdini, the tool is ready to be exported to Unreal Engine. For this, Houdini provides a feature to pack all nodes into a single node known as a Houdini Digital Asset (HDA). This HDA encapsulates all operations, workflows, effects, and functions for use in other projects or for sharing with other users. Parameters within the HDA can be exposed for external control, allowing users to customize the effects of the cave tool, including activation parameters for random networks and random rooms. The next chapter will delve deeper into how this cave generator HDA file is utilized in Unreal Engine 5.

next part