This is not related to a Minecraft clone
This question as been moved to CodeReview, as suggested. https://codereview.stackexchange.com/questions/62562/voxel-world-optimization#62562
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. 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.
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) {
}
}
}