Building Meshes in Unity, Vertex by Vertex

Alexander Pech
9 min readJun 6, 2021

--

In 2018, I wrote a piece for the community-driven Procedural Generation zine, Seeds, titled “Experiments in Generative Geometry: Building Meshes in Unity, Vertex by Vertex”. Seeds was part of the PROCJAM game jam, and my piece was an exploration of how 3D meshes could be build procedurally in the Unity game engine.

The work I did was built off of the excellent tutorial series by Jayelinda Suridge, Modelling by numbers. Like Jayelinda, I’m a 3D-Artist-turned-games-programmer, so this tutorial series was exactly they starting point I needed to begin my own experiments and explorations.

Below, I’m going to share the original submission piece, and then afterwards share some of the code, and go into more detail about some of the challenges I faced.

You can also,

Experiments in Generative Geometry (Seeds, Nov 2018)

Building Meshes in Unity, Vertex by Vertex

I’m an embedded software engineer from 9 to 5, but in my spare time I like to dabble with procedural geometry. Dissecting things into the smallest possible components and making them work for me is my jam, whether it’s manipulating the registers of a CPU or finding new ways to coerce vertices and polygons into useful game assets.

Off and on in my spare time I’ve been jumping into Unity and, using the built-in Mesh class, just seeing what I could come up with. I started with the basics of programmatically placing vertices and triangles. Then I moved on to basic primitives like cubes, cylinders and spheres. Using these methods as building blocks I gradually progressed to more complex and organic shapes.

Examples of my tree generation algorithm in action

A particular area of focus for me has been trees. Trees lend themselves easily to this kind of algorithm for a number of reasons. The branching structure lends itself nicely to a recursive or iterative algorithm, similar to a fractal. The topology of a branch is fairly simple, really just a tapered cylinder. Also, all trees are unique but follow similar patterns, making them ideal candidates for creation via a set of rules plus randomness.

Wireframe mesh of a tree branch, showing spiral pattern of vertices
Creating a spiral mesh, with varying levels of detail (LODs)

My basic procedural tree structure is a cylinder with some function controlling the direction of growth and radial thickness. I initially tried controlling branch direction via applying incremental rotations around a random axis. This gave a nice spiralled or twisted look to my branches but turned out to be quite difficult to control. My current solution uses spline curves. This gives me the control to generate a series of spline points however I want and then smoothly ‘grow’ the branch along the curve. I’ve also experimented with more physical based models, like growing towards a light source and applying gravity.

The radius function, even though it has less influence over the general shape of the tree, tends to be more complex. I like taking into account the angle of the current vertex as well to produce a bit of irregularity. This is particularly useful around the base of the trunk, where you don’t always want a perfect cylinder. So here you end up with what is essentially a two-variable function for your branch, defining the radius at any particular point along the length and radial direction.

If this is confusing, here is the picture I have in my head when the geometry is being created. You start with a spline curve and at the start of the curve you draw an arrow perpendicularly out from the curve. The end of the arrow points to your first vertex. Then, you start to move the arrow up the curve while also rotating it, forming a spiral. The length of the arrow is controlled by our radius function. As it spirals up you periodically place a vertex at the tip of the arrow and connect to the surrounding ones. This is the basis for the current version of my algorithm. (You may have noticed the topology of these branches aren’t exactly the same as cylinders as they have a single edge that spirals all the way along. Visually there is very little difference, but it gives me greater control because I don’t need to place vertices ring by ring.)

From here I hope to keep building upon my toolkit, gradually producing more complex and interesting shapes and also making the meshes produced efficient and scalable so I can generate whole forests. This was really just an introduction into the methods I’ve used, as a lot of technical challenges have presented themselves along the way. Generating different levels of detail was a big one. At one point I threw out everything and started again just so I could have control over this aspect right from the start! But now I have a friendly ‘polygon density’ slider that does all this for me.

This has been a fairly technical explanation, but more than anything I’m inspired by the biological and evolutionary processes that created this life in the first place, so I hope to continue incorporating aspects of that into my models. Even though right now I’m just creating some funky geometry, there is a future vision that this may result in generating not just meshes, but functional environments with ecosystems and an evolutionary history. This will hopefully be just one piece of a vaster world-building engine.

For now, I hope my experiments find some value with others. You can find some of my work at my itch.io page https://rednax.itch.io/ (including some random unrelated game jam projects). Hopefully plenty more to come!

Digging a little deeper…

Let’s take a closer look at the tree creator live demo.

Screenshot from the live Tree Creator demo on itch.io
Screenshot from the live Tree Creator demo on itch.io

First of all, how do we go from creating some bendy cylinders to this tree-like structure with some weirdly shaped foliage?

Let’s dig into the code a little.

Our scene has a TestTree GameObject with four important components to control our mesh generation:

  1. PGTreeBase — creates all the child GameObjects we need for the trunk and leaves
  2. TreeSpecies — container for all the variable data to feed into out generator (trunk height, branch length, etc)
  3. TreeSpeciesSliderUpdate — this is what creates and links the variables in TreeSpecies up to sliders in our GUI
  4. TreeTest — initialises our tree GameObject for this test scene

The most interesting one to look at here is PGTreeBase. It’s the component that’s going to kick off our the rest of our generation process.

First, lets look at how to create a basic tree part from a cylinder. This BuildCurve function actually builds a cylinder as a spiral by rotating around a centre curve and adding new vertices and triangles on each iteration. The MeshBuilder class simply acts as a container for our mesh properties (vertices, normals, uvs, tris), and the remaining properties define the shape of the mesh as we iterate and define vertices while twisting up the curve.

