HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMajor

Voxel World Optimization

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
optimizationvoxelworld

Problem

This is not related to a Minecraft clone.

I am currently writing a turn-based strategy game like Final Fantasy Tactics. The game is played on floating voxel-style islands, which are generated from heightmap images (will soon be dynamically generated using system.drawing). I already wrote the world generator (15 minute mock up) and the voxel world optimizer.

My only issue is that the voxel world optimization takes around 900ms to complete (a suggestion that I received on Stack Overflow recommended Parallel.ForEach and that dropped it down to 260-300ms). I wanted to show you guys some code and see if someone could assist me in dropping the opt-time down to around 100-200ms.

Here is my current Heightmap (the System is very crude at this point):

And here is a brief rendering of said Heightmap:

The World Optimizer that I have already written takes into consideration when faces cannot be seen, and then if that can be asserted, hides said faces (the land masses are hollow despite having voxels present). Again, I just need someone to help me optimize the optimizer so that It can work faster.

Here is my world optimizer; I will provide any other source code if required.

Full project source can be downloaded here. (OpenTK required & precompiled demo included)

```
using GameProject.Game.Framework.Geometry;
using System.Collections.Generic;
using OpenTK;

namespace GameProject.Game.Framework.Generators {
public enum OptimizationType {
FullOptimization
}
public static class WorldOptimizer {
public static void OptimizeVoxelWorld( List world , OptimizationType optimizationType ) {
switch( optimizationType ) {
case OptimizationType.FullOptimization:
DoFullOptimization( world );
break;
}
}

private static void DoFullOptimization( List world ) {
/**
* Loop Through The Voxel Collection and collect
* potential n

Solution

To solve this problem, I made each Voxel aware of its neighbours, this was achieved in the world generation/height-map loading phase.

Then I was able to change the optimization algorithm to the following (found in Program.cs):

private static void DoFullOptimization(IEnumerable world)
{
    foreach (var currentVoxel in world)
    {
        var visibleFaces = Faces.None;
        if (currentVoxel.BackNeighbor == null)
        {
            visibleFaces |= Faces.Back;
        }
        if (currentVoxel.FrontNeighbor == null)
        {
            visibleFaces |= Faces.Front;
        }
        if (currentVoxel.BottomNeighbor == null)
        {
            visibleFaces |= Faces.Bottom;
        }
        if (currentVoxel.TopNeighbor == null)
        {
            visibleFaces |= Faces.Top;
        }
        if (currentVoxel.LeftNeighbor == null)
        {
            visibleFaces |= Faces.Left;
        }
        if (currentVoxel.RightNeighbor == null)
        {
            visibleFaces |= Faces.Right;
        }

        currentVoxel.VisibleFaces = visibleFaces;
    }
}


This does mean I moved the performance hit to the world loading, however loading the sample height-map image and generating the voxels only took 21ms and the optimization took 0.96ms (yes, less than 1ms).

My entire solution can be found on BitBucket here.

The key in the loading phase is to keep track of the loaded neighbors, I do this in the WorldLoader by having a Dictionary. I only bother searching for the left/back/bottom neighbors because my Voxel implementation already deals with setting the other end of the relationship between neighbours (if x.LeftNeighbor = y then y.RightNeighbor == x).

Note

I am not a GameDev so my X, Y and Z are probably all the wrong way round or referring to the wrong thing!

Code Snippets

private static void DoFullOptimization(IEnumerable<Voxel> world)
{
    foreach (var currentVoxel in world)
    {
        var visibleFaces = Faces.None;
        if (currentVoxel.BackNeighbor == null)
        {
            visibleFaces |= Faces.Back;
        }
        if (currentVoxel.FrontNeighbor == null)
        {
            visibleFaces |= Faces.Front;
        }
        if (currentVoxel.BottomNeighbor == null)
        {
            visibleFaces |= Faces.Bottom;
        }
        if (currentVoxel.TopNeighbor == null)
        {
            visibleFaces |= Faces.Top;
        }
        if (currentVoxel.LeftNeighbor == null)
        {
            visibleFaces |= Faces.Left;
        }
        if (currentVoxel.RightNeighbor == null)
        {
            visibleFaces |= Faces.Right;
        }

        currentVoxel.VisibleFaces = visibleFaces;
    }
}

Context

StackExchange Code Review Q#62562, answer score: 21

Revisions (0)

No revisions yet.