/// <summary>
/// Processes an asteroid Voxel using function callbacks.
/// This allows for muti-threading, and generating content via algorithims.
/// </summary>
/// <param name="voxelMap"></param>
/// <param name="multiThread"></param>
/// <param name="material"></param>
/// <param name="func"></param>
/// <param name="readWrite"></param>
/// <returns></returns>
public static void ProcessAsteroid(MyVoxelMap voxelMap, bool multiThread, string material, Action<MyVoxelBuilderArgs> func, bool readWrite = true)
{
long counterTotal = (long)voxelMap.Size.X * (long)voxelMap.Size.Y * (long)voxelMap.Size.Z;
long counter = 0;
decimal progress = 0;
var timer = new Stopwatch();
Debug.Write(string.Format("Building Asteroid : {0:000},", progress));
Console.Write(string.Format("Building Asteroid : {0:000},", progress));
Exception threadException = null;
timer.Start();
if (!multiThread)
{
#region single thread processing
for (var x = 0; x < voxelMap.Size.X; x++)
{
for (var y = 0; y < voxelMap.Size.Y; y++)
{
for (var z = 0; z < voxelMap.Size.Z; z++)
{
var coords = new Vector3I(x, y, z);
byte volume = 0xff;
var cellMaterial = material;
if (readWrite)
voxelMap.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume);
var args = new MyVoxelBuilderArgs(voxelMap.Size, coords, cellMaterial, volume, 0xff);
try
{
func(args);
}
catch (Exception ex)
{
threadException = ex;
break;
}
if (args.Volume != MyVoxelConstants.VOXEL_CONTENT_FULL)
{
voxelMap.SetVoxelContent(args.Volume, ref coords);
}
if (material != args.Material)
{
voxelMap.SetVoxelMaterialAndIndestructibleContent(args.Material, args.Indestructible, ref coords);
}
counter++;
var prog = Math.Floor(counter / (decimal)counterTotal * 100);
if (prog != progress)
{
progress = prog;
Debug.Write(string.Format("{0:000},", progress));
}
}
}
}
#endregion
}
else
{
#region multi thread processing
// TODO: re-write the multi thread processing to be more stable.
// But still try and max out the processors.
long threadCounter = counterTotal / MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE / MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE / MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE;
var baseCoords = new Vector3I(0, 0, 0);
for (baseCoords.X = 0; baseCoords.X < voxelMap.Size.X; baseCoords.X += MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE)
{
for (baseCoords.Y = 0; baseCoords.Y < voxelMap.Size.Y; baseCoords.Y += MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE)
{
for (baseCoords.Z = 0; baseCoords.Z < voxelMap.Size.Z; baseCoords.Z += MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE)
{
var task = new Task(obj =>
{
var bgw = (MyVoxelTaskWorker)obj;
var coords = new Vector3I(0, 0, 0);
for (coords.X = bgw.BaseCoords.X; coords.X < bgw.BaseCoords.X + MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE; coords.X++)
{
for (coords.Y = bgw.BaseCoords.Y; coords.Y < bgw.BaseCoords.Y + MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE; coords.Y++)
{
for (coords.Z = bgw.BaseCoords.Z; coords.Z < bgw.BaseCoords.Z + MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE; coords.Z++)
{
byte volume = 0xff;
var cellMaterial = material;
if (readWrite)
voxelMap.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume);
var args = new MyVoxelBuilderArgs(voxelMap.Size, coords, cellMaterial, volume, 0xff);
try
{
func(args);
}
catch (Exception ex)
{
threadException = ex;
threadCounter = 0;
break;
}
if (args.Volume != MyVoxelConstants.VOXEL_CONTENT_FULL)
{
voxelMap.SetVoxelContent(args.Volume, ref coords);
}
if (material != args.Material)
{
voxelMap.SetVoxelMaterialAndIndestructibleContent(args.Material, args.Indestructible, ref coords);
}
}
}
}
lock (Locker)
{
counter += (long)MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE *
MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE *
MyVoxelConstants.VOXEL_DATA_CELLS_IN_RENDER_CELL_SIZE;
var prog = Math.Floor(counter / (decimal)counterTotal * 100);
if (prog != progress)
{
progress = prog;
Debug.Write(string.Format("{0:000},", progress));
Console.Write(string.Format("{0:000},", progress));
GC.Collect();
}
threadCounter--;
}
}, new MyVoxelTaskWorker(baseCoords));
task.Start();
}
}
}
GC.Collect();
while (threadCounter > 0)
{
System.Windows.Forms.Application.DoEvents();
}
System.Threading.Thread.Sleep(100);
System.Windows.Forms.Application.DoEvents();
#endregion
}
timer.Stop();
if (threadException != null)
throw threadException;
voxelMap.UpdateContentBounds();
var count = voxelMap.SumVoxelCells();
Debug.WriteLine(" Done. | {0} | VoxCells {1:#,##0}", timer.Elapsed, count);
Console.WriteLine(" Done. | {0} | VoxCells {1:#,##0}", timer.Elapsed, count);
}