Group: David Yang, Oliver Petrick, Ryan Alameddine, and Nick Jiang

Summary

Taking inspiration from Minecraft world generation, this project will procedurally generate an infinite world with complex terrains and cities. Additionally, there will be an interactive component to it where the user can move around the world using the WASD keys and space bar.

Slides

Milestone Slides

Video

Milestone Video

Current Progress

Procedural Terrain Generation

Octave 1 Octave 2
Octave 1 Octave 2
Octave 3 Octave Sum
Octave 3 Octave Sum

The core of our terrain generation is the Perlin Noise algorithm, which generates pseudo-random “smooth” noise. You can see examples with different frequencies and amplitudes in the octave images above. We use this to generate a height map by sampling from each octave and summing the result. We place grass on the top, dirt underneath, and stone far below.

Procedural Building Generation

To place the houses within each Chunk, we first sample a random width and depth and iterate through each block of the xz plane in the chunk. For each block, we check that the projected space for house’s foundation (add width along the x-axis, depth along the z-axis) is the same height; we don’t want to place a home on an uneven surface. If we find a suitable placement, we add a small buffer so that the homes are not directly next to one another and repeat the height checking.

Next, the house object is materialized with the rest of the Chunk blocks. The texture of the house is determined by its height which is also randomly generated. If the height is less than or equal to a certain constant, it’s considered a small house and given a random color for walls and an overhangging roof. If the height is greater, it’s considered a tall building and given brick texture.

Block Textures

While creating meshes for each chunk, we assign UV coordinates to each face in accordance with the block type. In particular, we actually have a 3D UVW space, where W selects which block texture to use. We wrote a simple shader which uses this W coordinate to select the texture to sample from a texture array, and then forwards the UV sampled color from the selected texture to a standard Unity Shader.

Player Movement

There is a player in the world which is controlled by the WASD keys. It can jump around with gravity but can also switch to a flying mode by double tapping jump (space bar). The player interacts with all the blocks in the world through collisions.

Multithreading

Even with our mesh generation optimizations (only showing faces which are not covered by another block), this was still too slow to generate many chunks at 60fps. Thus, we offloaded generation work onto other threads. By default, we use two threads to materialize chunks, and two threads to generate meshes. We synchronized this using an AsyncQueue synchronization structure we created, which is basically a thread-safe channel which performs computation on data before passing it into the output. This way, all shared data outside the channel input/output is immutable and the main thread never sleeps, so we cannot have synchronization issues or deadlock.

Preliminary Results

Milestone World World terrain with randomized buildings

The preliminary results are definitely promising. We have terrain of different heights, player movement, basic building generation, and multithreading. The video is a better demonstration of our results.

Updated Schedule

Voronoi Diagram
Basic Voronoi diagram

We are doing good on progress relative to our original schedule. For the next two weeks, we will be working on advanced city generation and our aspirational goals. One implementation we will be looking into are Voronoi diagrams to create the main roads of our world. These diagrams also split the world into natural “neighborhoods” for us to place buildings.

  • Week 3: Advanced city generation (Voronoi diagram roads), more buildings, begin working on aspirational goals
  • Week 4: Implement additional optimizations if needed and additional aspirational goals as time allows