Skip to content

SiggiG/ProceduralMeshDemos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

117 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Procedural mesh examples for Unreal 5

procmesh_project_2

Overview

I've been wanting to learn how to procedurally generate meshes in Unreal for some time now, and have noticed interest from the community as well.

There have been a few good discussions on the Unreal forums, but not a lot of samples for how to do this.

The purpose of this project is to provide examples for how to generate geometry in code, from simple cubes to more complex geometry generated from fractal algorithms.

I would love for this to become a community project, so I will accept both pull requests for new samples as well as any corrections to my code. I'm also willing to add contributors directly if anyone is interested (see contact information below).

I wrote the code to be readable, trying my best to explain each step along the way. There are many ways this code could be optimized to run better, but I wanted to keep things simple in the first few examples.

There is a lot of code duplication between the different examples which I felt was OK for the first few examples, but I will refactor some of the common functions into a utility class soon.

PLEASE NOTE: I update these examples from time to time to follow the latest Unreal versions. If you get really stuck feel free to send a PR or contact me below.

Unreal Engine 5 update notes

I finally updated the project for Unreal 5 and simplified the project structure

  • Cleanup
  • Made the code simpler by using the normal engine ProceduralMeshComponent. The other one is faster, but switching made this code example simpler
  • Derived a simple class from ProceduralMeshComponent to deal with serialization, and not saving mesh data into actor or map. Its regenerated every time its needed.
  • Simplified folder structure, merged Plugin into the main project source.
  • Deleted shadow map, turned on Lumen etc

Explanation of a few Unreal concepts.

Vertices, triangles, UV coordinates, normals and tangents.. oh my!

Meshes are created by setting up 3d coordinates and then defining polygons between those.

When creating meshes we enter data into a few different arrays. All of the arrays are of the same length except the Triangles one, and all of them reference the Vertices array in some way.

Vertices

This is a collection of all the points (vectors) in the 3d mesh.

Triangles

A triangular polygon is defined by 3 points in space, and this array contains references to what entries in the Vertices array define a polygon.

The order in which we add the vertices governs the way the polygon will face, and if you look at the back of a polygon it will simply be invisible (they are all one sided).

If you add vertices on a polygon in a counter-clockwise order, the polygon will face "towards you".

Example: We have 9 entries in the Vertices array and want to create a polygon from entries 4 to 6. The Triangles array would then contain the numbers: 3, 4, 5 (zero-based arrays).

UV coordinates

A UV coordinate is simply the X,Y coordinate on a texture that the corresponding vertex will have. The GPU then interpolates how to display the texture in between the vertices.

Normals

A normal is a vector that defines the direction a polygon is facing, or in this case the direction the polygon faces where the vertex is positioned.

Normally (pun intended) this can be calculated easily from the vectors in the polygon, but sometimes we want to manipulate this to provide smooth surfaces and other tricks. See SimpleCylinder for an example of smoothing a curved surface.

Tangents

A tangent is a vector that is perpendicular (forms a 90 degree angle) with the normal and is parallell to the polygon surface.

Geometry examples

Simple Cube

We start off with a very simple example of drawing a cube where you can set the Depth, Width and Height dimensions. Good starting template for understanding the quad-building pattern.

procexample_simplecube

Simple Cylinder

Shows how to draw a cylinder with configurable radius, height and how many polygons to use on the sides.

Demonstrates smooth normals (averaging adjacent polygon normals for GPU interpolation), double-sided rendering, and end cap closure with triangle fans.

procexample_simplecylinder

Simple Sphere

Three different sphere generation algorithms in one actor, selectable via a dropdown:

  • UV Sphere — Classic parametric sphere with latitude/longitude rings
  • Geodesic (Icosphere) — Subdivided icosahedron with edge midpoint caching and UV seam correction
  • Normalized Cube — Cube faces subdivided and projected onto a sphere surface
Cylinder Strip

Define multiple points in space and draw a cylinder section between each point to form a line. Each segment is independent, so there are visible gaps at the corners.

procexample_cylinderstrip

Smooth Cylinder Strip

A continuous tube along a polyline that solves the gap problem from the basic Cylinder Strip. At each corner joint, the cross-section orientation is interpolated using quaternion slerp, producing smooth spherical joints that cleanly connect angled segments. The number of interpolation steps per joint is configurable.

Sierpinski Line Pyramid

I have always been fascinated by fractals, and they are one of the reasons I wanted to learn how to make custom geometry in Unreal.

All fractals are drawn by a few very simple rules, but can create incredibly complicated results.

The Sierpinski pyramid is a 3D version of the Sierpinski triangle, drawn with cylindrical lines in 3D space. Line thickness reduces each generation.

procexample_sierpinskilines

Sierpinski Tetrahedron

The solid-face counterpart to the Sierpinski Line Pyramid. Instead of wireframe lines, this renders the fractal with filled triangular faces. Each tetrahedron recursively subdivides into 4 sub-tetrahedrons at edge midpoints, with continuous UV mapping across subdivisions.

Menger Sponge

A recursive fractal cube. Uses a two-pass approach: first counts exposed faces for buffer pre-allocation, then emits only outward-facing quads where neighbors are empty. The IsSolid() function tests each cell using base-3 digit analysis at each subdivision level. Iterations clamped to 4 (grid size 81³).

Branching Lines

Another simple algorithm that can create complex shapes seen in nature, including trees and lightning.

You start by defining two points in space and draw a line between them. Then add a point in the center of that line, and shift it out in a random direction. Then repeat this step for the two new sections created and repeat!

Supports optional smooth joints (quaternion slerp tube interpolation), sphere joints at fork points, and end caps (flat or tapered).

procexample_branchinglines

Branching Mesh (Space Colonization)

The most complex example. Uses the Space Colonization algorithm to grow tree-like structures from attractor points placed in a configurable crown volume (sphere, hemisphere, cone, or cylinder). Branch paths are smoothed with centripetal Catmull-Rom splines and swept with tube cross-sections. Fork transitions blend parent and child branches smoothly. Width follows the pipe model (leaf tips accumulate upward). Supports collision generation.

Grid with a noise heightmap

Simple grid mesh with random noise on the Z axis using FRandomStream with a configurable seed for reproducible results.

procexample_heightfieldnoise

Grid with animated heightmap

Grid mesh with an animated Z axis using combined sine and cosine waves. The only example that uses Tick() for per-frame animation, with an UpdateMeshSection fast path that avoids recreating the scene proxy every frame.

procexample_heightfieldnoise_animated

Grid with animated heightmap (Direct Proxy)

An alternative animated heightfield that bypasses ProceduralMeshComponent entirely. Uses a custom UDirectProxyMeshComponent with its own FPrimitiveSceneProxy to update GPU vertex buffers directly, eliminating the extra buffer copies that PMC requires. Same sine/cosine wave animation as above, but with a single-copy path from game thread to GPU.

Future work

More examples!

I want to provide more examples in the future, and would love if members of the community could provide some! Of course you will get full credit for your contributions.

  • Proper L-systems
  • Animated lightning

Contact info

If you have any questions, suggestions or want to contribute to this project please contact me at one of these places:

License

MIT License

Copyright (c) 2016 Sigurdur Gunnarsson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Credits

About

Examples of procedural mesh generation in Unreal Engine.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages