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<Voxel> world , OptimizationType optimizationType ) {
switch( optimizationType ) {
case OptimizationType.FullOptimization:
DoFullOptimization( world );
break;
}
}
private static void DoFullOptimization( List<Voxel> world ) {
/**
* Loop Through The Voxel Collection and collect
* potential neighbors.
*/
foreach( Voxel currentVoxel in world ) {
Vector3 backNeighbor = currentVoxel.Location;
backNeighbor.X += 2.0f;
Vector3 frontNeighbor = currentVoxel.Location;
frontNeighbor.X -= 2.0f;
Vector3 leftNeighbor = currentVoxel.Location;
leftNeighbor.Z -= 2.0f;
Vector3 rightNeighbor = currentVoxel.Location;
rightNeighbor.Z += 2.0f;
Vector3 topNeighbor = currentVoxel.Location;
topNeighbor.Y += 2.0f;
Vector3 bottomNeighbor = currentVoxel.Location;
bottomNeighbor.Y -= 2.0f;
/**
* This is the part that needs to be fixed.
* Basically we loop back through the collection
* AGAIN for every voxel. This means that we
* check every voxel at least twice, if not up
* to six times...I think.
*/
foreach( Voxel voxel in world ) {
if( voxel != currentVoxel ) {
if( voxel.Location == backNeighbor ) {
currentVoxel.ShowBackFace = false;
} else if( voxel.Location == frontNeighbor ) {
currentVoxel.ShowFrontFace = false;
} else if( voxel.Location == leftNeighbor ) {
currentVoxel.ShowLeftFace = false;
} else if( voxel.Location == rightNeighbor ) {
currentVoxel.ShowRightFace = false;
} else if( voxel.Location == topNeighbor ) {
currentVoxel.ShowTopFace = false;
} else if( voxel.Location == bottomNeighbor ) {
currentVoxel.ShowBottomFace = false;
}
}
}
}
}
/**
* Add this feature later with bitwise flags and other sorts of glorious sugar.
*/
private static void DoFullControlOptimization(List<Voxel> world) {
}
}
}
Suggestion #1; Use Parallel.ForEach loop (drops time down from 900ms to 260-300ms)
using System.Threading.Tasks;
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<Voxel> world , OptimizationType optimizationType ) {
switch( optimizationType ) {
case OptimizationType.FullOptimization:
DoFullOptimization( world );
break;
}
}
private static void DoFullOptimization( List<Voxel> world ) {
/**
* Loop Through The Voxel Collection and collect
* potential neighbors.
*/
// Parallel.ForEach drops Opt-Time down to 260-300ms!
// Was 900ms with regular for-each loop.
Parallel.ForEach( world , currentVoxel => {
Vector3 backNeighbor = currentVoxel.Location;
backNeighbor.X += 2.0f;
Vector3 frontNeighbor = currentVoxel.Location;
frontNeighbor.X -= 2.0f;
Vector3 leftNeighbor = currentVoxel.Location;
leftNeighbor.Z -= 2.0f;
Vector3 rightNeighbor = currentVoxel.Location;
rightNeighbor.Z += 2.0f;
Vector3 topNeighbor = currentVoxel.Location;
topNeighbor.Y += 2.0f;
Vector3 bottomNeighbor = currentVoxel.Location;
bottomNeighbor.Y -= 2.0f;
/**
* This is the part that needs to be fixed.
* Basically we loop back through the collection
* AGAIN for every voxel. This means that we
* check every voxel at least twice, if not up
* to six times...I think.
*/
foreach( Voxel voxel in world ) {
if( voxel != currentVoxel ) {
if( voxel.Location == backNeighbor ) {
currentVoxel.ShowBackFace = false;
} else if( voxel.Location == frontNeighbor ) {
currentVoxel.ShowFrontFace = false;
} else if( voxel.Location == leftNeighbor ) {
currentVoxel.ShowLeftFace = false;
} else if( voxel.Location == rightNeighbor ) {
currentVoxel.ShowRightFace = false;
} else if( voxel.Location == topNeighbor ) {
currentVoxel.ShowTopFace = false;
} else if( voxel.Location == bottomNeighbor ) {
currentVoxel.ShowBottomFace = false;
}
}
}
} );
}
/**
* Add this feature later with bitwise flags and other sorts of glorious sugar.
*/
private static void DoFullControlOptimization(List<Voxel> world) {
}
}
}