/// <summary> /// called multiple times for ships, to be kept up to date. /// </summary> public override void UpdateAfterSimulation10() { if (CommandAsteroidEditClear.ActiveVoxelDeleter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; var position = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; var currentAsteroidList = new List<IMyVoxelBase>(); var bb = new BoundingBoxD(position - 0.2f, position + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _isInRange = true; var storage = currentAsteroidList[0].Storage; var point = new Vector3I(position - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var min = (point / 64) * 64; var max = min + 63; var size = max - min; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, min, max); Vector3I p = point - min; var content = cache.Content(ref p); if (content > 0) { content = 0x00; cache.Content(ref p, content); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, min, max); } //storage = null; } else { _isInRange = false; } } if (CommandAsteroidEditSet.ActiveVoxelSetter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; CommandAsteroidEditSet.ActiveVoxelSetterPosition = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; } else { CommandAsteroidEditSet.ActiveVoxelSetterPosition = null; } }
/// <summary> /// called multiple times for ships, to be kept up to date. /// </summary> public override void UpdateAfterSimulation10() { if (CommandAsteroidEditClear.ActiveVoxelDeleter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; var position = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; var currentAsteroidList = new List <IMyVoxelBase>(); var bb = new BoundingBoxD(position - 0.2f, position + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _isInRange = true; var storage = currentAsteroidList[0].Storage; var point = new Vector3I(position - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var min = (point / 64) * 64; var max = min + 63; var size = max - min; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, min, max); Vector3I p = point - min; var content = cache.Content(ref p); if (content > 0) { content = 0x00; cache.Content(ref p, content); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, min, max); } //storage = null; } else { _isInRange = false; } } if (CommandAsteroidEditSet.ActiveVoxelSetter) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; CommandAsteroidEditSet.ActiveVoxelSetterPosition = worldMatrix.Translation + worldMatrix.Forward * 1.6f + worldMatrix.Up * 1.35f + worldMatrix.Right * 0.1f; } else { CommandAsteroidEditSet.ActiveVoxelSetterPosition = null; } }
public void GetFilledStorageBounds(out Vector3I min, out Vector3I max) { min = Vector3I.MaxValue; max = Vector3I.MinValue; Vector3I sz = Size; Vector3I SMax = Size - 1; MyStorageData data = new MyStorageData(); data.Resize(Size); Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, Vector3I.Zero, SMax); for (int z = 0; z < sz.Z; ++z) { for (int y = 0; y < sz.Y; ++y) { for (int x = 0; x < sz.X; ++x) { if (data.Content(x, y, z) > MyVoxelConstants.VOXEL_ISO_LEVEL) { Vector3I l = Vector3I.Max(new Vector3I(x - 1, y - 1, z - 1), Vector3I.Zero); min = Vector3I.Min(l, min); Vector3I h = Vector3I.Min(new Vector3I(x + 1, y + 1, z + 1), SMax); max = Vector3I.Max(h, max); } } } } }
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 float GetVoxelContentInBoundingBox_Obsolete(BoundingBoxD worldAabb, out float cellCount) { MyPrecalcComponent.AssertUpdateThread(); cellCount = 0; float result = 0; Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref worldAabb.Max, out maxCorner); minCorner += StorageMin; maxCorner += StorageMin; Storage.ClampVoxelCoord(ref minCorner); Storage.ClampVoxelCoord(ref maxCorner); m_tempStorage.Resize(minCorner, maxCorner); Storage.ReadRange(m_tempStorage, MyStorageDataTypeFlags.Content, 0, ref minCorner, ref maxCorner); BoundingBoxD voxelBox; Vector3I coord, cache; for (coord.Z = minCorner.Z, cache.Z = 0; coord.Z <= maxCorner.Z; coord.Z++, cache.Z++) { for (coord.Y = minCorner.Y, cache.Y = 0; coord.Y <= maxCorner.Y; coord.Y++, cache.Y++) { for (coord.X = minCorner.X, cache.X = 0; coord.X <= maxCorner.X; coord.X++, cache.X++) { MyVoxelCoordSystems.VoxelCoordToWorldAABB(PositionLeftBottomCorner - StorageMin * MyVoxelConstants.VOXEL_SIZE_IN_METRES, ref coord, out voxelBox); if (worldAabb.Intersects(voxelBox)) { float content = m_tempStorage.Content(ref cache) / MyVoxelConstants.VOXEL_CONTENT_FULL_FLOAT; float containPercent = (float)(worldAabb.Intersect(voxelBox).Volume / MyVoxelConstants.VOXEL_VOLUME_IN_METERS); result += content * containPercent; cellCount += containPercent; } } } } return(result); }
private static bool HasContentAt(this MyVoxelBase voxel, ref Vector3D localPosition) { Vector3I voxelCoord; MyVoxelCoordSystems.LocalPositionToVoxelCoord(ref localPosition, out voxelCoord); MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, ref voxelCoord, ref voxelCoord); return(cache.Content(0) > MyVoxelConstants.VOXEL_ISO_LEVEL); }
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); }
internal static int PointsInsideVoxel(MyVoxelBase voxel, MyStorageData tmpStorage, List <Vector3D> points) { var voxelMatrix = voxel.PositionComp.WorldMatrixInvScaled; var vecMax = new Vector3I(int.MaxValue); var vecMin = new Vector3I(int.MinValue); var results = 0; for (int index = 0; index < points.Count; ++index) { var point = points[index]; Vector3D result; Vector3D.Transform(ref point, ref voxelMatrix, out result); var r = result + (Vector3D)(voxel.Size / 2); var v1 = Vector3D.Floor(r); Vector3D.Fract(ref r, out r); var v2 = v1 + voxel.StorageMin; var v3 = v2 + 1; if (v2 != vecMax && v3 != vecMin) { tmpStorage.Resize(v2, v3); voxel.Storage.ReadRange(tmpStorage, MyStorageDataTypeFlags.Content, 0, v2, v3); vecMax = v2; vecMin = v3; } var num1 = tmpStorage.Content(0, 0, 0); var num2 = tmpStorage.Content(1, 0, 0); var num3 = tmpStorage.Content(0, 1, 0); var num4 = tmpStorage.Content(1, 1, 0); var num5 = tmpStorage.Content(0, 0, 1); var num6 = tmpStorage.Content(1, 0, 1); var num7 = tmpStorage.Content(0, 1, 1); var num8 = tmpStorage.Content(1, 1, 1); var num9 = num1 + (num2 - num1) * r.X; var num10 = num3 + (num4 - num3) * r.X; var num11 = num5 + (num6 - num5) * r.X; var num12 = num7 + (num8 - num7) * r.X; var num13 = num9 + (num10 - num9) * r.Y; var num14 = num11 + (num12 - num11) * r.Y; if (num13 + (num14 - num13) * r.Z >= sbyte.MaxValue) { ++results; } } return(results); }
internal static bool CheckPointsOnLine(MyVoxelBase voxel, LineD testLine, MyStorageData tmpStorage, int distBetweenPoints) { var voxelMatrix = voxel.PositionComp.WorldMatrixInvScaled; var vecMax = new Vector3I(int.MaxValue); var vecMin = new Vector3I(int.MinValue); var checkPoints = (int)(testLine.Length / distBetweenPoints); for (int i = 0; i < checkPoints; i++) { var point = testLine.From + (testLine.Direction * (distBetweenPoints * i)); Vector3D result; Vector3D.Transform(ref point, ref voxelMatrix, out result); var r = result + (Vector3D)(voxel.Size / 2); var v1 = Vector3D.Floor(r); Vector3D.Fract(ref r, out r); var v2 = v1 + voxel.StorageMin; var v3 = v2 + 1; if (v2 != vecMax && v3 != vecMin) { tmpStorage.Resize(v2, v3); voxel.Storage.ReadRange(tmpStorage, MyStorageDataTypeFlags.Content, 0, v2, v3); vecMax = v2; vecMin = v3; } var num1 = tmpStorage.Content(0, 0, 0); var num2 = tmpStorage.Content(1, 0, 0); var num3 = tmpStorage.Content(0, 1, 0); var num4 = tmpStorage.Content(1, 1, 0); var num5 = tmpStorage.Content(0, 0, 1); var num6 = tmpStorage.Content(1, 0, 1); var num7 = tmpStorage.Content(0, 1, 1); var num8 = tmpStorage.Content(1, 1, 1); var num9 = num1 + (num2 - num1) * r.X; var num10 = num3 + (num4 - num3) * r.X; var num11 = num5 + (num6 - num5) * r.X; var num12 = num7 + (num8 - num7) * r.X; var num13 = num9 + (num10 - num9) * r.Y; var num14 = num11 + (num12 - num11) * r.Y; if (num13 + (num14 - num13) * r.Z >= sbyte.MaxValue) { return(true); } } return(false); }
private void DrawContentsInfo(MyStorageData data) { byte min, max; uint sum = 0; uint nonZero = 0; uint nonFull = 0; min = byte.MaxValue; max = 0; int cellCount = data.SizeLinear / data.StepLinear; for (int i = 0; i < data.SizeLinear; i += data.StepLinear) { byte content = data.Content(i); if (min > content) { min = content; } if (max < content) { max = content; } sum += content; if (content != 0) { nonZero++; } if (content != 255) { nonFull++; } } Section("Probing Contents ({0} {1})", cellCount, cellCount > 1 ? "voxels" : "voxel"); Text("Min: {0}", min); Text("Average: {0}", sum / cellCount); Text("Max: {0}", max); VSpace(5); Text("Non-Empty: {0}", nonZero); Text("Non-Full: {0}", nonFull); }
public static bool CheckVoxelContent(long voxelId, Vector3D position) { IMyEntity entity; if (!MyAPIGateway.Entities.TryGetEntityById(voxelId, out entity)) { return(false); } 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; voxel.Storage.ClampVoxel(ref minVoxel); voxel.Storage.ClampVoxel(ref maxVoxel); MyStorageData cache = new MyStorageData(); cache.Resize(minVoxel, maxVoxel); voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, minVoxel, maxVoxel); // Grab content and material var original = cache.Content(0); //var material = cache.Material(0); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { //Logging.Instance.WriteLine(string.Format("Content is empty")); return(false); } return(true); }
public static void RemoveVoxelContent(long voxelId, Vector3D position, out byte materialRemoved, out float amountOfMaterial) { materialRemoved = 0; amountOfMaterial = 0f; MyStorageData cache = new MyStorageData(); IMyEntity entity; if (!MyAPIGateway.Entities.TryGetEntityById(voxelId, out entity)) { return; } IMyVoxelBase voxel = entity as IMyVoxelBase; byte original, material; 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); OreDetector.Instance.GetVoxelContent(voxel, position, out original, out material, cache); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) { Logger.Instance.LogMessage("Voxel Content empty"); //Logging.Instance.WriteLine(string.Format("Content is empty")); return; } // Calculate Material Mined var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); materialRemoved = material; amountOfMaterial = OreDetector.CalculateAmount(voxelMat, original * 3.9f); // Remove Content cache.Content(0, 0); voxel.Storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, minVoxel, maxVoxel); }
private bool excludeVoxelBase(Vector3D center, ref HashSet <IMyVoxelBase> asteroids) { MyStorageData cache = new MyStorageData(); cache.Resize(Vector3I.One); Vector3I voxelCoord; foreach (IMyVoxelBase asteroid in asteroids) { if (asteroid.WorldAABB.Contains(center) != ContainmentType.Contains) { continue; } MyVoxelCoordSystems.WorldPositionToVoxelCoord(asteroid.PositionLeftBottomCorner, ref center, out voxelCoord); asteroid.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, voxelCoord, voxelCoord); if (cache.Content(ref Vector3I.Zero) != (byte)0) { return(true); } } return(false); }
/// <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; }
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); }
internal void ReadContentRange(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; ProfilerShort.Begin("Testing removed shapes"); var overlappedRemovedShapes = OverlappedRemovedShapes; overlappedRemovedShapes.Clear(); ContainmentType testRemove = ContainmentType.Disjoint; for (int i = 0; i < m_data.RemovedShapes.Length; ++i) { var test = m_data.RemovedShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test == ContainmentType.Contains) { testRemove = ContainmentType.Contains; break; // completely empty so we can leave } else if (test == ContainmentType.Intersects) { testRemove = ContainmentType.Intersects; overlappedRemovedShapes.Add(m_data.RemovedShapes[i]); } } ProfilerShort.End(); if (testRemove == ContainmentType.Contains) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY); ProfilerShort.End(); return; } ProfilerShort.Begin("Testing filled shapes"); var overlappedFilledShapes = OverlappedFilledShapes; overlappedFilledShapes.Clear(); ContainmentType testFill = ContainmentType.Disjoint; for (int i = 0; i < m_data.FilledShapes.Length; ++i) { var test = m_data.FilledShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test == ContainmentType.Contains) { overlappedFilledShapes.Clear(); testFill = ContainmentType.Contains; break; } else if (test == ContainmentType.Intersects) { overlappedFilledShapes.Add(m_data.FilledShapes[i]); testFill = ContainmentType.Intersects; } } ProfilerShort.End(); if (testFill == ContainmentType.Disjoint) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY); ProfilerShort.End(); return; } else if (testRemove == ContainmentType.Disjoint && testFill == ContainmentType.Contains) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_FULL); ProfilerShort.End(); return; } ProfilerShort.Begin("Distance field computation"); Vector3I v = minInLod; Vector3 localPos = v * lodVoxelSize; Vector3 localPosStart = v * lodVoxelSize; var writeOffsetLoc = writeOffset - minInLod; for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z) { for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y) { v.X = minInLod.X; var write2 = v + writeOffsetLoc; var write = target.ComputeLinear(ref write2); for (; v.X <= maxInLod.X; ++v.X) { //Vector3 localPos = v * lodVoxelSize; //ProfilerShort.Begin("Dist filled"); float distFill; if (testFill == ContainmentType.Contains) { distFill = -1f; } else { //ProfilerShort.Begin("shape distances"); distFill = 1f; foreach (var shape in overlappedFilledShapes) { distFill = Math.Min(distFill, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule)); if (distFill <= -1) break; } //ProfilerShort.End(); } //ProfilerShort.BeginNextBlock("Dist removed"); float distRemoved = 1f; if (testRemove != ContainmentType.Disjoint) { foreach (var shape in overlappedRemovedShapes) { distRemoved = Math.Min(distRemoved, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule)); if (distRemoved <= -1) break; } } //ProfilerShort.BeginNextBlock("content"); float signedDist = MathHelper.Max(distFill, -distRemoved); var fillRatio = MathHelper.Clamp(-signedDist, -1f, 1f) * 0.5f + 0.5f; byte content = (byte)(fillRatio * MyVoxelConstants.VOXEL_CONTENT_FULL); target.Content(write, content); Debug.Assert(Math.Abs((((float)content) / MyVoxelConstants.VOXEL_CONTENT_FULL) - fillRatio) <= 0.5f); //ProfilerShort.End(); write += target.StepLinear; localPos.X += lodVoxelSize; } localPos.Y += lodVoxelSize; localPos.X = localPosStart.X; } localPos.Z += lodVoxelSize; localPos.Y = localPosStart.Y; } ProfilerShort.End(); }
// 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 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 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 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; }
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); }
// IMPORTANT: This method is called only from GetVoxelNormal(). Reason is that border voxels aren't copied during CopyVoxelContents, so we can check it now. byte GetVoxelContent(int x, int y, int z) { return(m_cache.Content(x, y, z)); }
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); } } } }
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++; } } }
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))); } }
public void GetFilledStorageBounds(out Vector3I min, out Vector3I max) { min = Vector3I.MaxValue; max = Vector3I.MinValue; Vector3I sz = Size; Vector3I SMax = Size - 1; MyStorageData data = new MyStorageData(); data.Resize(Size); Storage.ReadRange(data, MyStorageDataTypeFlags.Content, 0, Vector3I.Zero, SMax); for (int z = 0; z < sz.Z; ++z) for (int y = 0; y < sz.Y; ++y) for (int x = 0; x < sz.X; ++x) { if (data.Content(x, y, z) > MyVoxelConstants.VOXEL_ISO_LEVEL) { Vector3I l = Vector3I.Max(new Vector3I(x - 1, y - 1, z - 1), Vector3I.Zero); min = Vector3I.Min(l, min); Vector3I h = Vector3I.Min(new Vector3I(x + 1, y + 1, z + 1), SMax); max = Vector3I.Max(h, max); } } }
public override bool Invoke(ulong steamId, long playerId, string messageText) { // voxelset [0/off] [1/on] [A] [B] [C/Clear] if (messageText.StartsWith("/voxelset ", StringComparison.InvariantCultureIgnoreCase)) { var strings = messageText.Split(' '); if (strings.Length > 1) { if (strings[1].Equals("off", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("0", StringComparison.InvariantCultureIgnoreCase)) { ActiveVoxelSetterPosition = null; _activeVoxelSetterPositionA = null; _activeVoxelSetterPositionB = null; _activeVoxelSetterNameA = null; _activeVoxelSetterNameB = null; ActiveVoxelSetter = false; MyAPIGateway.Utilities.ShowNotification("Voxel setter off", 1000, MyFontEnum.Green); return true; } if (strings[1].Equals("on", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("1", StringComparison.InvariantCultureIgnoreCase)) { ActiveVoxelSetterPosition = null; _activeVoxelSetterPositionA = null; _activeVoxelSetterPositionB = null; _activeVoxelSetterNameA = null; _activeVoxelSetterNameB = null; ActiveVoxelSetter = true; MyAPIGateway.Utilities.ShowNotification("Voxel setter activated", 1000, MyFontEnum.Green); return true; } if (!ActiveVoxelSetter) { MyAPIGateway.Utilities.ShowNotification("Voxel setter hasn't been actived.", 2000, MyFontEnum.Red); return true; } if (strings[1].Equals("A", StringComparison.InvariantCultureIgnoreCase)) { var tmp = ActiveVoxelSetterPosition; if (tmp.HasValue) { var currentAsteroidList = new List<IMyVoxelBase>(); var bb = new BoundingBoxD(tmp.Value - 0.2f, tmp.Value + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _activeVoxelSetterNameA = currentAsteroidList[0].StorageName; _activeVoxelSetterPositionA = tmp; } } if (_activeVoxelSetterPositionA.HasValue) MyAPIGateway.Utilities.ShowMessage(_activeVoxelSetterNameA, "Voxel setter point A: active"); //MyAPIGateway.Utilities.ShowNotification("Voxel setter A: active.", 1000, MyFontEnum.Green); else MyAPIGateway.Utilities.ShowNotification("Voxel setter A: invalid.", 1000, MyFontEnum.Red); return true; } if (strings[1].Equals("B", StringComparison.InvariantCultureIgnoreCase)) { var tmp = ActiveVoxelSetterPosition; if (tmp.HasValue) { var currentAsteroidList = new List<IMyVoxelBase>(); var bb = new BoundingBoxD(tmp.Value - 0.2f, tmp.Value + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _activeVoxelSetterNameB = currentAsteroidList[0].StorageName; _activeVoxelSetterPositionB = tmp; } } if (_activeVoxelSetterPositionB.HasValue) MyAPIGateway.Utilities.ShowMessage(_activeVoxelSetterNameB, "Voxel setter point B: active"); //MyAPIGateway.Utilities.ShowNotification("Voxel setter B: active.", 1000, MyFontEnum.Green); else MyAPIGateway.Utilities.ShowNotification("Voxel setter B: invalid.", 1000, MyFontEnum.Red); return true; } if (strings[1].Equals("C", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("Clear", StringComparison.InvariantCultureIgnoreCase)) { if (_activeVoxelSetterPositionA.HasValue && _activeVoxelSetterPositionB.HasValue && _activeVoxelSetterNameA == _activeVoxelSetterNameB) { var currentAsteroidList = new List<IMyVoxelBase>(); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(_activeVoxelSetterNameA, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count > 0) { var storage = currentAsteroidList[0].Storage; var point1 = new Vector3I(_activeVoxelSetterPositionA.Value - currentAsteroidList[0].PositionLeftBottomCorner); var point2 = new Vector3I(_activeVoxelSetterPositionB.Value - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var size = storage.Size; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, Vector3I.Zero, size - 1); var min = Vector3I.Min(point1, point2); var max = Vector3I.Max(point1, point2); MyAPIGateway.Utilities.ShowMessage("Cutting", min.ToString() + " " + max.ToString()); //MyAPIGateway.Utilities.ShowNotification("cutting:" + min.ToString() + " " + max.ToString(), 5000, MyFontEnum.Blue); Vector3I p; for (p.Z = min.Z; p.Z <= max.Z; ++p.Z) for (p.Y = min.Y; p.Y <= max.Y; ++p.Y) for (p.X = min.X; p.X <= max.X; ++p.X) cache.Content(ref p, 0); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, size - 1); } } else if (_activeVoxelSetterNameA != _activeVoxelSetterNameB) { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: different asteroids.", 2000, MyFontEnum.Red); } else { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: invalid points.", 2000, MyFontEnum.Red); } return true; } if (strings[1].Equals("F", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("Fill", StringComparison.InvariantCultureIgnoreCase)) { if (_activeVoxelSetterPositionA.HasValue && _activeVoxelSetterPositionB.HasValue && _activeVoxelSetterNameA == _activeVoxelSetterNameB) { var currentAsteroidList = new List<IMyVoxelBase>(); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(_activeVoxelSetterNameA, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count > 0) { var storage = currentAsteroidList[0].Storage; var point1 = new Vector3I(_activeVoxelSetterPositionA.Value - currentAsteroidList[0].PositionLeftBottomCorner); var point2 = new Vector3I(_activeVoxelSetterPositionB.Value - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var size = storage.Size; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, Vector3I.Zero, size - 1); var min = Vector3I.Min(point1, point2); var max = Vector3I.Max(point1, point2); MyAPIGateway.Utilities.ShowMessage("Filling", min.ToString() + " " + max.ToString()); //MyAPIGateway.Utilities.ShowNotification("filling:" + min.ToString() + " " + max.ToString(), 5000, MyFontEnum.Blue); Vector3I p; for (p.Z = min.Z; p.Z <= max.Z; ++p.Z) for (p.Y = min.Y; p.Y <= max.Y; ++p.Y) for (p.X = min.X; p.X <= max.X; ++p.X) cache.Content(ref p, 0xff); storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, size - 1); } } else if (_activeVoxelSetterNameA != _activeVoxelSetterNameB) { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: different asteroids.", 2000, MyFontEnum.Red); } else { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: invalid points.", 2000, MyFontEnum.Red); } return true; } } } return false; }
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)); } } } } } } }
public override bool Invoke(ulong steamId, long playerId, string messageText) { // voxelset [0/off] [1/on] [A] [B] [C/Clear] if (messageText.StartsWith("/voxelset ", StringComparison.InvariantCultureIgnoreCase)) { var strings = messageText.Split(' '); if (strings.Length > 1) { if (strings[1].Equals("off", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("0", StringComparison.InvariantCultureIgnoreCase)) { ActiveVoxelSetterPosition = null; _activeVoxelSetterPositionA = null; _activeVoxelSetterPositionB = null; _activeVoxelSetterNameA = null; _activeVoxelSetterNameB = null; ActiveVoxelSetter = false; MyAPIGateway.Utilities.ShowNotification("Voxel setter off", 1000, MyFontEnum.Green); return(true); } if (strings[1].Equals("on", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("1", StringComparison.InvariantCultureIgnoreCase)) { ActiveVoxelSetterPosition = null; _activeVoxelSetterPositionA = null; _activeVoxelSetterPositionB = null; _activeVoxelSetterNameA = null; _activeVoxelSetterNameB = null; ActiveVoxelSetter = true; MyAPIGateway.Utilities.ShowNotification("Voxel setter activated", 1000, MyFontEnum.Green); return(true); } if (!ActiveVoxelSetter) { MyAPIGateway.Utilities.ShowNotification("Voxel setter hasn't been actived.", 2000, MyFontEnum.Red); return(true); } if (strings[1].Equals("A", StringComparison.InvariantCultureIgnoreCase)) { var tmp = ActiveVoxelSetterPosition; if (tmp.HasValue) { var currentAsteroidList = new List <IMyVoxelBase>(); var bb = new BoundingBoxD(tmp.Value - 0.2f, tmp.Value + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _activeVoxelSetterNameA = currentAsteroidList[0].StorageName; _activeVoxelSetterPositionA = tmp; } } if (_activeVoxelSetterPositionA.HasValue) { MyAPIGateway.Utilities.ShowMessage(_activeVoxelSetterNameA, "Voxel setter point A: active"); } //MyAPIGateway.Utilities.ShowNotification("Voxel setter A: active.", 1000, MyFontEnum.Green); else { MyAPIGateway.Utilities.ShowNotification("Voxel setter A: invalid.", 1000, MyFontEnum.Red); } return(true); } if (strings[1].Equals("B", StringComparison.InvariantCultureIgnoreCase)) { var tmp = ActiveVoxelSetterPosition; if (tmp.HasValue) { var currentAsteroidList = new List <IMyVoxelBase>(); var bb = new BoundingBoxD(tmp.Value - 0.2f, tmp.Value + 0.2f); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.IsBoxIntersectingBoundingBoxOfThisVoxelMap(ref bb)); if (currentAsteroidList.Count > 0) { _activeVoxelSetterNameB = currentAsteroidList[0].StorageName; _activeVoxelSetterPositionB = tmp; } } if (_activeVoxelSetterPositionB.HasValue) { MyAPIGateway.Utilities.ShowMessage(_activeVoxelSetterNameB, "Voxel setter point B: active"); } //MyAPIGateway.Utilities.ShowNotification("Voxel setter B: active.", 1000, MyFontEnum.Green); else { MyAPIGateway.Utilities.ShowNotification("Voxel setter B: invalid.", 1000, MyFontEnum.Red); } return(true); } if (strings[1].Equals("C", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("Clear", StringComparison.InvariantCultureIgnoreCase)) { if (_activeVoxelSetterPositionA.HasValue && _activeVoxelSetterPositionB.HasValue && _activeVoxelSetterNameA == _activeVoxelSetterNameB) { var currentAsteroidList = new List <IMyVoxelBase>(); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(_activeVoxelSetterNameA, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count > 0) { var storage = currentAsteroidList[0].Storage; var point1 = new Vector3I(_activeVoxelSetterPositionA.Value - currentAsteroidList[0].PositionLeftBottomCorner); var point2 = new Vector3I(_activeVoxelSetterPositionB.Value - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var size = storage.Size; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, Vector3I.Zero, size - 1); var min = Vector3I.Min(point1, point2); var max = Vector3I.Max(point1, point2); MyAPIGateway.Utilities.ShowMessage("Cutting", min.ToString() + " " + max.ToString()); //MyAPIGateway.Utilities.ShowNotification("cutting:" + min.ToString() + " " + max.ToString(), 5000, MyFontEnum.Blue); Vector3I p; for (p.Z = min.Z; p.Z <= max.Z; ++p.Z) { for (p.Y = min.Y; p.Y <= max.Y; ++p.Y) { for (p.X = min.X; p.X <= max.X; ++p.X) { cache.Content(ref p, 0); } } } storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, size - 1); } } else if (_activeVoxelSetterNameA != _activeVoxelSetterNameB) { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: different asteroids.", 2000, MyFontEnum.Red); } else { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: invalid points.", 2000, MyFontEnum.Red); } return(true); } if (strings[1].Equals("F", StringComparison.InvariantCultureIgnoreCase) || strings[1].Equals("Fill", StringComparison.InvariantCultureIgnoreCase)) { if (_activeVoxelSetterPositionA.HasValue && _activeVoxelSetterPositionB.HasValue && _activeVoxelSetterNameA == _activeVoxelSetterNameB) { var currentAsteroidList = new List <IMyVoxelBase>(); MyAPIGateway.Session.VoxelMaps.GetInstances(currentAsteroidList, v => v.StorageName.Equals(_activeVoxelSetterNameA, StringComparison.InvariantCultureIgnoreCase)); if (currentAsteroidList.Count > 0) { var storage = currentAsteroidList[0].Storage; var point1 = new Vector3I(_activeVoxelSetterPositionA.Value - currentAsteroidList[0].PositionLeftBottomCorner); var point2 = new Vector3I(_activeVoxelSetterPositionB.Value - currentAsteroidList[0].PositionLeftBottomCorner); var cache = new MyStorageData(); var size = storage.Size; cache.Resize(size); storage.ReadRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, (int)VRageRender.MyLodTypeEnum.LOD0, Vector3I.Zero, size - 1); var min = Vector3I.Min(point1, point2); var max = Vector3I.Max(point1, point2); MyAPIGateway.Utilities.ShowMessage("Filling", min.ToString() + " " + max.ToString()); //MyAPIGateway.Utilities.ShowNotification("filling:" + min.ToString() + " " + max.ToString(), 5000, MyFontEnum.Blue); Vector3I p; for (p.Z = min.Z; p.Z <= max.Z; ++p.Z) { for (p.Y = min.Y; p.Y <= max.Y; ++p.Y) { for (p.X = min.X; p.X <= max.X; ++p.X) { cache.Content(ref p, 0xff); } } } storage.WriteRange(cache, MyStorageDataTypeFlags.ContentAndMaterial, Vector3I.Zero, size - 1); } } else if (_activeVoxelSetterNameA != _activeVoxelSetterNameB) { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: different asteroids.", 2000, MyFontEnum.Red); } else { MyAPIGateway.Utilities.ShowNotification("Voxel setter Cut: invalid points.", 2000, MyFontEnum.Red); } return(true); } } } return(false); }
// 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 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); } } } }
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; }
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 unsafe void CalculateDistanceFieldInternal(Vector3 localPos, int faceHint, Vector3I min, Vector3I max, Vector3I writeOffsetLoc, MyStorageData target, float lodVoxelSize) { Vector3I vectori; this.PrepareCache(); Vector3 vector = localPos; if (faceHint == -1) { vectori.Z = min.Z; while (vectori.Z <= max.Z) { vectori.Y = min.Y; while (true) { if (vectori.Y > max.Y) { float *singlePtr3 = (float *)ref localPos.Z; singlePtr3[0] += lodVoxelSize; localPos.Y = vector.Y; int *numPtr3 = (int *)ref vectori.Z; numPtr3[0]++; break; } vectori.X = min.X; Vector3I p = (Vector3I)(vectori + writeOffsetLoc); int linearIdx = target.ComputeLinear(ref p); while (true) { if (vectori.X > max.X) { float *singlePtr2 = (float *)ref localPos.Y; singlePtr2[0] += lodVoxelSize; localPos.X = vector.X; int *numPtr2 = (int *)ref vectori.Y; numPtr2[0]++; break; } byte content = (byte)(((MathHelper.Clamp(-(this.SignedDistanceLocal(localPos, lodVoxelSize) / lodVoxelSize), -1f, 1f) * 0.5f) + 0.5f) * 255f); target.Content(linearIdx, content); linearIdx += target.StepLinear; float *singlePtr1 = (float *)ref localPos.X; singlePtr1[0] += lodVoxelSize; int *numPtr1 = (int *)ref vectori.X; numPtr1[0]++; } } } } else { vectori.Z = min.Z; while (vectori.Z <= max.Z) { vectori.Y = min.Y; while (true) { if (vectori.Y > max.Y) { float *singlePtr6 = (float *)ref localPos.Z; singlePtr6[0] += lodVoxelSize; localPos.Y = vector.Y; int *numPtr6 = (int *)ref vectori.Z; numPtr6[0]++; break; } vectori.X = min.X; Vector3I p = (Vector3I)(vectori + writeOffsetLoc); int linearIdx = target.ComputeLinear(ref p); while (true) { if (vectori.X > max.X) { float *singlePtr5 = (float *)ref localPos.Y; singlePtr5[0] += lodVoxelSize; localPos.X = vector.X; int *numPtr5 = (int *)ref vectori.Y; numPtr5[0]++; break; } byte content = (byte)(((MathHelper.Clamp(-(this.SignedDistanceLocal(localPos, lodVoxelSize, faceHint) / lodVoxelSize), -1f, 1f) * 0.5f) + 0.5f) * 255f); target.Content(linearIdx, content); linearIdx += target.StepLinear; float *singlePtr4 = (float *)ref localPos.X; singlePtr4[0] += lodVoxelSize; int *numPtr4 = (int *)ref vectori.X; numPtr4[0]++; } } } } }
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; }
/// <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); }
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(); }
internal void ReadContentRange(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; ProfilerShort.Begin("Testing removed shapes"); var overlappedRemovedShapes = OverlappedRemovedShapes; overlappedRemovedShapes.Clear(); ContainmentType testRemove = ContainmentType.Disjoint; for (int i = 0; i < m_data.RemovedShapes.Length; ++i) { var test = m_data.RemovedShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test == ContainmentType.Contains) { testRemove = ContainmentType.Contains; break; // completely empty so we can leave } else if (test == ContainmentType.Intersects) { testRemove = ContainmentType.Intersects; overlappedRemovedShapes.Add(m_data.RemovedShapes[i]); } } ProfilerShort.End(); if (testRemove == ContainmentType.Contains) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY); ProfilerShort.End(); return; } ProfilerShort.Begin("Testing filled shapes"); var overlappedFilledShapes = OverlappedFilledShapes; overlappedFilledShapes.Clear(); ContainmentType testFill = ContainmentType.Disjoint; for (int i = 0; i < m_data.FilledShapes.Length; ++i) { var test = m_data.FilledShapes[i].Contains(ref queryBox, ref querySphere, lodVoxelSize); if (test == ContainmentType.Contains) { overlappedFilledShapes.Clear(); testFill = ContainmentType.Contains; break; } else if (test == ContainmentType.Intersects) { overlappedFilledShapes.Add(m_data.FilledShapes[i]); testFill = ContainmentType.Intersects; } } ProfilerShort.End(); if (testFill == ContainmentType.Disjoint) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_EMPTY); ProfilerShort.End(); return; } else if (testRemove == ContainmentType.Disjoint && testFill == ContainmentType.Contains) { ProfilerShort.Begin("target.BlockFillContent"); target.BlockFillContent(writeOffset, writeOffset + (maxInLod - minInLod), MyVoxelConstants.VOXEL_CONTENT_FULL); ProfilerShort.End(); return; } ProfilerShort.Begin("Distance field computation"); Vector3I v = minInLod; Vector3 localPos = v * lodVoxelSize; Vector3 localPosStart = v * lodVoxelSize; var writeOffsetLoc = writeOffset - minInLod; for (v.Z = minInLod.Z; v.Z <= maxInLod.Z; ++v.Z) { for (v.Y = minInLod.Y; v.Y <= maxInLod.Y; ++v.Y) { v.X = minInLod.X; var write2 = v + writeOffsetLoc; var write = target.ComputeLinear(ref write2); for (; v.X <= maxInLod.X; ++v.X) { //Vector3 localPos = v * lodVoxelSize; //ProfilerShort.Begin("Dist filled"); float distFill; if (testFill == ContainmentType.Contains) { distFill = -1f; } else { //ProfilerShort.Begin("shape distances"); distFill = 1f; foreach (var shape in overlappedFilledShapes) { distFill = Math.Min(distFill, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule)); if (distFill <= -1) { break; } } //ProfilerShort.End(); } //ProfilerShort.BeginNextBlock("Dist removed"); float distRemoved = 1f; if (testRemove != ContainmentType.Disjoint) { foreach (var shape in overlappedRemovedShapes) { distRemoved = Math.Min(distRemoved, shape.SignedDistance(ref localPos, lodVoxelSize, m_data.MacroModule, m_data.DetailModule)); if (distRemoved <= -1) { break; } } } //ProfilerShort.BeginNextBlock("content"); float signedDist = MathHelper.Max(distFill, -distRemoved); var fillRatio = MathHelper.Clamp(-signedDist, -1f, 1f) * 0.5f + 0.5f; byte content = (byte)(fillRatio * MyVoxelConstants.VOXEL_CONTENT_FULL); target.Content(write, content); Debug.Assert(Math.Abs((((float)content) / MyVoxelConstants.VOXEL_CONTENT_FULL) - fillRatio) <= 0.5f); //ProfilerShort.End(); write += target.StepLinear; localPos.X += lodVoxelSize; } localPos.Y += lodVoxelSize; localPos.X = localPosStart.X; } localPos.Z += lodVoxelSize; localPos.Y = localPosStart.Y; } ProfilerShort.End(); }