private bool FindMaterial(IMyStorage storage, byte[] findMaterial) { if (findMaterial.Length == 0) { return(false); } var oldCache = new MyStorageData(); oldCache.Resize(storage.Size); storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 2, Vector3I.Zero, storage.Size - 1); //MyAPIGateway.Utilities.ShowMessage("check", string.Format("SizeLinear {0} {1}.", oldCache.SizeLinear, oldCache.StepLinear)); Vector3I p; for (p.Z = 0; p.Z < storage.Size.Z; ++p.Z) { for (p.Y = 0; p.Y < storage.Size.Y; ++p.Y) { for (p.X = 0; p.X < storage.Size.X; ++p.X) { var content = oldCache.Content(ref p); var material = oldCache.Material(ref p); if (content > 0 && findMaterial.Contains(material)) { return(true); } } } } return(false); }
byte IMyOctreeLeafNode.GetFilteredValue() { MyStorageData filteredValueBuffer = FilteredValueBuffer; this.m_provider.ReadRange(filteredValueBuffer, this.m_dataType.ToFlags(), ref Vector3I.Zero, this.m_cell.Lod, ref this.m_cell.CoordInLod, ref this.m_cell.CoordInLod); return((this.m_dataType == MyStorageDataTypeEnum.Material) ? filteredValueBuffer.Material(0) : filteredValueBuffer.Content(0)); }
private bool ReplaceAsteroidMaterial(ulong steamId, IMyVoxelBase originalAsteroid, string searchMaterialName1, string searchMaterialName2) { MyVoxelMaterialDefinition material1; string suggestedMaterials = ""; if (!Support.FindMaterial(searchMaterialName1, out material1, ref suggestedMaterials)) { MyAPIGateway.Utilities.SendMessage(steamId, "Invalid Material1 specified.", "Cannot find the material '{0}'.\r\nTry the following: {1}", searchMaterialName1, suggestedMaterials); return(true); } MyVoxelMaterialDefinition material2; if (!Support.FindMaterial(searchMaterialName2, out material2, ref suggestedMaterials)) { MyAPIGateway.Utilities.SendMessage(steamId, "Invalid Material2 specified.", "Cannot find the material '{0}'.\r\nTry the following: {1}", searchMaterialName2, suggestedMaterials); return(true); } var oldStorage = originalAsteroid.Storage; var oldCache = new MyStorageData(); oldCache.Resize(oldStorage.Size); oldStorage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, Vector3I.Zero, oldStorage.Size - 1); Vector3I p; for (p.Z = 0; p.Z < oldStorage.Size.Z; ++p.Z) { for (p.Y = 0; p.Y < oldStorage.Size.Y; ++p.Y) { for (p.X = 0; p.X < oldStorage.Size.X; ++p.X) { var material = oldCache.Material(ref p); if (material == material1.Index) { oldCache.Material(ref p, material2.Index); } } } } oldStorage.WriteRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, oldStorage.Size - 1); MyAPIGateway.Utilities.SendMessage(steamId, "Asteroid", "'{0}' material '{1}' replaced with '{2}'.", originalAsteroid.StorageName, material1.Id.SubtypeName, material2.Id.SubtypeName); return(true); }
public static MyVoxelMaterialDefinition GetMaterialAt(this VRage.Game.Voxels.IMyStorage self, ref Vector3D localCoords) { Vector3I lodVoxelRangeMin = Vector3D.Floor(localCoords / 1.0); MyStorageData target = new MyStorageData(MyStorageDataTypeFlags.All); target.Resize(Vector3I.One); self.ReadRange(target, MyStorageDataTypeFlags.Material, 0, lodVoxelRangeMin, lodVoxelRangeMin); return(MyDefinitionManager.Static.GetVoxelMaterialDefinition(target.Material(0))); }
public static MyVoxelMaterialDefinition GetMaterialAt(this VRage.Game.Voxels.IMyStorage self, ref Vector3I voxelCoords) { MyStorageData target = new MyStorageData(MyStorageDataTypeFlags.All); target.Resize(Vector3I.One); self.ReadRange(target, MyStorageDataTypeFlags.All, 0, voxelCoords, voxelCoords); byte materialIndex = target.Material(0); return((materialIndex != 0xff) ? MyDefinitionManager.Static.GetVoxelMaterialDefinition(materialIndex) : null); }
public static void GetMaterialContent(this VRage.Game.Voxels.IMyStorage self, ref Vector3I voxelCoords, out byte material, out byte content) { MyStorageData myStorageData = new MyStorageData(MyStorageDataTypeFlags.ContentAndMaterial); myStorageData.Resize(Vector3I.One); myStorageData.ClearMaterials(0); self.ReadRange(myStorageData, MyStorageDataTypeFlags.ContentAndMaterial, 0, voxelCoords, voxelCoords); material = myStorageData.Material(0); content = myStorageData.Content(0); }
public static MyVoxelMaterialDefinition GetMaterialAt_R(this IMyStorage self, ref Vector3I voxelCoords) { MyVoxelMaterialDefinition def; var cache = new MyStorageData(); cache.Resize(Vector3I.One); cache.ClearMaterials(0); self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, voxelCoords, voxelCoords); def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0)); return(def); }
private unsafe void DrawMaterialsInfo(MyStorageData data) { int *counts = stackalloc int[256]; int cellCount = data.SizeLinear / data.StepLinear; for (int i = 0; i < data.SizeLinear; i += data.StepLinear) { byte mat = data.Material(i); counts[mat]++; } Section("Probing Materials ({0} {1})", cellCount, cellCount > 1 ? "voxels" : "voxel"); List <MatInfo> hits = new List <MatInfo>(); for (int i = 0; i < 256; i++) { if (counts[i] > 0) { hits.Add(new MatInfo() { Material = (byte)i, Count = counts[i] }); } } hits.Sort(); int maxMaterial = MyDefinitionManager.Static.VoxelMaterialCount; foreach (var info in hits) { if (info.Material == MyVoxelConstants.NULL_MATERIAL) { Text(" Null Material: {0}", info.Count); } else if (info.Material > maxMaterial) { Text(" Invalid Material({1}): {0}", info.Count, info.Material); } else { Text(" {1}: {0}", info.Count, MyDefinitionManager.Static.GetVoxelMaterialDefinition(info.Material).Id.SubtypeName); } } }
public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3D localCoords) { MyVoxelMaterialDefinition def; Vector3I voxelCoords = Vector3D.Floor(localCoords / MyVoxelConstants.VOXEL_SIZE_IN_METRES); MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); cache.ClearMaterials(0); self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords); def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0)); return(def); }
private MyVoxelMaterialDefinition GetVoxelMaterial(MyVoxelBase voxelBase, Vector3D hitPos) { if (voxelBase.Storage == null || voxelBase.PositionComp == null) { return(null); } Vector3D localPosition; var wm = voxelBase.PositionComp.WorldMatrixInvScaled; Vector3D.TransformNoProjection(ref hitPos, ref wm, out localPosition); var voxelPosition = voxelBase.StorageMin + new Vector3I(localPosition) + (voxelBase.Size >> 1); StorageData.Resize(Vector3I.One); voxelBase.Storage.ReadRange(StorageData, MyStorageDataTypeFlags.Material, 0, voxelPosition, voxelPosition); byte materialIndex = StorageData.Material(0); return(MyVoxelMaterialDefinition.Get(materialIndex)); }
private bool IsValidVoxelTarget(NaniteMiningItem target, IMyEntity entity) { if (entity == null) { return(false); } byte material2 = 0; float amount = 0; IMyVoxelBase voxel = entity as IMyVoxelBase; Vector3D targetMin = target.Position; Vector3D targetMax = target.Position; Vector3I minVoxel, maxVoxel; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel); MyVoxelBase voxelBase = voxel as MyVoxelBase; minVoxel += voxelBase.StorageMin; maxVoxel += voxelBase.StorageMin; voxel.Storage.ClampVoxel(ref minVoxel); voxel.Storage.ClampVoxel(ref maxVoxel); MyStorageData cache = new MyStorageData(); cache.Resize(minVoxel, maxVoxel); var flag = MyVoxelRequestFlags.AdviseCache; cache.ClearContent(0); cache.ClearMaterials(0); byte original = 0; voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag); original = cache.Content(0); material2 = cache.Material(0); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { Logging.Instance.WriteLine("[Mining] Content is empty!", 2); MyAPIGateway.Utilities.InvokeOnGameThread(() => { AddMinedPosition(target); }); return(false); } Logging.Instance.WriteLine($"[Mining] Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}", 2); cache.Content(0, 0); var voxelMat = target.Definition; target.Amount = CalculateAmount(voxelMat, original * 8f); Logging.Instance.WriteLine($"[Mining] Removing: {target.Position} ({material2} {amount})", 2); if (material2 == 0) { Logging.Instance.WriteLine("[Mining] Material is 0", 2); MyAPIGateway.Utilities.InvokeOnGameThread(() => { AddMinedPosition(target); }); return(false); } if (target.Amount == 0f) { Logging.Instance.WriteLine("[Mining] Amount is 0", 2); MyAPIGateway.Utilities.InvokeOnGameThread(() => { AddMinedPosition(target); }); return(false); } return(true); }
internal void ReadMaterialRange(MyStorageData target, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) { float lodVoxelSizeHalf; BoundingBox queryBox; BoundingSphere querySphere; SetupReading(lodIndex, ref minInLod, ref maxInLod, out lodVoxelSizeHalf, out queryBox, out querySphere); float lodVoxelSize = 2f * lodVoxelSizeHalf; var overlappedDeposits = OverlappedDeposits; { ProfilerShort.Begin("Testing deposit shapes"); overlappedDeposits.Clear(); ContainmentType testDeposits = ContainmentType.Disjoint; for (int i = 0; i < m_data.Deposits.Length; ++i) { var test = m_data.Deposits[i].Shape.Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test != ContainmentType.Disjoint) { overlappedDeposits.Add(m_data.Deposits[i]); testDeposits = ContainmentType.Intersects; } } ProfilerShort.End(); if (testDeposits == ContainmentType.Disjoint) { ProfilerShort.Begin("target.BlockFillMaterial"); target.BlockFillMaterial(writeOffset, writeOffset + (maxInLod - minInLod), m_data.DefaultMaterial.Index); ProfilerShort.End(); return; } } ProfilerShort.Begin("Material computation"); Vector3I v; for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z) { for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y) { for (v.X = minInLod.X; v.X <= maxInLod.X; ++v.X) { Vector3 localPos = v * lodVoxelSize; float closestDistance = 1f; byte closestMaterialIdx = m_data.DefaultMaterial.Index; if (!MyFakes.DISABLE_COMPOSITE_MATERIAL) { foreach (var deposit in overlappedDeposits) { float distance = deposit.Shape.SignedDistance(ref localPos, MyVoxelConstants.VOXEL_SIZE_IN_METRES, m_data.MacroModule, m_data.DetailModule); if (distance < 0f && distance <= closestDistance) { closestDistance = distance; // DA: Pass default material to the layered deposit so only that does these if-s. var materialDef = deposit.GetMaterialForPosition(ref localPos, lodVoxelSize); closestMaterialIdx = materialDef == null ? m_data.DefaultMaterial.Index : materialDef.Index; } } } var write = v - minInLod + writeOffset; target.Material(ref write, closestMaterialIdx); } } } ProfilerShort.End(); }
private bool ReplaceAsteroidMaterial(IMyVoxelBase originalAsteroid, string searchMaterialName1, string searchMaterialName2) { MyVoxelMaterialDefinition material1; string suggestedMaterials = ""; if (!Support.FindMaterial(searchMaterialName1, out material1, ref suggestedMaterials)) { MyAPIGateway.Utilities.ShowMessage("Invalid Material1 specified.", "Cannot find the material '{0}'.\r\nTry the following: {1}", searchMaterialName1, suggestedMaterials); return true; } MyVoxelMaterialDefinition material2; if (!Support.FindMaterial(searchMaterialName2, out material2, ref suggestedMaterials)) { MyAPIGateway.Utilities.ShowMessage("Invalid Material2 specified.", "Cannot find the material '{0}'.\r\nTry the following: {1}", searchMaterialName2, suggestedMaterials); return true; } var oldStorage = originalAsteroid.Storage; var oldCache = new MyStorageData(); oldCache.Resize(oldStorage.Size); oldStorage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, Vector3I.Zero, oldStorage.Size - 1); Vector3I p; for (p.Z = 0; p.Z < oldStorage.Size.Z; ++p.Z) for (p.Y = 0; p.Y < oldStorage.Size.Y; ++p.Y) for (p.X = 0; p.X < oldStorage.Size.X; ++p.X) { var material = oldCache.Material(ref p); if (material == material1.Index) oldCache.Material(ref p, material2.Index); } oldStorage.WriteRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, oldStorage.Size - 1); MyAPIGateway.Utilities.ShowMessage("Asteroid", "'{0}' material '{1}' replaced with '{2}'.", originalAsteroid.StorageName, material1.Id.SubtypeName, material2.Id.SubtypeName); return true; }
private static MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream) { // Size of this voxel map (in voxels) Vector3I tmpSize; tmpSize.X = stream.ReadInt32(); tmpSize.Y = stream.ReadInt32(); tmpSize.Z = stream.ReadInt32(); var storage = new MyOctreeStorage(null, tmpSize); // Size of data cell in voxels. Has to be the same as current size specified by our constants. Vector3I cellSize; cellSize.X = stream.ReadInt32(); cellSize.Y = stream.ReadInt32(); cellSize.Z = stream.ReadInt32(); Trace.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS); Vector3I cellsCount = tmpSize / cellSize; Dictionary<byte, MyVoxelMaterialDefinition> mappingTable = null; if (fileVersion == STORAGE_TYPE_VERSION_CELL) { // loading material names->index mappings mappingTable = Compatibility_LoadMaterialIndexMapping(stream); } else if (fileVersion == 1) { // material name->index mappings were not saved in this version } var startCoord = Vector3I.Zero; var endCoord = new Vector3I(MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); var cache = new MyStorageData(); cache.Resize(Vector3I.Zero, endCoord); Vector3I cellCoord; for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++) { for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++) { for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++) { MyVoxelRangeType cellType = (MyVoxelRangeType)stream.ReadByteNoAlloc(); // Cell's are FULL by default, therefore we don't need to change them switch (cellType) { case MyVoxelRangeType.EMPTY: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_EMPTY); break; case MyVoxelRangeType.FULL: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_FULL); break; case MyVoxelRangeType.MIXED: Vector3I v; for (v.X = 0; v.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.X++) { for (v.Y = 0; v.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Y++) { for (v.Z = 0; v.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Z++) { cache.Content(ref v, stream.ReadByteNoAlloc()); } } } break; } startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref startCoord, ref endCoord); } } } try { // In case materials are not saved, catch any exceptions caused by this. // Read materials and indestructible for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++) { for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++) { for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++) { bool isSingleMaterial = stream.ReadByteNoAlloc() == 1; MyVoxelMaterialDefinition material = null; if (isSingleMaterial) { material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable); cache.ClearMaterials(material.Index); } else { byte indestructibleContent; Vector3I voxelCoordInCell; for (voxelCoordInCell.X = 0; voxelCoordInCell.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.X++) { for (voxelCoordInCell.Y = 0; voxelCoordInCell.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Y++) { for (voxelCoordInCell.Z = 0; voxelCoordInCell.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Z++) { material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable); indestructibleContent = stream.ReadByteNoAlloc(); cache.Material(ref voxelCoordInCell, material.Index); } } } } startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); storage.WriteRange(cache, MyStorageDataTypeFlags.Material, ref startCoord, ref endCoord); } } } } catch (EndOfStreamException ex) { MySandboxGame.Log.WriteLine(ex); } return storage; }
private void ProcessAsteroid(string displayType, string displayName, IMyVoxelMap voxelMap, double distance, BoundingBoxD aabb) { Vector3I min = Vector3I.MaxValue; Vector3I max = Vector3I.MinValue; Vector3I block; Dictionary <byte, long> assetCount = new Dictionary <byte, long>(); // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue. for (block.Z = 0; block.Z < voxelMap.Storage.Size.Z; block.Z += 64) { for (block.Y = 0; block.Y < voxelMap.Storage.Size.Y; block.Y += 64) { for (block.X = 0; block.X < voxelMap.Storage.Size.X; block.X += 64) { var cacheSize = new Vector3I(64); var oldCache = new MyStorageData(); oldCache.Resize(cacheSize); // LOD1 is not detailed enough for content information on asteroids. voxelMap.Storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1); Vector3I p; for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z) { for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y) { for (p.X = 0; p.X < cacheSize.X; ++p.X) { var content = oldCache.Content(ref p); if (content > 0) { min = Vector3I.Min(min, p + block); max = Vector3I.Max(max, p + block + 1); var material = oldCache.Material(ref p); if (assetCount.ContainsKey(material)) { assetCount[material] += content; } else { assetCount.Add(material, content); } } } } } } } } var assetNameCount = new Dictionary <string, long>(); foreach (var kvp in assetCount) { var name = MyDefinitionManager.Static.GetVoxelMaterialDefinition(kvp.Key).Id.SubtypeName; if (assetNameCount.ContainsKey(name)) { assetNameCount[name] += kvp.Value; } else { assetNameCount.Add(name, kvp.Value); } } assetNameCount = assetNameCount.OrderByDescending(e => e.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); var sum = assetNameCount.Values.Sum(); var ores = new StringBuilder(); foreach (var kvp in assetNameCount) { ores.AppendFormat("{0} {1:N} {2:P}\r\n", kvp.Key, (double)kvp.Value / 255, (double)kvp.Value / (double)sum); } var contentBox = new BoundingBoxD(voxelMap.PositionLeftBottomCorner + min, voxelMap.PositionLeftBottomCorner + max); var description = string.Format("Distance: {0:N}\r\nSize: {1}\r\nBoundingBox Center: [X:{2:N} Y:{3:N} Z:{4:N}]\r\n\r\nContent Size:{5}\r\nLOD0 Content Center: [X:{6:N} Y:{7:N} Z:{8:N}]\r\n\r\nMaterial Mass Percent\r\n{9}", distance, voxelMap.Storage.Size, aabb.Center.X, aabb.Center.Y, aabb.Center.Z, max - min, contentBox.Center.X, contentBox.Center.Y, contentBox.Center.Z, ores); MyAPIGateway.Utilities.ShowMissionScreen(string.Format("ID {0}:", displayType), string.Format("'{0}'", displayName), " ", description, null, "OK"); }
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 block; Vector3I newBlock; Vector3I cacheSize; var asteroid = new MyVoxelMap(); asteroid.Load(filenamePrimary); BoundingBoxI content = modelPrimary.InflatedContentBounds; for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64) { for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64) { for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64) { var cache = new MyStorageData(); cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1, MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1, MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1); cache.Resize(cacheSize); asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1); newBlock = ((minPrimary - min) + (Vector3D)(block - content.Min)).RoundToVector3I(); newAsteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1); } } } asteroid.Load(filenameSecondary); content = modelSecondary.InflatedContentBounds; for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64) { for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64) { for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64) { var cache = new MyStorageData(); cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1, MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1, MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1); cache.Resize(cacheSize); asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1); newBlock = ((minSecondary - min) + (Vector3D)(block - content.Min)).RoundToVector3I(); var newCache = new MyStorageData(); newCache.Resize(cacheSize); newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1); Vector3I p; for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z) { for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y) { for (p.X = 0; p.X < cacheSize.X; ++p.X) { byte volume = cache.Content(ref p); byte material = cache.Material(ref p); if (volume > 0) { newCache.Material(ref p, material); } } } } newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1); } } } }
/// <summary> /// /// </summary> /// <param name="voxelMap"></param> /// <param name="resolution">0 to 8. 0 for fine/slow detail.</param> /// <param name="distance"></param> /// <returns></returns> private int FindMaterial(IMyVoxelBase voxelMap, Vector3D center, int resolution, double distance) { int hits = 0; var materials = MyDefinitionManager.Static.GetVoxelMaterialDefinitions().Where(v => v.IsRare).ToArray(); var findMaterial = materials.Select(f => f.Index).ToArray(); var storage = voxelMap.Storage; var scale = (int)Math.Pow(2, resolution); //MyAPIGateway.Utilities.ShowMessage("center", center.ToString()); var point = new Vector3I(center - voxelMap.PositionLeftBottomCorner); //MyAPIGateway.Utilities.ShowMessage("point", point.ToString()); var min = ((point - (int)distance) / 64) * 64; min = Vector3I.Max(min, Vector3I.Zero); //MyAPIGateway.Utilities.ShowMessage("min", min.ToString()); var max = ((point + (int)distance) / 64) * 64; max = Vector3I.Max(max, min + 64); //MyAPIGateway.Utilities.ShowMessage("max", max.ToString()); //MyAPIGateway.Utilities.ShowMessage("size", voxelMap.StorageName + " " + storage.Size.ToString()); if (min.X >= storage.Size.X || min.Y >= storage.Size.Y || min.Z >= storage.Size.Z) { //MyAPIGateway.Utilities.ShowMessage("size", "out of range"); return 0; } var oldCache = new MyStorageData(); //var smin = new Vector3I(0, 0, 0); //var smax = new Vector3I(31, 31, 31); ////var size = storage.Size; //var size = smax - smin + 1; //size = new Vector3I(16, 16, 16); //oldCache.Resize(size); //storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, resolution, Vector3I.Zero, size - 1); var smax = (max / scale) - 1; var smin = (min / scale); var size = smax - smin + 1; oldCache.Resize(size); storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, resolution, smin, smax); //MyAPIGateway.Utilities.ShowMessage("smax", smax.ToString()); //MyAPIGateway.Utilities.ShowMessage("size", size .ToString()); //MyAPIGateway.Utilities.ShowMessage("size - 1", (size - 1).ToString()); Vector3I p; for (p.Z = 0; p.Z < size.Z; ++p.Z) for (p.Y = 0; p.Y < size.Y; ++p.Y) for (p.X = 0; p.X < size.X; ++p.X) { // place GPS in the center of the Voxel var position = voxelMap.PositionLeftBottomCorner + (p * scale) + (scale / 2) + min; if (Math.Sqrt((position - center).LengthSquared()) < distance) { var content = oldCache.Content(ref p); var material = oldCache.Material(ref p); if (content > 0 && findMaterial.Contains(material)) { var index = Array.IndexOf(findMaterial, material); var name = materials[index].MinedOre; var gps = MyAPIGateway.Session.GPS.Create("Ore " + name, "scanore", position, true, false); MyAPIGateway.Session.GPS.AddGps(MyAPIGateway.Session.Player.IdentityId, gps); hits++; } } } return hits; }
public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3I voxelCoords) { MyVoxelMaterialDefinition def; MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); cache.ClearMaterials(0); self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords); def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0)); return def; }
public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck = false) { // change range so normal can be computed at edges (expand by 1 in all directions) voxelStart -= 1; voxelEnd += 1; if (storage == null) { return(null); } using (storage.Pin()) { if (storage.Closed) { return(null); } MyVoxelRequestFlags request = MyVoxelRequestFlags.ContentChecked; // | (doNotCheck ? MyVoxelRequestFlags.DoNotCheck : 0); //if (lod == 0 && generateMaterials) request |= MyVoxelRequestFlags.AdviseCache; bool readAmbient = false; if (generateMaterials && storage.DataProvider != null && storage.DataProvider.ProvidesAmbient) { readAmbient = true; } m_cache.Resize(voxelStart, voxelEnd); if (readAmbient) { m_cache.StoreOcclusion = true; } storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd, ref request); if (request.HasFlag(MyVoxelRequestFlags.EmptyContent) || request.HasFlag(MyVoxelRequestFlags.FullContent) || (!request.HasFlag(MyVoxelRequestFlags.ContentChecked) && !m_cache.ContainsIsoSurface())) { //if(generateMaterials && lod == 0) Debugger.Break(); //storage.DebugDrawChunk(voxelStart, voxelEnd); return(null); } var center = (storage.Size / 2) * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var voxelSize = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod); var vertexCellOffset = voxelStart - AffectedRangeOffset; double numCellsHalf = 0.5 * (m_cache.Size3D.X - 3); var posOffset = ((Vector3D)vertexCellOffset + numCellsHalf) * (double)voxelSize; if (generateMaterials) { // 255 is the new black m_cache.ClearMaterials(255); } if (readAmbient) { m_cache.Clear(MyStorageDataTypeEnum.Occlusion, 0); } IsoMesher mesher = new IsoMesher(); ProfilerShort.Begin("Dual Contouring"); unsafe { fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content]) fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material]) { var size3d = m_cache.Size3D; Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z); mesher.Calculate(size3d.X, content, material, m_buffer, useAmbient, posOffset - center); } } ProfilerShort.End(); if (generateMaterials) { request = 0; request |= MyVoxelRequestFlags.SurfaceMaterial; request |= MyVoxelRequestFlags.ConsiderContent; var req = readAmbient ? MyStorageDataTypeFlags.Material | MyStorageDataTypeFlags.Occlusion : MyStorageDataTypeFlags.Material; storage.ReadRange(m_cache, req, lod, ref voxelStart, ref voxelEnd, ref request); FixCacheMaterial(voxelStart, voxelEnd); unsafe { fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content]) fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material]) { int materialOverride = request.HasFlag(MyVoxelRequestFlags.OneMaterial) ? m_cache.Material(0) : -1; var size3d = m_cache.Size3D; Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z); if (readAmbient) fixed(byte *ambient = m_cache[MyStorageDataTypeEnum.Occlusion]) mesher.CalculateMaterials(size3d.X, content, material, ambient, materialOverride); else { mesher.CalculateMaterials(size3d.X, content, material, null, materialOverride); } } } } else { m_cache.ClearMaterials(0); } mesher.Finish(m_buffer); if (m_buffer.VerticesCount == 0 || m_buffer.Triangles.Count == 0) { return(null); } ProfilerShort.Begin("Geometry post-processing"); { var positions = m_buffer.Positions.GetInternalArray(); var vertexCells = m_buffer.Cells.GetInternalArray(); var materials = m_buffer.Materials.GetInternalArray(); for (int i = 0; i < m_buffer.VerticesCount; i++) { Debug.Assert(positions[i].IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One)); vertexCells[i] += vertexCellOffset; Debug.Assert(vertexCells[i].IsInsideInclusive(voxelStart + 1, voxelEnd - 1)); Debug.Assert(materials[i] != MyVoxelConstants.NULL_MATERIAL); } m_buffer.PositionOffset = posOffset; m_buffer.PositionScale = new Vector3((float)(numCellsHalf * voxelSize)); m_buffer.CellStart = voxelStart + 1; m_buffer.CellEnd = voxelEnd - 1; } ProfilerShort.End(); // Replace filled mesh with new one. // This way prevents allocation of meshes which then end up empty. var buffer = m_buffer; m_buffer = new MyIsoMesh(); return(buffer); } }
protected override IEnumerator <bool> ProcessVoxels(HashSet <IMyVoxelBase> Voxels) { if (!MyKernel.Session.Settings.EnableDrilling) { yield return(false); } if (Voxels.Count == 0) { yield return(false); } if (MyKernel.TermControls.ToolMode == true) { yield return(false); } if (!SafeZonesHelper.IsActionAllowed(MyKernel.Block.GetPosition(), MySafeZoneAction.Drilling, MyKernel.Block.EntityId)) { yield return(false); } //WriteToLog("ProcessVoxels", $"Processing {Voxels.Count} voxels"); Stopwatch stopwatch = Stopwatch.StartNew(); LineD WorkingRay = new LineD(MyKernel.BeamDrawer.BeamStart, MyKernel.BeamDrawer.BeamEnd); foreach (MyVoxelBase Voxel in Voxels.OfType <MyVoxelBase>()) { if (!SafeZonesHelper.IsActionAllowed((Voxel as IMyEntity).WorldAABB, MySafeZoneAction.Drilling, MyKernel.Block.EntityId)) { continue; } if (Voxel.GetOrePriority() == -1) { continue; // Idk why, but the same early exit is found in MyShipDrill } Vector3D?VoxelHit = Voxel.GetClosestPointOnRay(WorkingRay, step: 0.99f); if (VoxelHit.HasValue) { MyKernel.ResponderModule.UpdateStatusReport($"\r\nFound a voxel", true); lock (BlockedVoxels) { if (!BlockedVoxels.ContainsKey(Voxel.EntityId)) { BlockedVoxels.Add(Voxel.EntityId, new List <Vector3I>()); } } Vector3D hitpos = VoxelHit.Value; //MyVoxelMaterialDefinition Material = Voxel.GetMaterialAt(ref hitpos); Vector3D CutoutSphereCenter = hitpos + (-WorkingRay.Direction * DrillingOffsetM); //stopwatch.Stop(); //WriteToLog("ProcessVoxels", $"Hit: {Math.Round(Vector3D.Distance(WorkingRay.From, hitpos), 2)}m, cutout: {Math.Round(Vector3D.Distance(WorkingRay.From, CutoutSphereCenter), 2)} m away, Material: {(Material != null ? Material.MaterialTypeName : "null")}"); //stopwatch.Start(); BoundingSphereD Cutout = new BoundingSphereD(CutoutSphereCenter, CutoutRadius); //List<Vector3I> VoxelPoints = Voxel.GetVoxelPointsInSphere(Cutout); Vector3I refCorner; Vector3I refMaxCorner; MyStorageData cutoutVoxels = Voxel.GetVoxelCacheInSphere(Cutout, out refCorner, out refMaxCorner); //WriteToLog("ProcessVoxels", $"Cutout cache Min is {Math.Round(Vector3D.Distance(hitpos, Voxel.PositionLeftBottomCorner + refCorner), 2)}m away"); //WriteToLog("ProcessVoxels", $"Cutout cache Max is {Math.Round(Vector3D.Distance(hitpos, Voxel.PositionLeftBottomCorner + refCorner + cutoutVoxels.Size3D), 2)}m away"); Dictionary <MyVoxelMaterialDefinition, float> Materials = new Dictionary <MyVoxelMaterialDefinition, float>(); int nullMaterials = 0; int totalPoints = 0; Stopwatch enumeratorWatch = new Stopwatch(); using (MyStorageData.MortonEnumerator VoxelLoop = new MyStorageData.MortonEnumerator(cutoutVoxels, MyStorageDataTypeEnum.Content | MyStorageDataTypeEnum.Material)) { MyKernel.ResponderModule.UpdateStatusReport($"Entered enumerator", true); enumeratorWatch.Start(); Dictionary <byte, float> RawMaterials = new Dictionary <byte, float>(); Vector3I VoxelInSphereCenter; Vector3 CoordsSystemOutValue; //MyVoxelCoordSystems.WorldPositionToLocalPosition(Cutout.Center, Voxel.PositionComp.WorldMatrix, Voxel.PositionComp.WorldMatrixInvScaled, Voxel.SizeInMetresHalf, out CoordsSystemOutValue); //VoxelInSphereCenter = new Vector3I(CoordsSystemOutValue / 1f) + Voxel.StorageMin; Vector3D sphereCenter = Cutout.Center; MyVoxelCoordSystems.WorldPositionToLocalPosition(Voxel.PositionLeftBottomCorner, ref sphereCenter, out CoordsSystemOutValue); VoxelInSphereCenter = new Vector3I(CoordsSystemOutValue / 1f) + Voxel.StorageMin; Vector3D ReconstructedPosition = Voxel.PositionLeftBottomCorner + VoxelInSphereCenter; //WriteToLog("ProcessVoxels", $"VoxelInSphereCenter is {Math.Round(Vector3D.Distance(hitpos, ReconstructedPosition), 2)}m away from hitpos"); double CutoutRadiusSquared = Cutout.Radius * Cutout.Radius; int processedPoints = 0; int skippedPoints = 0; int linearIndex = -1; for (bool move = true; move != false;) { enumeratorWatch.Start(); try { move = VoxelLoop.MoveNext(); } catch { move = false; MyKernel.ResponderModule.UpdateStatusReport("Keen enumerator died", true); } if (move) { linearIndex++; Vector3I voxelPoint; cutoutVoxels.ComputePosition(linearIndex, out voxelPoint); voxelPoint += refCorner; BoundingBoxD voxelBox = new BoundingBoxD(Voxel.PositionLeftBottomCorner + voxelPoint, Voxel.PositionLeftBottomCorner + voxelPoint + 1); var PointContainment = Cutout.Contains(voxelBox); bool Contacts = PointContainment.HasFlag(ContainmentType.Contains) || PointContainment.HasFlag(ContainmentType.Intersects); if (Contacts || Vector3D.DistanceSquared(ReconstructedPosition, Voxel.PositionLeftBottomCorner + voxelPoint) <= CutoutRadiusSquared) { bool pointBlocked = true; lock (BlockedVoxels) { pointBlocked = BlockedVoxels[Voxel.EntityId].Contains(voxelPoint); if (!pointBlocked) { BlockedVoxels[Voxel.EntityId].Add(voxelPoint); } } if (!pointBlocked) { byte ContentFillLevel = cutoutVoxels.Content(linearIndex); byte MaterialId = cutoutVoxels.Material(linearIndex); float MaterialFillRatio = ContentFillLevel / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; if (!RawMaterials.ContainsKey(MaterialId)) { RawMaterials.Add(MaterialId, MaterialFillRatio); } else { RawMaterials[MaterialId] += MaterialFillRatio; } processedPoints++; } else { skippedPoints++; } } else { skippedPoints++; } int voxelIterationLimit = MyKernel.Session.Settings.SpeedMultiplierAcceleratesDrilling ? VoxelIterationLimit * MyKernel.TermControls.SpeedMultiplier : VoxelIterationLimit; if (processedPoints > 0 && processedPoints % voxelIterationLimit == 0) { //MyKernel.ResponderModule.UpdateStatusReport($"Cutting out {Math.Round(Cutout.Radius * 2, 1)}m sphere:\r\n{linearIndex} voxels processed", append: true); enumeratorWatch.Stop(); yield return(true); } } totalPoints = linearIndex; } MyKernel.ResponderModule.UpdateStatusReport($"Total processed points: {totalPoints} ({processedPoints}/{skippedPoints})", true); enumeratorWatch.Stop(); MyKernel.ResponderModule.UpdateStatusReport($"EnumeratorWatch: {Math.Round(enumeratorWatch.Elapsed.TotalMilliseconds, 3)}ms", true); //WriteToLog("ProcessVoxels", $"Found {processedPoints} valid voxel points out of {totalPoints}", EemRdx.SessionModules.LoggingLevelEnum.DebugLog, true, 2000); foreach (KeyValuePair <byte, float> kvp in RawMaterials) { MyVoxelMaterialDefinition material = MyDefinitionManager.Static.GetVoxelMaterialDefinition(kvp.Key); if (material != null) { Materials.Add(material, kvp.Value * DrillingYield); } else { nullMaterials++; continue; } } } MyKernel.ResponderModule.UpdateStatusReport($"Quitted enumerator", true); //WriteToLog("ProcessVoxels", $"Found {VoxelPoints.Count} valid voxel points", EemRdx.SessionModules.LoggingLevelEnum.DebugLog, true, 2000); //WriteToLog("ProcessVoxels", $"Found {Materials.Count} valid materials{(nullMaterials > 0 ? $" and {nullMaterials} null materials" : "")}", EemRdx.SessionModules.LoggingLevelEnum.DebugLog, true, 2000); //foreach (var kvp in Materials) //{ // WriteToLog("ProcessVoxels", $"Material: {kvp.Key.MaterialTypeName} (mined ore: {(kvp.Key.MinedOre != null ? kvp.Key.MinedOre : "null")}), amount: {kvp.Value}"); //} MyKernel.ResponderModule.UpdateStatusReport($"Calculating materials", true); Dictionary <MyObjectBuilder_Ore, float> MaterialsToAdd = new Dictionary <MyObjectBuilder_Ore, float>(); int nullMinedOres = 0; foreach (KeyValuePair <MyVoxelMaterialDefinition, float> kvp in Materials) { MyVoxelMaterialDefinition material = kvp.Key; if (string.IsNullOrWhiteSpace(material.MinedOre)) { nullMinedOres++; continue; } try { if (MyKernel.TermControls.DumpStone && material.MinedOre == "Stone") { continue; } MyObjectBuilder_Ore oreBuilder = MyObjectBuilderSerializer.CreateNewObject <MyObjectBuilder_Ore>(material.MinedOre); oreBuilder.MaterialTypeName = new MyStringHash?(material.Id.SubtypeId); MyPhysicalItemDefinition oreDef = MyDefinitionManager.Static.GetPhysicalItemDefinition(oreBuilder); float MinedAmountInKg = (kvp.Value / 1000 / oreDef.Volume) * oreDef.Mass * kvp.Key.MinedOreRatio * 32; stopwatch.Stop(); //WriteToLog("ProcessVoxels", $"Found material {material.MaterialTypeName}, {Math.Round(kvp.Value)} points, mined amount would be {Math.Round(MinedAmountInKg)} kg"); stopwatch.Start(); MaterialsToAdd.Add(oreBuilder, MinedAmountInKg); } catch (Exception Scrap) { LogError("ProcessVoxels().dict_Materials.Iterate", $"Unknown error occurred on material {material.MinedOre}", Scrap); } } Stopwatch cutoutWatch = Stopwatch.StartNew(); //Voxel.Storage.WriteRange(cutoutVoxels, MyStorageDataTypeFlags.ContentAndMaterial, refCorner - 1, refMaxCorner + 1); Voxel.RootVoxel.PerformCutOutSphereFast(Cutout.Center, (float)Cutout.Radius, true); cutoutWatch.Stop(); //WriteToLog("ProcessVoxels", $"Sphere was cut in {cutoutWatch.ElapsedTicks} ticks, which is {Math.Round(cutoutWatch.Elapsed.TotalMilliseconds, 4)} ms"); foreach (var kvp in MaterialsToAdd) { MyDefinitionId OreId = kvp.Key.GetId(); MyItemType oreItemType = new MyItemType(OreId.TypeId, OreId.SubtypeId); float amountToAdd = kvp.Value; while (amountToAdd > 0.1f) { while (((float)ToolCargo.CurrentVolume / (float)ToolCargo.MaxVolume) > 0.9f) { yield return(true); } MyInventoryItem oreItem = new MyInventoryItem(oreItemType, 0, (VRage.MyFixedPoint)amountToAdd); float FittingAmount = (float)(ToolCargo as Sandbox.Game.MyInventory).ComputeAmountThatFits(OreId); if (FittingAmount > amountToAdd) { FittingAmount = amountToAdd; } ToolCargo.AddItems((VRage.MyFixedPoint)FittingAmount, kvp.Key); amountToAdd -= FittingAmount; //MyKernel.ResponderModule.UpdateStatusReport($"Adding {Math.Round(FittingAmount)}u of {OreId.SubtypeId}, {amountToAdd} remains", append: false); } } } else { MyKernel.ResponderModule.UpdateStatusReport($"No voxel found", true); } } stopwatch.Stop(); double ElapsedMs = stopwatch.Elapsed.TotalMilliseconds; //WriteToLog("ProcessVoxels", $"Voxels processed, elapsed time: {stopwatch.ElapsedTicks} ticks, which is {Math.Round(ElapsedMs, 3)} ms"); MyKernel.ResponderModule.UpdateStatusReport($"Cycle finished", true); yield return(false); }
public unsafe void ReadMaterialRange(ref MyVoxelDataRequest req, bool detectOnly = false) { Vector3I vectori4; req.Flags = req.RequestFlags & MyVoxelRequestFlags.RequestFlags; Vector3I minInLod = req.MinInLod; Vector3I maxInLod = req.MaxInLod; float lodSize = 1 << (req.Lod & 0x1f); bool flag = req.RequestFlags.HasFlags(MyVoxelRequestFlags.SurfaceMaterial); bool flag2 = req.RequestFlags.HasFlags(MyVoxelRequestFlags.ConsiderContent); bool preciseOrePositions = req.RequestFlags.HasFlags(MyVoxelRequestFlags.PreciseOrePositions); this.m_planetShape.PrepareCache(); if (this.m_biomes != null) { if (req.SizeLinear > 0x7d) { BoundingBox request = new BoundingBox((Vector3)(minInLod * lodSize), (Vector3)(maxInLod * lodSize)); this.PrepareRulesForBoxInternal(ref request); } else if (!m_rangeClean || !ReferenceEquals(CachedProvider, this)) { this.CleanRules(); } } Vector3 vector = (minInLod + 0.5f) * lodSize; Vector3 pos = vector; Vector3I vectori3 = (Vector3I)(-minInLod + req.Offset); if (detectOnly) { vectori4.Z = minInLod.Z; while (vectori4.Z <= maxInLod.Z) { vectori4.Y = minInLod.Y; while (true) { if (vectori4.Y > maxInLod.Y) { float *singlePtr3 = (float *)ref pos.Z; singlePtr3[0] += lodSize; pos.Y = vector.Y; int *numPtr3 = (int *)ref vectori4.Z; numPtr3[0]++; break; } vectori4.X = minInLod.X; while (true) { byte num2; if (vectori4.X > maxInLod.X) { float *singlePtr2 = (float *)ref pos.Y; singlePtr2[0] += lodSize; pos.X = vector.X; int *numPtr2 = (int *)ref vectori4.Y; numPtr2[0]++; break; } MyVoxelMaterialDefinition definition = this.GetMaterialForPosition(ref pos, lodSize, out num2, preciseOrePositions); if ((definition != null) && (definition.Index != 0xff)) { return; } float *singlePtr1 = (float *)ref pos.X; singlePtr1[0] += lodSize; int *numPtr1 = (int *)ref vectori4.X; numPtr1[0]++; } } } MyVoxelRequestFlags *flagsPtr1 = (MyVoxelRequestFlags *)ref req.Flags; *((int *)flagsPtr1) |= 8; } else { bool flag4 = true; MyStorageData target = req.Target; vectori4.Z = minInLod.Z; while (true) { while (true) { if (vectori4.Z <= maxInLod.Z) { vectori4.Y = minInLod.Y; break; } if (flag4) { MyVoxelRequestFlags *flagsPtr2 = (MyVoxelRequestFlags *)ref req.Flags; *((int *)flagsPtr2) |= 8; } return; } while (true) { if (vectori4.Y > maxInLod.Y) { float *singlePtr6 = (float *)ref pos.Z; singlePtr6[0] += lodSize; pos.Y = vector.Y; int *numPtr6 = (int *)ref vectori4.Z; numPtr6[0]++; break; } vectori4.X = minInLod.X; Vector3I p = (Vector3I)(vectori4 + vectori3); int linearIdx = target.ComputeLinear(ref p); while (true) { if (vectori4.X <= maxInLod.X) { byte num4; if ((!flag || (target.Material(linearIdx) == 0)) && (!flag2 || (target.Content(linearIdx) != 0))) { byte num5; MyVoxelMaterialDefinition definition2 = this.GetMaterialForPosition(ref pos, lodSize, out num5, preciseOrePositions); num4 = (definition2 != null) ? definition2.Index : ((byte)0xff); } else { num4 = 0xff; } target.Material(linearIdx, num4); flag4 &= num4 == 0xff; linearIdx += target.StepLinear; float *singlePtr4 = (float *)ref pos.X; singlePtr4[0] += lodSize; int *numPtr4 = (int *)ref vectori4.X; numPtr4[0]++; continue; } else { float *singlePtr5 = (float *)ref pos.Y; singlePtr5[0] += lodSize; pos.X = vector.X; int *numPtr5 = (int *)ref vectori4.Y; numPtr5[0]++; } break; } } } } }
public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 direction, MyVoxelMaterialDefinition material) { ProfilerShort.Begin("MakeCrater"); Vector3 normal = Vector3.Normalize(sphere.Center - voxelMap.RootVoxel.WorldMatrix.Translation); Vector3I minCorner, maxCorner; { Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f; Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES) * 1.3f; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner); } voxelMap.Storage.ClampVoxelCoord(ref minCorner); voxelMap.Storage.ClampVoxelCoord(ref maxCorner); Vector3I worldMinCorner = minCorner + voxelMap.StorageMin; Vector3I worldMaxCorner = maxCorner + voxelMap.StorageMin; // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache bool changed = false; ProfilerShort.Begin("Reading cache"); m_cache.Resize(minCorner, maxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref worldMinCorner, ref worldMaxCorner); ProfilerShort.End(); ProfilerShort.Begin("Changing cache"); int removedVoxelContent = 0; Vector3I tempVoxelCoord; Vector3I cachePos = (maxCorner - minCorner) / 2; byte oldMaterial = m_cache.Material(ref cachePos); float digRatio = 1 - Vector3.Dot(normal, direction); Vector3 newCenter = sphere.Center - normal * (float)sphere.Radius * 1.1f;//0.9f; float sphRadA = (float)(sphere.Radius * 1.5f); float sphRadSqA = (float)(sphRadA * sphRadA); float voxelSizeHalfTransformedPosA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); float voxelSizeHalfTransformedNegA = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadA + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); Vector3 newDelCenter = newCenter + normal * (float)sphere.Radius * (0.7f + digRatio) + direction * (float)sphere.Radius * 0.65f; float sphRadD = (float)(sphere.Radius); float sphRadSqD = (float)(sphRadD * sphRadD); float voxelSizeHalfTransformedPosD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); float voxelSizeHalfTransformedNegD = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (-2 * sphRadD + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); Vector3 newSetCenter = newCenter + normal * (float)sphere.Radius * (digRatio) + direction * (float)sphere.Radius * 0.3f; float sphRadS = (float)(sphere.Radius * 0.1f); float sphRadSqS = (float)(sphRadS * sphRadS); float voxelSizeHalfTransformedPosS = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (2 * sphRadS + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z) { for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y) { for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X) { Vector3D voxelPosition; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition); byte originalContent = m_cache.Content(ref cachePos); //Add sphere if (originalContent != MyVoxelConstants.VOXEL_CONTENT_FULL) { float addDist = (float)(voxelPosition - newCenter).LengthSquared(); float addDiff = (float)(addDist - sphRadSqA); byte newContent; if (addDiff > voxelSizeHalfTransformedPosA) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (addDiff < voxelSizeHalfTransformedNegA) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { float value = (float)Math.Sqrt(addDist + sphRadSqA - 2 * sphRadA * Math.Sqrt(addDist)); if (addDiff < 0) { value = -value; } // This formula will work even if diff is positive or negative newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } if (newContent > originalContent) { if (material != null) { m_cache.Material(ref cachePos, oldMaterial); } changed = true; m_cache.Content(ref cachePos, newContent); } } //Delete sphere float delDist = (float)(voxelPosition - newDelCenter).LengthSquared(); float delDiff = (float)(delDist - sphRadSqD); byte contentToRemove; if (delDiff > voxelSizeHalfTransformedPosD) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (delDiff < voxelSizeHalfTransformedNegD) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { float value = (float)Math.Sqrt(delDist + sphRadSqD - 2 * sphRadD * Math.Sqrt(delDist)); if (delDiff < 0) { value = -value; } // This formula will work even if diff is positive or negative contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - value / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { changed = true; int newVal = originalContent - contentToRemove; if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY) { newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } m_cache.Content(ref cachePos, (byte)newVal); removedVoxelContent += originalContent - newVal; } //Set material float setDist = (float)(voxelPosition - newSetCenter).LengthSquared(); float setDiff = (float)(setDist - sphRadSqS); if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f) // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly { MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos)); // Change the material: // - always on boundaries between material and nothing // - smoothly on inner boundaries MyVoxelMaterialDefinition newMaterial = material; if (setDiff > 0) { byte content = m_cache.Content(ref cachePos); if (content == MyVoxelConstants.VOXEL_CONTENT_FULL) { newMaterial = originalMaterial; } if (setDiff >= voxelSizeHalfTransformedPosS && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY) // set material behind boundary only for empty voxels { newMaterial = originalMaterial; } } if (originalMaterial == newMaterial) { continue; } m_cache.Material(ref cachePos, newMaterial.Index); changed = true; } float dist = (float)(voxelPosition - newCenter).LengthSquared(); float diff = (float)(dist - sphRadSqA); if (diff <= 0f) { originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE); if (wrinkled) { changed = true; } } } } } } ProfilerShort.End(); if (changed) { ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels"); RemoveSmallVoxelsUsingChachedVoxels(); ProfilerShort.BeginNextBlock("Writing cache"); minCorner += voxelMap.StorageMin; maxCorner += voxelMap.StorageMin; voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner); MyShapeSphere sphereShape = new MyShapeSphere(); sphereShape.Center = sphere.Center; sphereShape.Radius = (float)(sphere.Radius * 1.5); OnVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, sphereShape); ProfilerShort.End(); } ProfilerShort.End(); }
public override bool Invoke(string messageText) { if (messageText.StartsWith("/rotateroid ", StringComparison.InvariantCultureIgnoreCase)) { var match = Regex.Match(messageText, @"/rotateroid\s{1,}(?<Key>.+){1,}\s{1,}(?<X>[+-]?((\d+(\.\d*)?)|(\.\d+)))\s{1,}(?<Y>[+-]?((\d+(\.\d*)?)|(\.\d+)))\s{1,}(?<Z>[+-]?((\d+(\.\d*)?)|(\.\d+)))", RegexOptions.IgnoreCase); if (match.Success) { var rotateVector = new Vector3( double.Parse(match.Groups["X"].Value, CultureInfo.InvariantCulture), double.Parse(match.Groups["Y"].Value, CultureInfo.InvariantCulture), double.Parse(match.Groups["Z"].Value, CultureInfo.InvariantCulture)); var searchName = match.Groups["Key"].Value; var currentAsteroidList = new List<IMyVoxelBase>(); IMyVoxelBase originalAsteroid = null; MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(searchName, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count == 1) { originalAsteroid = currentAsteroidList[0]; } else { MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.IndexOf(searchName, StringComparison.InvariantCultureIgnoreCase) >= 0); if (currentAsteroidList.Count == 1) { originalAsteroid = currentAsteroidList[0]; } } int index; if (searchName.Substring(0, 1) == "#" && Int32.TryParse(searchName.Substring(1), out index) && index > 0 && index <= CommandAsteroidsList.AsteroidCache.Count) { originalAsteroid = CommandAsteroidsList.AsteroidCache[index - 1]; } if (originalAsteroid == null) { MyAPIGateway.Utilities.ShowMessage("Cannot find asteroid", string.Format("'{0}'", searchName)); return true; } var quaternion = Quaternion.CreateFromYawPitchRoll(rotateVector.X / (180 / MathHelper.Pi), rotateVector.Y / (180 / MathHelper.Pi), rotateVector.Z / (180 / MathHelper.Pi)); var oldStorage = originalAsteroid.Storage; var oldCache = new MyStorageData(); oldCache.Resize(oldStorage.Size); oldStorage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, Vector3I.Zero, oldStorage.Size - 1); var transSize = Vector3I.Transform(oldStorage.Size, quaternion); var newSize = Vector3I.Abs(transSize); var newName = Support.CreateUniqueStorageName(originalAsteroid.StorageName); var newVoxelMap = Support.CreateNewAsteroid(newName, newSize, originalAsteroid.PositionLeftBottomCorner); var cache = new MyStorageData(); var min = Vector3I.Zero; var max = newSize - 1; cache.Resize(min, max); Vector3I p; for (p.Z = 0; p.Z < oldStorage.Size.Z; ++p.Z) for (p.Y = 0; p.Y < oldStorage.Size.Y; ++p.Y) for (p.X = 0; p.X < oldStorage.Size.X; ++p.X) { var content = oldCache.Content(ref p); var material = oldCache.Material(ref p); var newP = Vector3I.Transform(p, quaternion); // readjust the points, as rotation occurs arround 0,0,0. newP.X = newP.X < 0 ? newP.X - transSize.X - 1 : newP.X; newP.Y = newP.Y < 0 ? newP.Y - transSize.Y - 1 : newP.Y; newP.Z = newP.Z < 0 ? newP.Z - transSize.Z - 1 : newP.Z; cache.Content(ref newP, content); cache.Material(ref newP, material); } newVoxelMap.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, min, max); MyAPIGateway.Entities.RemoveEntity((IMyEntity)originalAsteroid); // Invalidate the cache, to force user to select again to prevent possible corruption by using an old cache. CommandAsteroidsList.AsteroidCache.Clear(); return true; } } return false; }
public static MyVoxelMaterialDefinition GetMaterialAt(this IMyStorage self, ref Vector3D localCoords) { MyVoxelMaterialDefinition def; Vector3I voxelCoords = Vector3D.Floor(localCoords / MyVoxelConstants.VOXEL_SIZE_IN_METRES); MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); cache.ClearMaterials(0); self.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, ref voxelCoords, ref voxelCoords); def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(cache.Material(0)); return def; }
private bool FindMaterial(IMyStorage storage, byte[] findMaterial) { if (findMaterial.Length == 0) return false; var oldCache = new MyStorageData(); oldCache.Resize(storage.Size); storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 2, Vector3I.Zero, storage.Size - 1); //MyAPIGateway.Utilities.ShowMessage("check", string.Format("SizeLinear {0} {1}.", oldCache.SizeLinear, oldCache.StepLinear)); Vector3I p; for (p.Z = 0; p.Z < storage.Size.Z; ++p.Z) for (p.Y = 0; p.Y < storage.Size.Y; ++p.Y) for (p.X = 0; p.X < storage.Size.X; ++p.X) { var content = oldCache.Content(ref p); var material = oldCache.Material(ref p); if (content > 0 && findMaterial.Contains(material)) { return true; } } return false; }
public unsafe MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream) { Vector3I vectori; Vector3I vectori2; Vector3I vectori6; vectori.X = stream.ReadInt32(); vectori.Y = stream.ReadInt32(); vectori.Z = stream.ReadInt32(); MyOctreeStorage storage = new MyOctreeStorage(null, vectori); vectori2.X = stream.ReadInt32(); vectori2.Y = stream.ReadInt32(); vectori2.Z = stream.ReadInt32(); Vector3I vectori3 = (Vector3I)(vectori / vectori2); Dictionary <byte, MyVoxelMaterialDefinition> mapping = null; if (fileVersion == 2) { mapping = this.Compatibility_LoadMaterialIndexMapping(stream); } else { int num2 = fileVersion; } Vector3I zero = Vector3I.Zero; Vector3I end = new Vector3I(7); MyStorageData source = new MyStorageData(MyStorageDataTypeFlags.All); source.Resize(Vector3I.Zero, end); vectori6.X = 0; while (vectori6.X < vectori3.X) { vectori6.Y = 0; while (true) { if (vectori6.Y >= vectori3.Y) { int *numPtr6 = (int *)ref vectori6.X; numPtr6[0]++; break; } vectori6.Z = 0; while (true) { if (vectori6.Z >= vectori3.Z) { int *numPtr5 = (int *)ref vectori6.Y; numPtr5[0]++; break; } MyVoxelContentConstitution constitution = (MyVoxelContentConstitution)stream.ReadByteNoAlloc(); switch (constitution) { case MyVoxelContentConstitution.Empty: source.ClearContent(0); break; case MyVoxelContentConstitution.Full: source.ClearContent(0xff); break; case MyVoxelContentConstitution.Mixed: Vector3I vectori7; vectori7.X = 0; while (vectori7.X < 8) { vectori7.Y = 0; while (true) { if (vectori7.Y >= 8) { int *numPtr3 = (int *)ref vectori7.X; numPtr3[0]++; break; } vectori7.Z = 0; while (true) { if (vectori7.Z >= 8) { int *numPtr2 = (int *)ref vectori7.Y; numPtr2[0]++; break; } source.Content(ref vectori7, stream.ReadByteNoAlloc()); int *numPtr1 = (int *)ref vectori7.Z; numPtr1[0]++; } } } break; default: break; } zero = vectori6 * 8; storage.WriteRange(source, MyStorageDataTypeFlags.Content, zero, (Vector3I)(zero + 7), true, false); int *numPtr4 = (int *)ref vectori6.Z; numPtr4[0]++; } } } try { vectori6.X = 0; while (vectori6.X < vectori3.X) { vectori6.Y = 0; while (true) { if (vectori6.Y >= vectori3.Y) { int *numPtr12 = (int *)ref vectori6.X; numPtr12[0]++; break; } vectori6.Z = 0; while (true) { if (vectori6.Z >= vectori3.Z) { int *numPtr11 = (int *)ref vectori6.Y; numPtr11[0]++; break; } MyVoxelMaterialDefinition definition = null; if (stream.ReadByteNoAlloc() == 1) { source.ClearMaterials(this.Compatibility_LoadCellVoxelMaterial(stream, mapping).Index); } else { Vector3I vectori8; vectori8.X = 0; while (vectori8.X < 8) { vectori8.Y = 0; while (true) { if (vectori8.Y >= 8) { int *numPtr9 = (int *)ref vectori8.X; numPtr9[0]++; break; } vectori8.Z = 0; while (true) { if (vectori8.Z >= 8) { int *numPtr8 = (int *)ref vectori8.Y; numPtr8[0]++; break; } definition = this.Compatibility_LoadCellVoxelMaterial(stream, mapping); stream.ReadByteNoAlloc(); source.Material(ref vectori8, definition.Index); int *numPtr7 = (int *)ref vectori8.Z; numPtr7[0]++; } } } } zero = vectori6 * 8; storage.WriteRange(source, MyStorageDataTypeFlags.Material, zero, (Vector3I)(zero + 7), true, false); int *numPtr10 = (int *)ref vectori6.Z; numPtr10[0]++; } } } } catch (EndOfStreamException exception) { MySandboxGame.Log.WriteLine(exception); } return(storage); }
// Linearly interpolates position, normal and material on poly-cube edge. Interpolated point is where an isosurface cuts an edge between two vertices, each with their own scalar value. void GetVertexInterpolation(MyStorageData cache, MyTemporaryVoxel inputVoxelA, MyTemporaryVoxel inputVoxelB, int edgeIndex) { MyEdge edge = m_edges[edgeIndex]; byte contentA = cache.Content(inputVoxelA.IdxInCache); byte contentB = cache.Content(inputVoxelB.IdxInCache); byte materialA = cache.Material(inputVoxelA.IdxInCache); byte materialB = cache.Material(inputVoxelB.IdxInCache); if (Math.Abs(MyVoxelConstants.VOXEL_ISO_LEVEL - contentA) < 0.00001f) { edge.Position = inputVoxelA.Position; edge.Normal = inputVoxelA.Normal; edge.Material = materialA; edge.Ambient = inputVoxelA.Ambient; return; } if (Math.Abs(MyVoxelConstants.VOXEL_ISO_LEVEL - contentB) < 0.00001f) { edge.Position = inputVoxelB.Position; edge.Normal = inputVoxelB.Normal; edge.Material = materialB; edge.Ambient = inputVoxelB.Ambient; return; } float mu = (float)(MyVoxelConstants.VOXEL_ISO_LEVEL - contentA) / (float)(contentB - contentA); Debug.Assert(mu > 0.0f && mu < 1.0f); edge.Position.X = inputVoxelA.Position.X + mu * (inputVoxelB.Position.X - inputVoxelA.Position.X); edge.Position.Y = inputVoxelA.Position.Y + mu * (inputVoxelB.Position.Y - inputVoxelA.Position.Y); edge.Position.Z = inputVoxelA.Position.Z + mu * (inputVoxelB.Position.Z - inputVoxelA.Position.Z); //edge.Normal = ComputeVertexNormal(ref edge.Position); edge.Normal.X = inputVoxelA.Normal.X + mu * (inputVoxelB.Normal.X - inputVoxelA.Normal.X); edge.Normal.Y = inputVoxelA.Normal.Y + mu * (inputVoxelB.Normal.Y - inputVoxelA.Normal.Y); edge.Normal.Z = inputVoxelA.Normal.Z + mu * (inputVoxelB.Normal.Z - inputVoxelA.Normal.Z); if (MyUtils.IsZero(edge.Normal)) { edge.Normal = inputVoxelA.Normal; } else { edge.Normal = MyUtils.Normalize(edge.Normal); } if (MyUtils.IsZero(edge.Normal)) { edge.Normal = inputVoxelA.Normal; } float mu2 = ((float)contentB) / (((float)contentA) + ((float)contentB)); edge.Material = (mu2 <= 0.5f) ? materialA : materialB; edge.Ambient = inputVoxelA.Ambient + mu2 * (inputVoxelB.Ambient - inputVoxelA.Ambient); return; }
// Linearly interpolates position, normal and material on poly-cube edge. Interpolated point is where an isosurface cuts an edge between two vertices, each with their own scalar value. void GetVertexInterpolation(MyStorageData cache, MyTemporaryVoxel inputVoxelA, MyTemporaryVoxel inputVoxelB, int edgeIndex) { MyEdge edge = m_edges[edgeIndex]; byte contentA = cache.Content(inputVoxelA.IdxInCache); byte contentB = cache.Content(inputVoxelB.IdxInCache); byte materialA = cache.Material(inputVoxelA.IdxInCache); byte materialB = cache.Material(inputVoxelB.IdxInCache); if (Math.Abs(MyVoxelConstants.VOXEL_ISO_LEVEL - contentA) < 0.00001f) { edge.Position = inputVoxelA.Position; edge.Normal = inputVoxelA.Normal; edge.Material = materialA; edge.Ambient = inputVoxelA.Ambient; return; } if (Math.Abs(MyVoxelConstants.VOXEL_ISO_LEVEL - contentB) < 0.00001f) { edge.Position = inputVoxelB.Position; edge.Normal = inputVoxelB.Normal; edge.Material = materialB; edge.Ambient = inputVoxelB.Ambient; return; } float mu = (float)(MyVoxelConstants.VOXEL_ISO_LEVEL - contentA) / (float)(contentB - contentA); Debug.Assert(mu > 0.0f && mu < 1.0f); edge.Position.X = inputVoxelA.Position.X + mu * (inputVoxelB.Position.X - inputVoxelA.Position.X); edge.Position.Y = inputVoxelA.Position.Y + mu * (inputVoxelB.Position.Y - inputVoxelA.Position.Y); edge.Position.Z = inputVoxelA.Position.Z + mu * (inputVoxelB.Position.Z - inputVoxelA.Position.Z); //edge.Normal = ComputeVertexNormal(ref edge.Position); edge.Normal.X = inputVoxelA.Normal.X + mu * (inputVoxelB.Normal.X - inputVoxelA.Normal.X); edge.Normal.Y = inputVoxelA.Normal.Y + mu * (inputVoxelB.Normal.Y - inputVoxelA.Normal.Y); edge.Normal.Z = inputVoxelA.Normal.Z + mu * (inputVoxelB.Normal.Z - inputVoxelA.Normal.Z); if (MyUtils.IsZero(edge.Normal)) edge.Normal = inputVoxelA.Normal; else edge.Normal = MyUtils.Normalize(edge.Normal); if (MyUtils.IsZero(edge.Normal)) edge.Normal = inputVoxelA.Normal; float mu2 = ((float)contentB) / (((float)contentA) + ((float)contentB)); edge.Material = (mu2 <= 0.5f) ? materialA : materialB; edge.Ambient = inputVoxelA.Ambient + mu2 * (inputVoxelB.Ambient - inputVoxelA.Ambient); return; }
private unsafe void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell, long detectorId) { Vector3I lodVoxelRangeMin = cell << 3; Vector3I lodVoxelRangeMax = (Vector3I)(lodVoxelRangeMin + 7); storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 2, lodVoxelRangeMin, lodVoxelRangeMax); if (cache.ContainsVoxelsAboveIsoLevel()) { Vector3I vectori3; MyVoxelRequestFlags preciseOrePositions = MyVoxelRequestFlags.PreciseOrePositions; storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 2, lodVoxelRangeMin, lodVoxelRangeMax, ref preciseOrePositions); MaterialPositionData[] materialData = MaterialData; vectori3.Z = 0; while (vectori3.Z < 8) { vectori3.Y = 0; while (true) { if (vectori3.Y >= 8) { int *numPtr4 = (int *)ref vectori3.Z; numPtr4[0]++; break; } vectori3.X = 0; while (true) { if (vectori3.X >= 8) { int *numPtr3 = (int *)ref vectori3.Y; numPtr3[0]++; break; } int linearIdx = cache.ComputeLinear(ref vectori3); if (cache.Content(linearIdx) > 0x7f) { byte index = cache.Material(linearIdx); Vector3D vectord = ((vectori3 + lodVoxelRangeMin) * 4f) + 2f; Vector3 *vectorPtr1 = (Vector3 *)ref materialData[index].Sum; vectorPtr1[0] += vectord; int *numPtr1 = (int *)ref materialData[index].Count; numPtr1[0]++; } int *numPtr2 = (int *)ref vectori3.X; numPtr2[0]++; } } } MyEntityOreDeposit item = null; for (int i = 0; i < materialData.Length; i++) { if (materialData[i].Count != 0) { MyVoxelMaterialDefinition voxelMaterialDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition((byte)i); if ((voxelMaterialDefinition != null) && voxelMaterialDefinition.IsRare) { if (item == null) { item = new MyEntityOreDeposit(this.VoxelMap, cell, detectorId); } MyEntityOreDeposit.Data data = new MyEntityOreDeposit.Data { Material = voxelMaterialDefinition, AverageLocalPosition = (Vector3)Vector3D.Transform((materialData[i].Sum / ((float)materialData[i].Count)) - this.VoxelMap.SizeInMetresHalf, Quaternion.CreateFromRotationMatrix(this.VoxelMap.WorldMatrix)) }; item.Materials.Add(data); } } } if (item != null) { this.m_result.Add(item); } else { this.m_emptyCells.Add(cell); } Array.Clear(materialData, 0, materialData.Length); } }
private void ProcessCell(MyStorageData cache, IMyStorage storage, Vector3I cell, long detectorId) { //bool m_miningDebug = false; if (cache == null || storage == null) { return; } Vector3I vector3I = cell << 3; Vector3I lodVoxelRangeMax = vector3I + 7; // Advice cache because of performance issues var flag = MyVoxelRequestFlags.ContentCheckedDeep; Stopwatch stopwatch = Stopwatch.StartNew(); storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, vector3I, lodVoxelRangeMax, ref flag); stopwatch.Stop(); int readingTime = (int)((stopwatch.ElapsedTicks * 1000000) / Stopwatch.Frequency); if (readingTime > 1000) { int changeAmount = (int)(readingTime / 1000); if (MyAPIGateway.Physics.ServerSimulationRatio < 1.00f) { sleepTimer += changeAmount * 100; } else { sleepTimer = Math.Max(sleepTimer - 1, 1); } MyAPIGateway.Parallel.Sleep(sleepTimer); } //if (m_miningDebug) //Logging.Instance.WriteLine($"ProcessCell.ReadRange(1) took {(stopwatch.ElapsedTicks * 1000000)/Stopwatch.Frequency} microseconds"); if (cache.ContainsVoxelsAboveIsoLevel()) { //Stopwatch stopwatch2 = Stopwatch.StartNew(); storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, vector3I, lodVoxelRangeMax, ref flag); //stopwatch2.Stop(); //if (m_miningDebug) //Logging.Instance.WriteLine($"ProcessCell.ReadRange(2) took {(stopwatch2.ElapsedTicks * 1000000)/Stopwatch.Frequency} microseconds"); Vector3I p = default(Vector3I); p.Z = 0; while (p.Z < 8) { p.Y = 0; while (p.Y < 8) { p.X = 0; while (p.X < 8) { int linearIdx = cache.ComputeLinear(ref p); if (cache.Content(linearIdx) > 127) { byte b = cache.Material(linearIdx); if (HasFilterUpgrade) { var voxelDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition(b); if (voxelDefinition != null && voxelDefinition.MinedOre != null) { foreach (string mat in OreListSelected) { if (voxelDefinition.MinedOre.ToLower() == mat.ToLower()) { Materials.AddMaterial(b, vector3I + p); break; } } } else { Materials.AddMaterial(b, vector3I + p); } } else { Materials.AddMaterial(b, vector3I + p); } } p.X++; } p.Y++; } p.Z++; } } }
private void ReadVoxel(IMyVoxelBase voxel, Vector3D position, Dictionary <Vector3D, NaniteMiningItem> targets, HashSet <string> allowedOreList = null) { var m_cache = new MyStorageData(); NaniteShapeSphere shapeSphere = new NaniteShapeSphere(); shapeSphere.Center = position; shapeSphere.Radius = NaniteConstructionManager.Settings.MiningRadius / 2; //NaniteShapeCapsule shapeCapsule = new NaniteShapeCapsule(); //shapeCapsule.A = positionA; //shapeCapsule.B = positionB; //shapeCapsule.Radius = NaniteConstructionManager.Settings.MiningRadius; Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxel, shapeSphere, out minCorner, out maxCorner, out numCells); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; //bool bRareOnly = true; //if (allowedOreList != null && allowedOreList.Contains("Stone")) // bRareOnly = false; m_cache.Resize(cacheMin, cacheMax); m_cache.ClearContent(0); m_cache.ClearMaterials(0); var flags = MyVoxelRequestFlags.AdviseCache; voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax, ref flags); //voxel.Storage.PinAndExecute(() => { Vector3I pos; for (pos.X = minCorner.X; pos.X <= maxCorner.X; ++pos.X) { for (pos.Y = minCorner.Y; pos.Y <= maxCorner.Y; ++pos.Y) { for (pos.Z = minCorner.Z; pos.Z <= maxCorner.Z; ++pos.Z) { // get original amount var relPos = pos - cacheMin; var lin = m_cache.ComputeLinear(ref relPos); //var relPos = pos - cacheMin; // Position of voxel in local space var original = m_cache.Content(lin); // Content at this position if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { continue; } var material = m_cache.Material(lin); // Material at this position Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref pos, out vpos); if (targets.ContainsKey(vpos)) { continue; } /* * var volume = shapeSphere.GetVolume(ref vpos); * if (volume == 0f) // Shape and voxel do not intersect at this position, so continue * continue; */ // Pull information about voxel required for later processing var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly) //if(voxelMat.IsRare) if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare)) { if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre)) { continue; } NaniteMiningItem miningItem = new NaniteMiningItem(); miningItem.Position = vpos; miningItem.VoxelMaterial = material; miningItem.VoxelId = voxel.EntityId; miningItem.Amount = original; // * 3.9f; miningItem.MiningHammer = this; targets.Add(vpos, miningItem); //count++; } //m_cache.Content(lin, 0); //m_cache.Material(lin, 0); } } } //voxel.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, cacheMin, cacheMax); }; /* * int count = 0; * for (var itCells = new Vector3I_RangeIterator(ref Vector3I.Zero, ref numCells); itCells.IsValid(); itCells.MoveNext()) * { * Vector3I cellMinCorner, cellMaxCorner; * GetCellCorners(ref minCorner, ref maxCorner, ref itCells, out cellMinCorner, out cellMaxCorner); * * var cacheMin = cellMinCorner - 1; * var cacheMax = cellMaxCorner + 1; * voxel.Storage.ClampVoxel(ref cacheMin); * voxel.Storage.ClampVoxel(ref cacheMax); * * m_cache.Resize(cacheMin, cacheMax); * voxel.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, cacheMin, cacheMax); * * for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) * { * var relPos = it.Current - cacheMin; // Position of voxel in local space * var original = m_cache.Content(ref relPos); // Content at this position * var material = m_cache.Material(ref relPos); // Material at this position * * if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) * continue; * * Vector3D vpos; * MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref it.Current, out vpos); * if (targets.ContainsKey(vpos)) * continue; * * var volume = shapeSphere.GetVolume(ref vpos); * if (volume == 0f) // Shape and voxel do not intersect at this position, so continue * continue; * * // Pull information about voxel required for later processing * var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); * //if ((bRareOnly && voxelMat.IsRare) || !bRareOnly) * //if(voxelMat.IsRare) * if (allowedOreList != null)// || (allowedOreList == null && bRareOnly && voxelMat.IsRare)) * { * if (allowedOreList != null && !allowedOreList.Contains(voxelMat.MinedOre)) * continue; * * NaniteMiningItem miningItem = new NaniteMiningItem(); * miningItem.Position = vpos; * miningItem.VoxelMaterial = material; * miningItem.VoxelId = voxel.EntityId; * miningItem.Amount = original; // * 3.9f; * miningItem.MiningHammer = this; * targets.Add(vpos, miningItem); * count++; * } * } * } */ //Logging.Instance.WriteLine(string.Format("Voxels Read: {0} - {1}", voxel.GetType().Name, count)); }
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 block; Vector3I newBlock; Vector3I cacheSize; var asteroid = new MyVoxelMap(); asteroid.Load(filenameSecondary); BoundingBoxI content = modelSecondary.InflatedContentBounds; for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64) { for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64) { for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64) { var cache = new MyStorageData(); cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1, MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1, MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1); cache.Resize(cacheSize); asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1); newBlock = ((minSecondary - min) + (Vector3D)(block - content.Min)).RoundToVector3I(); newAsteroid.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1); } } } asteroid.Load(filenamePrimary); content = modelPrimary.InflatedContentBounds; for (block.Z = content.Min.Z; block.Z <= content.Max.Z; block.Z += 64) { for (block.Y = content.Min.Y; block.Y <= content.Max.Y; block.Y += 64) { for (block.X = content.Min.X; block.X <= content.Max.X; block.X += 64) { var cache = new MyStorageData(); cacheSize = new Vector3I(MathHelper.Min(content.Max.X, block.X + 63) - block.X + 1, MathHelper.Min(content.Max.Y, block.Y + 63) - block.Y + 1, MathHelper.Min(content.Max.Z, block.Z + 63) - block.Z + 1); cache.Resize(cacheSize); asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1); newBlock = ((minPrimary - min) + (Vector3D)(block - content.Min)).RoundToVector3I(); var newCache = new MyStorageData(); newCache.Resize(cacheSize); newAsteroid.Storage.ReadRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, newBlock, newBlock + cacheSize - 1); Vector3I p; for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z) { for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y) { for (p.X = 0; p.X < cacheSize.X; ++p.X) { byte volume = cache.Content(ref p); byte material = cache.Material(ref p); if (volume > 0) { byte existingVolume = newCache.Content(ref p); if (volume > existingVolume) { newCache.Content(ref p, volume); } // Overwrites secondary material with primary. newCache.Material(ref p, material); } else { // try to find cover material. Vector3I[] points = CreateTestPoints(p, cacheSize - 1); for (int i = 0; i < points.Length; i++) { byte testVolume = cache.Content(ref points[i]); if (testVolume > 0) { material = cache.Material(ref points[i]); newCache.Material(ref p, material); break; } } } } } } newAsteroid.Storage.WriteRange(newCache, MyStorageDataTypeFlags.ContentAndMaterial, newBlock, newBlock + cacheSize - 1); } } } }
public static void RemoveVoxelContent(long voxelId, Vector3D position, out byte materialRemoved, out float amountOfMaterial) { materialRemoved = 0; amountOfMaterial = 0f; IMyEntity entity; if (!MyAPIGateway.Entities.TryGetEntityById(voxelId, out entity)) { return; } var voxel = entity as IMyVoxelBase; var targetMin = position; var targetMax = position; Vector3I minVoxel, maxVoxel; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMin, out minVoxel); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref targetMax, out maxVoxel); MyVoxelBase voxelBase = voxel as MyVoxelBase; minVoxel += voxelBase.StorageMin; maxVoxel += voxelBase.StorageMin + 1; voxel.Storage.ClampVoxel(ref minVoxel); voxel.Storage.ClampVoxel(ref maxVoxel); MyStorageData cache = new MyStorageData(); cache.Resize(minVoxel, maxVoxel); var flag = MyVoxelRequestFlags.AdviseCache; cache.ClearContent(0); cache.ClearMaterials(0); byte original = 0; byte material = 0; // I don't really think pinning is necessary since I'm in the main thread, but this hasn't been working for awhile, so I'll keep it here. voxel.Storage.PinAndExecute(() => { voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, minVoxel, maxVoxel, ref flag); // Grab content and material original = cache.Content(0); material = cache.Material(0); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { //Logging.Instance.WriteLine(string.Format("Content is empty")); return; } // Remove Content Logging.Instance.WriteLine($"Material: SizeLinear: {cache.SizeLinear}, Size3D: {cache.Size3D}, AboveISO: {cache.ContainsVoxelsAboveIsoLevel()}"); cache.Content(0, 0); voxel.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, minVoxel, maxVoxel); }); // Calculate Material Mined var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); materialRemoved = material; amountOfMaterial = CalculateAmount(voxelMat, original * 3.9f); // This will sync the clients. Apparently voxel writes do not sync, lovely. if (Sync.IsServer) { VoxelRemovalData data = new VoxelRemovalData(); data.VoxelID = voxelId; data.Position = position; MyAPIGateway.Multiplayer.SendMessageToOthers(8969, ASCIIEncoding.ASCII.GetBytes(MyAPIGateway.Utilities.SerializeToXML(data))); } }
private static MyStorageBase Compatibility_LoadCellStorage(int fileVersion, Stream stream) { // Size of this voxel map (in voxels) Vector3I tmpSize; tmpSize.X = stream.ReadInt32(); tmpSize.Y = stream.ReadInt32(); tmpSize.Z = stream.ReadInt32(); var storage = new MyOctreeStorage(null, tmpSize); // Size of data cell in voxels. Has to be the same as current size specified by our constants. Vector3I cellSize; cellSize.X = stream.ReadInt32(); cellSize.Y = stream.ReadInt32(); cellSize.Z = stream.ReadInt32(); #if !XB1 Trace.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS); #else // XB1 System.Diagnostics.Debug.Assert(cellSize.X == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Y == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS && cellSize.Z == MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS); #endif // XB1 Vector3I cellsCount = tmpSize / cellSize; Dictionary <byte, MyVoxelMaterialDefinition> mappingTable = null; if (fileVersion == STORAGE_TYPE_VERSION_CELL) { // loading material names->index mappings mappingTable = Compatibility_LoadMaterialIndexMapping(stream); } else if (fileVersion == 1) { // material name->index mappings were not saved in this version } var startCoord = Vector3I.Zero; var endCoord = new Vector3I(MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); var cache = new MyStorageData(); cache.Resize(Vector3I.Zero, endCoord); Vector3I cellCoord; for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++) { for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++) { for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++) { MyVoxelRangeType cellType = (MyVoxelRangeType)stream.ReadByteNoAlloc(); // Cell's are FULL by default, therefore we don't need to change them switch (cellType) { case MyVoxelRangeType.EMPTY: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_EMPTY); break; case MyVoxelRangeType.FULL: cache.ClearContent(MyVoxelConstants.VOXEL_CONTENT_FULL); break; case MyVoxelRangeType.MIXED: Vector3I v; for (v.X = 0; v.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.X++) { for (v.Y = 0; v.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Y++) { for (v.Z = 0; v.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; v.Z++) { cache.Content(ref v, stream.ReadByteNoAlloc()); } } } break; } startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); storage.WriteRange(cache, MyStorageDataTypeFlags.Content, ref startCoord, ref endCoord); } } } try { // In case materials are not saved, catch any exceptions caused by this. // Read materials and indestructible for (cellCoord.X = 0; cellCoord.X < cellsCount.X; cellCoord.X++) { for (cellCoord.Y = 0; cellCoord.Y < cellsCount.Y; cellCoord.Y++) { for (cellCoord.Z = 0; cellCoord.Z < cellsCount.Z; cellCoord.Z++) { bool isSingleMaterial = stream.ReadByteNoAlloc() == 1; MyVoxelMaterialDefinition material = null; if (isSingleMaterial) { material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable); cache.ClearMaterials(material.Index); } else { byte indestructibleContent; Vector3I voxelCoordInCell; for (voxelCoordInCell.X = 0; voxelCoordInCell.X < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.X++) { for (voxelCoordInCell.Y = 0; voxelCoordInCell.Y < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Y++) { for (voxelCoordInCell.Z = 0; voxelCoordInCell.Z < MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; voxelCoordInCell.Z++) { material = Compatibility_LoadCellVoxelMaterial(stream, mappingTable); indestructibleContent = stream.ReadByteNoAlloc(); cache.Material(ref voxelCoordInCell, material.Index); } } } } startCoord = cellCoord * MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS; endCoord = startCoord + (MyVoxelConstants.DATA_CELL_SIZE_IN_VOXELS - 1); storage.WriteRange(cache, MyStorageDataTypeFlags.Material, ref startCoord, ref endCoord); } } } } catch (EndOfStreamException ex) { MySandboxGame.Log.WriteLine(ex); } return(storage); }
private void ExecuteQuery() { try { var shape = _component._cachedRegion; var worldMin = shape.Center - shape.Radius; var worldMax = shape.Center + shape.Radius; Vector3I voxMin, voxMax; MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMin, out voxMin); MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMax, out voxMax); { var tmp = Vector3I.Max(voxMin, voxMax); voxMin = Vector3I.Min(voxMin, voxMax); voxMax = tmp; } { voxMin = voxMin >> _component.Definition.LevelOfDetail; voxMax = (voxMax >> _component.Definition.LevelOfDetail) + 1; } _storage.Resize(voxMin, voxMax); // ReSharper disable once RedundantCast ((IMyStorage)_vox.Storage).ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, _component.Definition.LevelOfDetail, in voxMin, in voxMax); for (var i = 0; i < _countsWorking.Length; i++) { _countsWorking[i] = 0; } for (var itr = new Vector3I_RangeIterator(ref voxMin, ref voxMax); itr.IsValid(); itr.MoveNext()) { var local = itr.Current; var localRoot = local << _component.Definition.LevelOfDetail; Vector3D box; MyVoxelCoordSystems.VoxelCoordToWorldPosition(_vox.PositionLeftBottomCorner, ref localRoot, out box); if (!shape.Intersects(new BoundingBoxD(box, box + (1 << _component.Definition.LevelOfDetail)))) { continue; } var stor = local - voxMin; var idx = _storage.ComputeLinear(ref stor); var content = _storage.Content(idx); if (content == 0) { continue; } if (_component.Definition.Mode == VoxelPowerCountMode.Surface) { if (content == byte.MaxValue) { continue; } content = 1; } _countsWorking[_storage.Material(idx)] += content; } { var tmp = _countsWorking; _countsWorking = Counts; Counts = tmp; } } finally { _currentlyExecuting = false; _component.QueryFinishedAsync(); } }
/// <summary> /// /// </summary> /// <param name="voxelMap"></param> /// <param name="center"></param> /// <param name="resolution">0 to 8. 0 for fine/slow detail.</param> /// <param name="distance"></param> /// <param name="scanHits"></param> /// <returns></returns> private void FindMaterial(IMyVoxelBase voxelMap, Vector3D center, int resolution, double distance, List <ScanHit> scanHits) { const double checkDistance = 50 * 50; // 50 meter seperation. var materials = MyDefinitionManager.Static.GetVoxelMaterialDefinitions().Where(v => v.IsRare).ToArray(); var findMaterial = materials.Select(f => f.Index).ToArray(); var storage = voxelMap.Storage; var scale = (int)Math.Pow(2, resolution); //MyAPIGateway.Utilities.ShowMessage("center", center.ToString()); var point = new Vector3I(center - voxelMap.PositionLeftBottomCorner); //MyAPIGateway.Utilities.ShowMessage("point", point.ToString()); var min = ((point - (int)distance) / 64) * 64; min = Vector3I.Max(min, Vector3I.Zero); //MyAPIGateway.Utilities.ShowMessage("min", min.ToString()); var max = ((point + (int)distance) / 64) * 64; max = Vector3I.Max(max, min + 64); //MyAPIGateway.Utilities.ShowMessage("max", max.ToString()); //MyAPIGateway.Utilities.ShowMessage("size", voxelMap.StorageName + " " + storage.Size.ToString()); if (min.X >= storage.Size.X || min.Y >= storage.Size.Y || min.Z >= storage.Size.Z) { //MyAPIGateway.Utilities.ShowMessage("size", "out of range"); return; } var oldCache = new MyStorageData(); //var smin = new Vector3I(0, 0, 0); //var smax = new Vector3I(31, 31, 31); ////var size = storage.Size; //var size = smax - smin + 1; //size = new Vector3I(16, 16, 16); //oldCache.Resize(size); //storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, resolution, Vector3I.Zero, size - 1); var smax = (max / scale) - 1; var smin = (min / scale); var size = smax - smin + 1; oldCache.Resize(size); storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, resolution, smin, smax); //MyAPIGateway.Utilities.ShowMessage("smax", smax.ToString()); //MyAPIGateway.Utilities.ShowMessage("size", size .ToString()); //MyAPIGateway.Utilities.ShowMessage("size - 1", (size - 1).ToString()); Vector3I p; for (p.Z = 0; p.Z < size.Z; ++p.Z) { for (p.Y = 0; p.Y < size.Y; ++p.Y) { for (p.X = 0; p.X < size.X; ++p.X) { // place GPS in the center of the Voxel Vector3D position = voxelMap.PositionLeftBottomCorner + (p * scale) + (scale / 2f) + min; if (Math.Sqrt((position - center).LengthSquared()) < distance) { byte content = oldCache.Content(ref p); byte material = oldCache.Material(ref p); if (content > 0 && findMaterial.Any(m => m == material)) { bool addHit = true; foreach (ScanHit scanHit in scanHits) { if (scanHit.Material == material && Vector3D.DistanceSquared(position, scanHit.Position) < checkDistance) { addHit = false; break; } } if (addHit) { scanHits.Add(new ScanHit(position, material)); } } } } } } }
private void ProcessAsteroid(string displayType, string displayName, IMyVoxelMap voxelMap, double distance, BoundingBoxD aabb) { Vector3I min = Vector3I.MaxValue; Vector3I max = Vector3I.MinValue; Vector3I block; Dictionary<byte, long> assetCount = new Dictionary<byte, long>(); // read the asteroid in chunks of 64 to avoid the Arithmetic overflow issue. for (block.Z = 0; block.Z < voxelMap.Storage.Size.Z; block.Z += 64) for (block.Y = 0; block.Y < voxelMap.Storage.Size.Y; block.Y += 64) for (block.X = 0; block.X < voxelMap.Storage.Size.X; block.X += 64) { var cacheSize = new Vector3I(64); var oldCache = new MyStorageData(); oldCache.Resize(cacheSize); // LOD1 is not detailed enough for content information on asteroids. voxelMap.Storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, 0, block, block + cacheSize - 1); Vector3I p; for (p.Z = 0; p.Z < cacheSize.Z; ++p.Z) for (p.Y = 0; p.Y < cacheSize.Y; ++p.Y) for (p.X = 0; p.X < cacheSize.X; ++p.X) { var content = oldCache.Content(ref p); if (content > 0) { min = Vector3I.Min(min, p + block); max = Vector3I.Max(max, p + block + 1); var material = oldCache.Material(ref p); if (assetCount.ContainsKey(material)) assetCount[material] += content; else assetCount.Add(material, content); } } } var assetNameCount = new Dictionary<string, long>(); foreach (var kvp in assetCount) { var name = MyDefinitionManager.Static.GetVoxelMaterialDefinition(kvp.Key).Id.SubtypeName; if (assetNameCount.ContainsKey(name)) assetNameCount[name] += kvp.Value; else assetNameCount.Add(name, kvp.Value); } assetNameCount = assetNameCount.OrderByDescending(e => e.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); var sum = assetNameCount.Values.Sum(); var ores = new StringBuilder(); foreach (var kvp in assetNameCount) ores.AppendFormat("{0} {1:N} {2:P}\r\n", kvp.Key, (double)kvp.Value / 255, (double)kvp.Value / (double)sum); var contentBox = new BoundingBoxD(voxelMap.PositionLeftBottomCorner + min, voxelMap.PositionLeftBottomCorner + max); var description = string.Format("Distance: {0:N}\r\nSize: {1}\r\nBoundingBox Center: [X:{2:N} Y:{3:N} Z:{4:N}]\r\n\r\nContent Size:{5}\r\nLOD0 Content Center: [X:{6:N} Y:{7:N} Z:{8:N}]\r\n\r\nMaterial Mass Percent\r\n{9}", distance, voxelMap.Storage.Size, aabb.Center.X, aabb.Center.Y, aabb.Center.Z, max - min, contentBox.Center.X, contentBox.Center.Y, contentBox.Center.Z, ores); MyAPIGateway.Utilities.ShowMissionScreen(string.Format("ID {0}:", displayType), string.Format("'{0}'", displayName), " ", description, null, "OK"); }
public static void MakeCrater(MyVoxelBase voxelMap, BoundingSphereD sphere, Vector3 normal, MyVoxelMaterialDefinition material) { ProfilerShort.Begin("MakeCrater"); Vector3I minCorner, maxCorner; { Vector3D sphereMin = sphere.Center - (sphere.Radius - MyVoxelConstants.VOXEL_SIZE_IN_METRES); Vector3D sphereMax = sphere.Center + (sphere.Radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMin, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref sphereMax, out maxCorner); } voxelMap.Storage.ClampVoxelCoord(ref minCorner); voxelMap.Storage.ClampVoxelCoord(ref maxCorner); // We are tracking which voxels were changed, so we can invalidate only needed cells in the cache bool changed = false; ProfilerShort.Begin("Reading cache"); m_cache.Resize(minCorner, maxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref minCorner, ref maxCorner); ProfilerShort.End(); ProfilerShort.Begin("Changing cache"); int removedVoxelContent = 0; Vector3I tempVoxelCoord; Vector3I cachePos; for (tempVoxelCoord.Z = minCorner.Z, cachePos.Z = 0; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++, ++cachePos.Z) { for (tempVoxelCoord.Y = minCorner.Y, cachePos.Y = 0; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++, ++cachePos.Y) { for (tempVoxelCoord.X = minCorner.X, cachePos.X = 0; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++, ++cachePos.X) { Vector3D voxelPosition; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref tempVoxelCoord, out voxelPosition); float addDist = (float)(voxelPosition - sphere.Center).Length(); float addDiff = (float)(addDist - sphere.Radius); byte newContent; if (addDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (addDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - addDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } byte originalContent = m_cache.Content(ref cachePos); if (newContent > originalContent && originalContent > 0) { if (material != null) { m_cache.Material(ref cachePos, material.Index); } changed = true; m_cache.Content(ref cachePos, newContent); } float delDist = (float)(voxelPosition - (sphere.Center + (float)sphere.Radius * 0.7f * normal)).Length(); float delDiff = (float)(delDist - sphere.Radius); byte contentToRemove; if (delDiff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (delDiff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentToRemove = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentToRemove = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - delDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY && contentToRemove > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { changed = true; int newVal = originalContent - contentToRemove; if (newVal < MyVoxelConstants.VOXEL_CONTENT_EMPTY) { newVal = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } m_cache.Content(ref cachePos, (byte)newVal); removedVoxelContent += originalContent - newVal; } float setDist = (float)(voxelPosition - (sphere.Center - (float)sphere.Radius * 0.5f * normal)).Length(); float setDiff = (float)(setDist - sphere.Radius / 4f); if (setDiff <= MyVoxelConstants.VOXEL_SIZE_IN_METRES * 1.5f) // could be VOXEL_SIZE_IN_METRES_HALF, but we want to set material in empty cells correctly { byte indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_FULL; if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) // outside { indestructibleContentToSet = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (setDiff >= -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) // boundary { indestructibleContentToSet = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - setDiff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } MyVoxelMaterialDefinition originalMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref cachePos)); // Change the material: // - always on boundaries between material and nothing // - smoothly on inner boundaries MyVoxelMaterialDefinition newMaterial = material; if (setDiff > 0) { byte content = m_cache.Content(ref cachePos); if (content == MyVoxelConstants.VOXEL_CONTENT_FULL) { newMaterial = originalMaterial; } if (setDiff >= MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF && content != MyVoxelConstants.VOXEL_CONTENT_EMPTY) // set material behind boundary only for empty voxels { newMaterial = originalMaterial; } } if (originalMaterial == newMaterial) { continue; } m_cache.Material(ref cachePos, newMaterial.Index); changed = true; } float dist = (float)(voxelPosition - sphere.Center).Length(); float diff = (float)(dist - sphere.Radius); if (diff <= 0f) { originalContent = m_cache.Content(ref cachePos); if (originalContent > MyVoxelConstants.VOXEL_CONTENT_EMPTY) { bool wrinkled = m_cache.WrinkleVoxelContent(ref cachePos, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_ADD, MyVoxelConstants.DEFAULT_WRINKLE_WEIGHT_REMOVE); if (wrinkled) { changed = true; } } } } } } ProfilerShort.End(); if (changed) { ProfilerShort.Begin("RemoveSmallVoxelsUsingChachedVoxels"); RemoveSmallVoxelsUsingChachedVoxels(); ProfilerShort.BeginNextBlock("Writing cache"); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref minCorner, ref maxCorner); ProfilerShort.End(); } ProfilerShort.End(); }
/// <summary> /// /// </summary> /// <param name="voxelMap"></param> /// <param name="resolution">0 to 8. 0 for fine/slow detail.</param> /// <param name="distance"></param> /// <returns></returns> private int FindMaterial(IMyVoxelBase voxelMap, Vector3D center, int resolution, double distance) { Util.GetInstance().Log("Finding Mineral", "findingOres.txt"); int hits = 0; var materials = MyDefinitionManager.Static.GetVoxelMaterialDefinitions().Where(v => v.IsRare).ToArray(); var findMaterial = materials.Select(f => f.Index).ToArray(); var storage = voxelMap.Storage; var scale = (int)Math.Pow(2, resolution); //MyAPIGateway.Utilities.ShowMessage("center", center.ToString()); var point = new Vector3I(center - voxelMap.PositionLeftBottomCorner); //MyAPIGateway.Utilities.ShowMessage("point", point.ToString()); var min = ((point - (int)distance) / 64) * 64; min = Vector3I.Max(min, Vector3I.Zero); //MyAPIGateway.Utilities.ShowMessage("min", min.ToString()); var max = ((point + (int)distance) / 64) * 64; max = Vector3I.Max(max, min + 64); //MyAPIGateway.Utilities.ShowMessage("max", max.ToString()); //MyAPIGateway.Utilities.ShowMessage("size", voxelMap.StorageName + " " + storage.Size.ToString()); if (min.X >= storage.Size.X || min.Y >= storage.Size.Y || min.Z >= storage.Size.Z) { //MyAPIGateway.Utilities.ShowMessage("size", "out of range"); return(0); } var oldCache = new MyStorageData(); //var smin = new Vector3I(0, 0, 0); //var smax = new Vector3I(31, 31, 31); ////var size = storage.Size; //var size = smax - smin + 1; //size = new Vector3I(16, 16, 16); //oldCache.Resize(size); //storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, resolution, Vector3I.Zero, size - 1); var smax = (max / scale) - 1; var smin = (min / scale); var size = smax - smin + 1; oldCache.Resize(size); storage.ReadRange(oldCache, MyStorageDataTypeFlags.ContentAndMaterial, resolution, smin, smax); //MyAPIGateway.Utilities.ShowMessage("smax", smax.ToString()); //MyAPIGateway.Utilities.ShowMessage("size", size .ToString()); //MyAPIGateway.Utilities.ShowMessage("size - 1", (size - 1).ToString()); Vector3I p; for (p.Z = 0; p.Z < size.Z; ++p.Z) { for (p.Y = 0; p.Y < size.Y; ++p.Y) { for (p.X = 0; p.X < size.X; ++p.X) { // place GPS in the center of the Voxel var position = voxelMap.PositionLeftBottomCorner + (p * scale) + (scale / 2) + min; if (Math.Sqrt((position - center).LengthSquared()) < distance) { var content = oldCache.Content(ref p); var material = oldCache.Material(ref p); if (content > 0 && findMaterial.Contains(material)) { var index = Array.IndexOf(findMaterial, material); var name = materials[index].MinedOre; Util.GetInstance().Log(hits + " Ore " + name + " scanore " + position, "findingOres.txt"); //var gps = MyAPIGateway.Session.GPS.Create("Ore " + name, "scanore", position, true, false); //MyAPIGateway.Session.GPS.AddLocalGps(gps); hits++; } } } } } return(hits); }