void BuildCurve(MeshBuilder meshBuilder, Vector3 offset, float radius, int segments, float v, Quaternion rotation, float twist_angle, bool buildTriangles, int branchVertices)
{
for(int i = 0; i <= segments; i++) {
// Calculate vertex position
float theta = (Mathf.PI*2.0f*(float)i)/(float)segments + twist_angle*Mathf.Deg2Rad;
float x = Mathf.Cos(theta)*radius;
float y = 0.0f;
float z = Mathf.Sin(theta)*radius;
// Set normals to face along radial line
meshBuilder.Normals.Add(new Vector3(Mathf.Cos(theta), 0, Mathf.Sin(theta)));
meshBuilder.Vertices.Add((rotation * new Vector3(x,y,z)) + offset);
meshBuilder.UVs.Add(new Vector2(i/(float)(segments),v));
if(buildTriangles) {
int baseIndex = meshBuilder.Vertices.Count-1;
if(i != 0) {
meshBuilder.AddTriangle(baseIndex,baseIndex-segments-branchVertices-1,baseIndex-1);
}
if(i != segments) {
meshBuilder.AddTriangle(baseIndex,baseIndex-segments-branchVertices,baseIndex-segments-branchVertices-1);
}
}
}
}

By using this basic building block in a number of different ways, we can build different sub-structures of a tree.

The algorithm creates a series of different tree parts in order, from the Trunk (starting piece), Forks/Branches, and finishing at Stems (endpoints). Building each piece is really just a variation of the same cylinder creation algorithm.

Flowchart showing flow through functions BuildTrunk, BuildFork, BuildBranch, and looping back again to BuildFork before terminating at BuildStem

The algorithm is recursive, and uses an ‘end condition’ to determine when a branch should terminate. The end condition is either a ‘maximum number of branches’, or, ‘branch radius has reduced to zero’.

A more intuitive visualisation of the process might look a bit look this:

Rearranging the flowchart into a ‘literal tree’

Just by adding a variety of controls to the size/shape and random variation for all these shapes (defining a tree ‘species’), we can build a wide variety of different tree structures, and seed many variations of the same ‘species’.

What about the leaves?

As with hand-modelled in-game tree meshes, the leaf shapes aren’t really evident in the geometry, and are instead defined using alpha textures. (The geometry is a basic, flat mesh of a few polys.)

The challenge here was to create those alpha maps in a procedural manner.

Generated tree leaves, shaded vs wireframe

The alpha map design is inspired by the shape of oak leaves, and is created by defining a random bezier curve from the stem to the tip of the leaf. The space between the curve and the centre line is then mirrored, and the result is mirrored along that centre y axis.

Photo by Catia Climovich on Unsplash

As you can see, this leads to some pretty strange and interesting shapes.

Examples of generated leaf shapes

Creating a basic UI for species variable control

The generated UI in the Tree Creator demo

Finally, I’d like to share how I went about creating a simple UI for tweaking the variables defined in the TreeSpecies component.

This was important, because it made it much faster and easier to test the affects of different variables, and also enabled the ‘Tree Editor’ to be built as a playable Unity project.

All of the sliders are generating via a script, based on a list of variables to expose to the UI.

This is defined in the TreeSpeciesSliderUpdate component. Here’s what the code looks like:

This CreateSlider function creates a new slider for a given generic property. It instantiates a predefined Slider prefab, attaches it to our UI, and sets up a listener so that the slider value updates the actual value on the TreeSpecies.

void CreateSlider(string name, string property, float minValue, float maxValue) {GameObject newSliderObj = Instantiate(m_floatSlider, m_listContainer.transform) as GameObject;// Set name text
newSliderObj.transform.Find("Name").GetComponent<Text>().text = name;
RectTransform rt = newSliderObj.GetComponent<RectTransform>();
rt.anchoredPosition = new Vector2(0,-sliderCount*sliderSpacing);
Slider newSlider = newSliderObj.GetComponentInChildren<Slider>();
newSlider.minValue = minValue;
newSlider.maxValue = maxValue;
newSlider.value = (float)species.GetType().GetField(property).GetValue(species);
newSlider.onValueChanged.AddListener( (value) => { species.GetType().GetField(property).SetValue(species, value); } );
sliderCount++;
}

Then, all we need to do in our component is call CreateSlider for each property we want a control for:

void Start () {
CreateSlider("Trunk Height", "m_height", 1.0f, 5.0f);
CreateSlider("Trunk Start Radius", "m_start_radius", 0.5f, 5.0f);
CreateSlider("Trunk End Radius", "m_end_radius", 0.5f, 5.0f);
CreateSlider("Trunk Twist Angle", "m_twist_angle", 0.0f, 180.0f);
...
}

While you could do a similar thing in the inspector, setting this up makes it really simple to rapidly prototype various properties and controls within the game window itself, and gives us the added advantage of actually leaving us with an in-game ‘editor’

Conclusion

This has really just scratched the surface of what this project was about, but I hope I’ve highlighted some of the most interesting aspects.

There’s lots more detail and evidence of experimentation in the code repository at https://github.com/alexpech12/ProcGeom.

Don’t forget to check out the live demo, and some of my other game projects at https://rednax.itch.io/

Thanks for reading!

--

--

Alexander Pech
Alexander Pech

Written by Alexander Pech

Software Developer in Ruby on Rails and C++. Hobbyist game dev with Unity and Godot.

No responses yet