private void MergeAsteroidVolumeInto(ref MyVoxelMap newAsteroid, Vector3D min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3D minPrimary, Vector3D minSecondary) { var filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath; var filenamePrimary = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath; Vector3I coords; var asteroid = new MyVoxelMap(); asteroid.Load(filenameSecondary, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true); for (coords.Z = (int)modelSecondary.ContentBounds.Min.Z; coords.Z <= modelSecondary.ContentBounds.Max.Z; coords.Z++) { for (coords.Y = (int)modelSecondary.ContentBounds.Min.Y; coords.Y <= modelSecondary.ContentBounds.Max.Y; coords.Y++) { for (coords.X = (int)modelSecondary.ContentBounds.Min.X; coords.X <= modelSecondary.ContentBounds.Max.X; coords.X++) { byte volume; string cellMaterial; asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume); var newCoord = ((minSecondary - min) + ((Vector3D)coords - modelSecondary.ContentBounds.Min)).RoundToVector3I(); newAsteroid.SetVoxelContent(volume, ref newCoord); newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord); } } } asteroid.Load(filenamePrimary, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true); for (coords.Z = (int)modelPrimary.ContentBounds.Min.Z; coords.Z <= modelPrimary.ContentBounds.Max.Z; coords.Z++) { for (coords.Y = (int)modelPrimary.ContentBounds.Min.Y; coords.Y <= modelPrimary.ContentBounds.Max.Y; coords.Y++) { for (coords.X = (int)modelPrimary.ContentBounds.Min.X; coords.X <= modelPrimary.ContentBounds.Max.X; coords.X++) { byte volume; string cellMaterial; asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume); if (volume > 0) { byte existingVolume; string existingCellMaterial; var newCoord = ((minPrimary - min) + ((Vector3D)coords - modelPrimary.ContentBounds.Min)).RoundToVector3I(); newAsteroid.GetVoxelMaterialContent(ref newCoord, out existingCellMaterial, out existingVolume); if (volume > existingVolume) { newAsteroid.SetVoxelContent(volume, ref newCoord); } // Overwrites secondary material with primary. newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord); } } } } }
private void MergeAsteroidMaterialFrom(ref MyVoxelMap newAsteroid, Vector3 min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3 minPrimary, Vector3 minSecondary) { var filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath; var filenamePrimary = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath; Vector3I coords; var asteroid = new MyVoxelMap(); asteroid.Load(filenamePrimary); for (coords.Z = (int)modelPrimary.ContentBounds.Min.Z; coords.Z <= modelPrimary.ContentBounds.Max.Z; coords.Z++) { for (coords.Y = (int)modelPrimary.ContentBounds.Min.Y; coords.Y <= modelPrimary.ContentBounds.Max.Y; coords.Y++) { for (coords.X = (int)modelPrimary.ContentBounds.Min.X; coords.X <= modelPrimary.ContentBounds.Max.X; coords.X++) { byte volume; string cellMaterial; asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume); var newCoord = ((minPrimary - min) + ((Vector3D)coords - modelPrimary.ContentBounds.Min)).RoundToVector3I(); newAsteroid.SetVoxelContent(volume, ref newCoord); newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord); } } } asteroid.Load(filenameSecondary); for (coords.Z = (int)modelSecondary.ContentBounds.Min.Z; coords.Z <= modelSecondary.ContentBounds.Max.Z; coords.Z++) { for (coords.Y = (int)modelSecondary.ContentBounds.Min.Y; coords.Y <= modelSecondary.ContentBounds.Max.Y; coords.Y++) { for (coords.X = (int)modelSecondary.ContentBounds.Min.X; coords.X <= modelSecondary.ContentBounds.Max.X; coords.X++) { var newCoord = ((minSecondary - min) + ((Vector3D)coords - modelSecondary.ContentBounds.Min)).RoundToVector3I(); if (Vector3I.BoxContains(Vector3I.Zero, modelPrimary.Size - 1, newCoord)) { byte volume; string cellMaterial; asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume); if (volume > 0) { newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord); } } } } } }
public void RotateAsteroid(VRageMath.Quaternion quaternion) { var sourceFile = SourceVoxelFilepath ?? VoxelFilepath; var asteroid = new MyVoxelMap(); asteroid.Load(sourceFile, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true); var newAsteroid = new MyVoxelMap(); var transSize = Vector3I.Transform(asteroid.Size, quaternion); var newSize = Vector3I.Abs(transSize); newAsteroid.Init(Vector3D.Zero, newSize, SpaceEngineersCore.Resources.GetDefaultMaterialName()); Vector3I coords; for (coords.Z = 0; coords.Z < asteroid.Size.Z; coords.Z++) { for (coords.Y = 0; coords.Y < asteroid.Size.Y; coords.Y++) { for (coords.X = 0; coords.X < asteroid.Size.X; coords.X++) { byte volume = 0xff; string cellMaterial; asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume); var newCoord = Vector3I.Transform(coords, quaternion); // readjust the points, as rotation occurs arround 0,0,0. newCoord.X = newCoord.X < 0 ? newCoord.X - transSize.X : newCoord.X; newCoord.Y = newCoord.Y < 0 ? newCoord.Y - transSize.Y : newCoord.Y; newCoord.Z = newCoord.Z < 0 ? newCoord.Z - transSize.Z : newCoord.Z; newAsteroid.SetVoxelContent(volume, ref newCoord); newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord); } } } var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); newAsteroid.Save(tempfilename); SourceVoxelFilepath = tempfilename; }
private bool ExtractStationIntersect(bool tightIntersection) { // Make a shortlist of station Entities in the bounding box of the asteroid. var asteroidWorldAABB = new BoundingBoxD(DataModel.ContentBounds.Min + DataModel.PositionAndOrientation.Value.Position, DataModel.ContentBounds.Max + DataModel.PositionAndOrientation.Value.Position); var stations = MainViewModel.GetIntersectingEntities(asteroidWorldAABB).Where(e => e.ClassType == ClassType.Station).Cast <StructureCubeGridModel>().ToList(); if (stations.Count == 0) { return(false); } var modified = false; var sourceFile = DataModel.SourceVoxelFilepath ?? DataModel.VoxelFilepath; var asteroid = new MyVoxelMap(); asteroid.Load(sourceFile, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true); var total = stations.Sum(s => s.CubeGrid.CubeBlocks.Count); MainViewModel.ResetProgress(0, total); // Search through station entities cubes for intersection with this voxel. foreach (var station in stations) { var quaternion = station.PositionAndOrientation.Value.ToQuaternion(); foreach (var cube in station.CubeGrid.CubeBlocks) { MainViewModel.IncrementProgress(); var definition = SpaceEngineersApi.GetCubeDefinition(cube.TypeId, station.CubeGrid.GridSizeEnum, cube.SubtypeName); var orientSize = definition.Size.Transform(cube.BlockOrientation).Abs(); var min = cube.Min.ToVector3() * station.CubeGrid.GridSizeEnum.ToLength(); var max = (cube.Min + orientSize) * station.CubeGrid.GridSizeEnum.ToLength(); var p1 = Vector3D.Transform(min, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2); var p2 = Vector3D.Transform(max, quaternion) + station.PositionAndOrientation.Value.Position - (station.CubeGrid.GridSizeEnum.ToLength() / 2); var cubeWorldAABB = new BoundingBoxD(Vector3.Min(p1, p2), Vector3.Max(p1, p2)); // find worldAABB of block. if (asteroidWorldAABB.Intersects(cubeWorldAABB)) { var pointMin = new Vector3I(cubeWorldAABB.Min - DataModel.PositionAndOrientation.Value.Position); var pointMax = new Vector3I(cubeWorldAABB.Max - DataModel.PositionAndOrientation.Value.Position); Vector3I coords; for (coords.Z = pointMin.Z; coords.Z <= pointMax.Z; coords.Z++) { for (coords.Y = pointMin.Y; coords.Y <= pointMax.Y; coords.Y++) { for (coords.X = pointMin.X; coords.X <= pointMax.X; coords.X++) { if (coords.X >= 0 && coords.Y >= 0 && coords.Z >= 0 && coords.X < asteroid.Size.X && coords.Y < asteroid.Size.Y && coords.Z < asteroid.Size.Z) { asteroid.SetVoxelContent(0, ref coords); } } } } modified = true; } } } MainViewModel.ClearProgress(); if (modified) { var tempfilename = TempfileUtil.NewFilename(MyVoxelMap.V2FileExtension); asteroid.Save(tempfilename); // replaces the existing asteroid file, as it is still the same size and dimentions. DataModel.SourceVoxelFilepath = tempfilename; } return(modified); }
private void SubtractAsteroidVolumeFrom(ref MyVoxelMap newAsteroid, Vector3D min, StructureVoxelModel modelPrimary, StructureVoxelModel modelSecondary, Vector3D minPrimary, Vector3D minSecondary) { var filenameSecondary = modelSecondary.SourceVoxelFilepath ?? modelSecondary.VoxelFilepath; var filenamePrimary = modelPrimary.SourceVoxelFilepath ?? modelPrimary.VoxelFilepath; Vector3I coords; var asteroid = new MyVoxelMap(); asteroid.Load(filenamePrimary, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true); for (coords.Z = (int)modelPrimary.ContentBounds.Min.Z; coords.Z <= modelPrimary.ContentBounds.Max.Z; coords.Z++) { for (coords.Y = (int)modelPrimary.ContentBounds.Min.Y; coords.Y <= modelPrimary.ContentBounds.Max.Y; coords.Y++) { for (coords.X = (int)modelPrimary.ContentBounds.Min.X; coords.X <= modelPrimary.ContentBounds.Max.X; coords.X++) { byte volume; string cellMaterial; asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume); var newCoord = ((minPrimary - min) + ((Vector3D)coords - modelPrimary.ContentBounds.Min)).RoundToVector3I(); newAsteroid.SetVoxelContent(volume, ref newCoord); newAsteroid.SetVoxelMaterialAndIndestructibleContent(cellMaterial, 0xff, ref newCoord); } } } asteroid.Load(filenameSecondary, SpaceEngineersCore.Resources.GetDefaultMaterialName(), true); for (coords.Z = (int)modelSecondary.ContentBounds.Min.Z; coords.Z <= modelSecondary.ContentBounds.Max.Z; coords.Z++) { for (coords.Y = (int)modelSecondary.ContentBounds.Min.Y; coords.Y <= modelSecondary.ContentBounds.Max.Y; coords.Y++) { for (coords.X = (int)modelSecondary.ContentBounds.Min.X; coords.X <= modelSecondary.ContentBounds.Max.X; coords.X++) { var newCoord = ((minSecondary - min) + ((Vector3D)coords - modelSecondary.ContentBounds.Min)).RoundToVector3I(); if (Vector3I.BoxContains(Vector3I.Zero, modelPrimary.Size - 1, newCoord)) { byte volume; string cellMaterial; asteroid.GetVoxelMaterialContent(ref coords, out cellMaterial, out volume); if (volume > 0) { byte existingVolume; string existingCellMaterial; newAsteroid.GetVoxelMaterialContent(ref newCoord, out existingCellMaterial, out existingVolume); if (existingVolume - volume < 0) { volume = 0; } else { volume = (byte)(existingVolume - volume); } newAsteroid.SetVoxelContent(volume, ref newCoord); } } } } } }
/// <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); }