private static void GetVoxelShapeDimensions(MyVoxelBase voxelMap, MyShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells) { BoundingBoxD worldBoundaries = shape.GetWorldBoundaries(); ComputeShapeBounds(voxelMap, ref worldBoundaries, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner); numCells = new Vector3I((maxCorner.X - minCorner.X) / 0x10, (maxCorner.Y - minCorner.Y) / 0x10, (maxCorner.Z - minCorner.Z) / 0x10); }
private static void CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { // Check static grids around (possible change to dynamic) if (Sync.IsServer && MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); List <MyEntity> boxOverlapList = new List <MyEntity>(); MyEntities.GetElementsInBox(ref cutOutBox, boxOverlapList); foreach (var entity in boxOverlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) { grid.TestDynamic = true; } } } boxOverlapList.Clear(); } }
private static void GetVoxelShapeDimensions(MyVoxelBase voxelMap, MyShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells) { { var bbox = shape.GetWorldBoundaries(); ComputeShapeBounds(voxelMap, ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner); } numCells = new Vector3I((maxCorner.X - minCorner.X) / CELL_SIZE, (maxCorner.Y - minCorner.Y) / CELL_SIZE, (maxCorner.Z - minCorner.Z) / CELL_SIZE); }
private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { if (Sync.IsServer) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList); // Check static grids around (possible change to dynamic) if (/*MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL &&*/ MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { foreach (var entity in m_overlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) { grid.TestDynamic = true; } } } } } var voxelPhysics = voxelMap as MyVoxelPhysics; MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet; if (planet != null) { var planetEnvironment = planet.Components.Get <MyPlanetEnvironmentComponent>(); if (planetEnvironment != null) { var sectors = planetEnvironment.GetSectorsInRange(shape); if (sectors != null) { foreach (var sector in sectors) { sector.DisableItemsInShape(shape); } } } } m_overlapList.Clear(); }
private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { if (!Sync.IsServer) { return; } BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList); // Check static grids around (possible change to dynamic) if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { foreach (var entity in m_overlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) { grid.TestDynamic = true; } } } } var voxelPhysics = voxelMap as MyVoxelPhysics; MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet; if (planet != null) { var center = cutOutBox.Center; foreach (var environment in planet.GetEnvironmentItemsAtPosition(ref center)) { environment.RemoveItemsAroundPoint(cutOutBox.Center, cutOutBox.HalfExtents.Max()); } } m_overlapList.Clear(); }
public static void RevertShape(MyVoxelBase voxelMap, MyShape shape) { using (voxelMap.Pin()) { if (!voxelMap.MarkedForClose) { Vector3I vectori; Vector3I maxCorner; Vector3I minCorner; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori); minCorner = Vector3I.Max(Vector3I.One, minCorner); maxCorner = Vector3I.Max(minCorner, maxCorner - Vector3I.One); voxelMap.Storage.DeleteRange(MyStorageDataTypeFlags.All, minCorner, maxCorner, false); BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); MySandboxGame.Static.Invoke(delegate { if (voxelMap.Storage != null) { voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All); NotifyVoxelChanged(MyVoxelBase.OperationType.Revert, voxelMap, ref cutOutBox); } }, "RevertShape notify"); } } }
private static void OnVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { if (!Sync.IsServer) return; BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList); // Check static grids around (possible change to dynamic) if (MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { foreach (var entity in m_overlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) grid.TestDynamic = true; } } } var voxelPhysics = voxelMap as MyVoxelPhysics; MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet; if (planet != null) { var center = cutOutBox.Center; foreach (var environment in planet.GetEnvironmentItemsAtPosition(ref center)) { environment.RemoveItemsAroundPoint(cutOutBox.Center, cutOutBox.HalfExtents.Max()); } } m_overlapList.Clear(); }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false) { if (MySession.Static.EnableVoxelDestruction == false) { voxelsCountInPercent = 0; voxelMaterial = null; return; } ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; // Some shapes just ignore transforms so we round the bbox conservativelly by converting it to sphere var bbox = shape.GetWorldBoundaries(); var center = bbox.Center; var radius = (center - bbox.Min).Length(); MatrixD mat = voxelMap.PositionComp.WorldMatrix; MatrixD inverse; //Vector3D translation = mat.Translation; //mat.Translation = Vector3D.Zero; // invert is used to bring voxel coordinates back to world. inverse = voxelMap.PositionComp.WorldMatrixInvScaled;//MatrixD.Invert(ref mat, out inverse); Vector3 offset = voxelMap.StorageMin + voxelMap.SizeInMetresHalf; Vector3D.Transform(ref center, ref inverse, out center); // The transform is centered, but the code expects voxel local coordinates. center += voxelMap.SizeInMetresHalf; bbox = new BoundingBoxD(center - radius, center + radius); Vector3I minCorner, maxCorner; ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax); { var shapeCenter = bbox.Center; Vector3I exactCenter; MyVoxelCoordSystems.WorldPositionToVoxelCoord(Vector3.Zero, ref shapeCenter, out exactCenter); exactCenter -= cacheMin; exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1); voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter)); } ProfilerShort.Begin("Main loop"); for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cacheMin; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove { continue; } Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToLocalPosition(ref it.Current, out vpos); // center vpos -= offset; // transform back to world space. Vector3D.Transform(ref vpos, ref mat, out vpos); var volume = shape.GetVolume(ref vpos); if (volume == 0f) // if there is no intersection { continue; } var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); var toRemove = (int)(maxRemove * voxelMat.DamageRatio); var newVal = MathHelper.Clamp(original - toRemove, 0, original - maxRemove); var removed = Math.Abs(original - newVal); if (!onlyCheck) { m_cache.Content(ref relPos, (byte)newVal); } originalSum += original; removedSum += removed; if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap); } ProfilerShort.BeginNextBlock("Write"); if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } ProfilerShort.End(); voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; if (removedSum > 0) { CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape); } ProfilerShort.End(); }
private static void GetVoxelShapeDimensions(MyVoxelBase voxelMap, MyShape shape, out Vector3I minCorner, out Vector3I maxCorner, out Vector3I numCells, float extent = 0.0f) { { var bbox = shape.GetWorldBoundaries(); ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner); } minCorner += voxelMap.StorageMin; maxCorner += voxelMap.StorageMin; numCells = new Vector3I((maxCorner.X - minCorner.X) / CELL_SIZE, (maxCorner.Y - minCorner.Y) / CELL_SIZE, (maxCorner.Z - minCorner.Z) / CELL_SIZE); }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false) { ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; var bbox = shape.GetWorldBoundaries(); Vector3I minCorner, maxCorner; ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax); { var shapeCenter = bbox.Center; Vector3I exactCenter; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeCenter, out exactCenter); exactCenter -= cacheMin; exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1); voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter)); } for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cacheMin; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove continue; Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); var volume = shape.GetVolume(ref vpos); if (volume == 0f) // if there is no intersection continue; var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); var toRemove = (int)(maxRemove * voxelMat.DamageRatio); var newVal = MathHelper.Clamp(original - toRemove, 0, maxRemove); var removed = Math.Abs(original - newVal); if (!onlyCheck) m_cache.Content(ref relPos, (byte)newVal); originalSum += original; removedSum += removed; if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } } if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap.SyncObject); } voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; ProfilerShort.End(); }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false, bool applyDamageMaterial = false, bool onlyApplyMaterial = false) { if (MySession.Static.EnableVoxelDestruction == false) { voxelsCountInPercent = 0; voxelMaterial = null; return; } ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; bool materials = exactCutOutMaterials != null; // Bring the shape into voxel space. var oldTranmsform = shape.Transformation; var newTransf = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled; newTransf.Translation += voxelMap.SizeInMetresHalf; shape.Transformation = newTransf; // This boundary should now be in our local space var bbox = shape.GetWorldBoundaries(); Vector3I minCorner, maxCorner; ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner); bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial; var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf /*const int SHIFT = 4; const int REM = (1 << SHIFT) - 1; const int MASK = ~REM; cacheMin &= MASK; cacheMax = (cacheMax + REM) & MASK;*/ voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); m_cache.ClearMaterials(0); // Advise that the read content shall be cached MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache; voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags); Vector3I center; if (materials) { center = m_cache.Size3D / 2; voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center)); } else { center = (cacheMin + cacheMax) / 2; voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center); } MyVoxelMaterialDefinition voxelMat = null; ProfilerShort.Begin("Main loop"); 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 original = m_cache.Content(lin); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove continue; Vector3D spos = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var volume = shape.GetVolume(ref spos); if (volume == 0f) // if there is no intersection continue; var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var toRemove = maxRemove;// (int)(maxRemove * voxelMat.DamageRatio); var newVal = Math.Max(original - toRemove, 0);//MathHelper.Clamp(original - toRemove, 0, original-maxRemove); var removed = original - newVal; if (!onlyCheck && !onlyApplyMaterial) m_cache.Content(lin, (byte)newVal); originalSum += original; removedSum += removed; if (readMaterial) voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin)); if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } if (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck) m_cache.Material(lin, voxelMat.DamagedMaterialId); } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial); } ProfilerShort.BeginNextBlock("Write"); if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! //RemoveSmallVoxelsUsingChachedVoxels(); var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content; if (MyFakes.LOG_NAVMESH_GENERATION) MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax); voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax); } ProfilerShort.End(); voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; shape.Transformation = oldTranmsform; if (removedSum > 0) OnVoxelChanged(OperationType.Cut, voxelMap, shape); ProfilerShort.End(); }
private static void OnVoxelChanged(OperationType type, MyVoxelBase voxelMap, MyShape shape) { if (Sync.IsServer) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); MyEntities.GetElementsInBox(ref cutOutBox, m_overlapList); // Check static grids around (possible change to dynamic) if (/*MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL &&*/ MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { foreach (var entity in m_overlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == OperationType.Cut) grid.TestDynamic = true; } } } } var voxelPhysics = voxelMap as MyVoxelPhysics; MyPlanet planet = voxelPhysics != null ? voxelPhysics.Parent : voxelMap as MyPlanet; if (planet != null) { var planetEnvironment = planet.Components.Get<MyPlanetEnvironmentComponent>(); if (planetEnvironment != null) { var sectors = planetEnvironment.GetSectorsInRange(shape); if (sectors != null) foreach (var sector in sectors) sector.DisableItemsInShape(shape); } } m_overlapList.Clear(); }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false) { ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; var bbox = shape.GetWorldBoundaries(); Vector3I minCorner, maxCorner; ComputeShapeBounds(ref bbox, voxelMap.PositionLeftBottomCorner, voxelMap.Storage.Size, out minCorner, out maxCorner); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax); { var shapeCenter = bbox.Center; Vector3I exactCenter; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxelMap.PositionLeftBottomCorner, ref shapeCenter, out exactCenter); exactCenter -= cacheMin; exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1); voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter)); } for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cacheMin; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove { continue; } Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); var volume = shape.GetVolume(ref vpos); if (volume == 0f) // if there is no intersection { continue; } var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); var toRemove = (int)(maxRemove * voxelMat.DamageRatio); var newVal = MathHelper.Clamp(original - toRemove, 0, maxRemove); var removed = Math.Abs(original - newVal); if (!onlyCheck) { m_cache.Content(ref relPos, (byte)newVal); } originalSum += original; removedSum += removed; if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } } if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap.SyncObject); } voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; ProfilerShort.End(); }
private static bool CanPlaceInArea(PaintType type, MyShape Shape) { if (type == PaintType.Fill) { m_foundElements.Clear(); BoundingBoxD box = Shape.GetWorldBoundaries(); MyEntities.GetElementsInBox(ref box, m_foundElements); foreach (var entity in m_foundElements) { if (IsForbiddenEntity(entity)) { if (entity.PositionComp.WorldAABB.Intersects(box)) { return false; } } } } return true; }
static bool CanPlaceInArea(OperationType type, MyShape Shape) { if (type == OperationType.Fill) { m_foundElements.Clear(); BoundingBoxD box = Shape.GetWorldBoundaries(); MyEntities.GetElementsInBox(ref box, m_foundElements); foreach (var entity in m_foundElements) { if (IsForbiddenEntity(entity)) { if (entity.PositionComp.WorldAABB.Intersects(box)) { MyHud.Notifications.Add(MyNotificationSingletons.CopyPasteAsteoridObstructed); return false; } } } } return true; }
private static void CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType type, MyVoxelBase voxelMap, MyShape shape) { // Check static grids around (possible change to dynamic) if (Sync.IsServer && MyFakes.ENABLE_BLOCK_PLACEMENT_ON_VOXEL && MyFakes.ENABLE_BLOCKS_IN_VOXELS_TEST && MyStructuralIntegrity.Enabled) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); cutOutBox.Inflate(0.25); List<MyEntity> boxOverlapList = new List<MyEntity>(); MyEntities.GetElementsInBox(ref cutOutBox, boxOverlapList); foreach (var entity in boxOverlapList) { var grid = entity as MyCubeGrid; if (grid != null && grid.IsStatic) { if (grid.Physics != null && grid.Physics.Shape != null) { grid.Physics.Shape.RecalculateConnectionsToWorld(grid.GetBlocks()); } if (type == MyVoxelBase.OperationType.Cut) grid.TestDynamic = true; } } boxOverlapList.Clear(); } }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false, bool applyDamageMaterial = false, bool onlyApplyMaterial = false) { if (MySession.Static.EnableVoxelDestruction == false) { voxelsCountInPercent = 0; voxelMaterial = null; return; } ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; bool materials = exactCutOutMaterials != null; // Bring the shape into voxel space. var oldTranmsform = shape.Transformation; var newTransf = oldTranmsform * voxelMap.PositionComp.WorldMatrixInvScaled; newTransf.Translation += voxelMap.SizeInMetresHalf; shape.Transformation = newTransf; // This boundary should now be in our local space var bbox = shape.GetWorldBoundaries(); Vector3I minCorner, maxCorner; ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner); bool readMaterial = exactCutOutMaterials != null || applyDamageMaterial; var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; //try on making the read/write cell alligned see MyOctreeStorage.WriteRange - Micro octree leaf /*const int SHIFT = 4; * const int REM = (1 << SHIFT) - 1; * const int MASK = ~REM; * cacheMin &= MASK; * cacheMax = (cacheMax + REM) & MASK;*/ voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); m_cache.ClearMaterials(0); // Advise that the read content shall be cached MyVoxelRequestFlags flags = MyVoxelRequestFlags.AdviseCache; voxelMap.Storage.ReadRange(m_cache, readMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax, ref flags); Vector3I center; if (materials) { center = m_cache.Size3D / 2; voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref center)); } else { center = (cacheMin + cacheMax) / 2; voxelMaterial = voxelMap.Storage.GetMaterialAt(ref center); } MyVoxelMaterialDefinition voxelMat = null; ProfilerShort.Begin("Main loop"); 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 original = m_cache.Content(lin); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove { continue; } Vector3D spos = (Vector3D)(pos - voxelMap.StorageMin) * MyVoxelConstants.VOXEL_SIZE_IN_METRES; var volume = shape.GetVolume(ref spos); if (volume == 0f) // if there is no intersection { continue; } var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var toRemove = maxRemove; // (int)(maxRemove * voxelMat.DamageRatio); var newVal = Math.Max(original - toRemove, 0); //MathHelper.Clamp(original - toRemove, 0, original-maxRemove); var removed = original - newVal; if (!onlyCheck && !onlyApplyMaterial) { m_cache.Content(lin, (byte)newVal); } originalSum += original; removedSum += removed; if (readMaterial) { voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(lin)); } if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } if (applyDamageMaterial && voxelMat.HasDamageMaterial && !onlyCheck) { m_cache.Material(lin, voxelMat.DamagedMaterialId); } } } } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial); } ProfilerShort.BeginNextBlock("Write"); if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! //RemoveSmallVoxelsUsingChachedVoxels(); var dataTypeFlags = applyDamageMaterial ? MyStorageDataTypeFlags.ContentAndMaterial : MyStorageDataTypeFlags.Content; if (MyFakes.LOG_NAVMESH_GENERATION) { MyAIComponent.Static.Pathfinding.VoxelPathfinding.DebugLog.LogStorageWrite(voxelMap, m_cache, dataTypeFlags, cacheMin, cacheMax); } voxelMap.Storage.WriteRange(m_cache, dataTypeFlags, ref cacheMin, ref cacheMax); } ProfilerShort.End(); voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; shape.Transformation = oldTranmsform; if (removedSum > 0) { OnVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape); } ProfilerShort.End(); }
public static void CutOutShape(MyVoxelBase voxelMap, MyShape shape, bool voxelHand = false) { if (MySession.Static.EnableVoxelDestruction || MySession.Static.HighSimulationQuality) { using (voxelMap.Pin()) { if (!voxelMap.MarkedForClose) { Vector3I vectori; Vector3I maxCorner; Vector3I minCorner; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori); ulong num = 0UL; if (m_cache == null) { m_cache = new MyStorageData(MyStorageDataTypeFlags.All); } Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori); while (true) { Vector3I vectori2; Vector3I vectori3; if (!it.IsValid()) { if (num > 0L) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); MySandboxGame.Static.Invoke(delegate { if (voxelMap.Storage != null) { voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All); NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref cutOutBox); } }, "CutOutShape notify"); } break; } GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3); Vector3I voxelCoord = vectori2 - 1; Vector3I vectori5 = (Vector3I)(vectori3 + 1); voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1); voxelMap.Storage.ClampVoxelCoord(ref vectori5, 1); ulong num2 = 0UL; m_cache.Resize(voxelCoord, vectori5); MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent; voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, voxelCoord, vectori5, ref considerContent); Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3); while (true) { if (!iterator2.IsValid()) { if (num2 > 0L) { RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, voxelCoord, vectori5, false, true); } num += num2; it.MoveNext(); break; } Vector3I p = iterator2.Current - voxelCoord; byte num3 = m_cache.Content(ref p); if (num3 != 0) { Vector3D vectord; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord); float volume = shape.GetVolume(ref vectord); if (volume != 0f) { int num5 = Math.Min((int)(255f - (volume * 255f)), num3); ulong num6 = (ulong)Math.Abs((int)(num3 - num5)); m_cache.Content(ref p, (byte)num5); if (num5 == 0) { m_cache.Material(ref p, 0xff); } num2 += num6; } } iterator2.MoveNext(); } } } } } }
public static void FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { using (voxelMap.Pin()) { if (!voxelMap.MarkedForClose) { Vector3I vectori; Vector3I maxCorner; Vector3I minCorner; ulong num = 0UL; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori); minCorner = Vector3I.Max(Vector3I.One, minCorner); maxCorner = Vector3I.Max(minCorner, maxCorner - Vector3I.One); if (m_cache == null) { m_cache = new MyStorageData(MyStorageDataTypeFlags.All); } Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref Vector3I.Zero, ref vectori); while (true) { Vector3I vectori2; Vector3I vectori3; if (!it.IsValid()) { if (num > 0L) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); MySandboxGame.Static.Invoke(delegate { if (voxelMap.Storage != null) { voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All); NotifyVoxelChanged(MyVoxelBase.OperationType.Fill, voxelMap, ref cutOutBox); } }, "FillInShape Notify"); } break; } GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3); Vector3I originalValue = vectori3; voxelMap.Storage.ClampVoxelCoord(ref vectori2, 0); voxelMap.Storage.ClampVoxelCoord(ref vectori3, 0); ClampingInfo info = CheckForClamping(vectori2, vectori2); ClampingInfo info2 = CheckForClamping(originalValue, vectori3); m_cache.Resize(vectori2, vectori3); MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent; voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent); ulong num2 = 0UL; Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3); while (true) { if (!iterator2.IsValid()) { if (num2 > 0L) { RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.All, vectori2, vectori3, false, true); } num += num2; it.MoveNext(); break; } Vector3I p = iterator2.Current - vectori2; byte num3 = m_cache.Content(ref p); if ((num3 != 0xff) || (m_cache.Material(ref p) != materialIdx)) { if ((((iterator2.Current.X == vectori2.X) && info.X) || (((iterator2.Current.X == vectori3.X) && info2.X) || (((iterator2.Current.Y == vectori2.Y) && info.Y) || (((iterator2.Current.Y == vectori3.Y) && info2.Y) || ((iterator2.Current.Z == vectori2.Z) && info.Z))))) || ((iterator2.Current.Z == vectori3.Z) && info2.Z)) { if (num3 != 0) { m_cache.Material(ref p, materialIdx); } } else { Vector3D vectord; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord); float volume = shape.GetVolume(ref vectord); if (volume > 0f) { long num6 = Math.Max(num3, (int)(volume * 255f)); m_cache.Content(ref p, (byte)num6); if (num6 != 0) { m_cache.Material(ref p, materialIdx); } num2 += ((ulong)num6) - num3; } } } iterator2.MoveNext(); } } } } }
public static unsafe void ChangeMaterialsInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx, bool[] materialsToChange) { if ((voxelMap != null) && (shape != null)) { using (voxelMap.Pin()) { if (!voxelMap.MarkedForClose) { Vector3I vectori; Vector3I vectori2; Vector3I vectori5; MatrixD xd = shape.Transformation * voxelMap.PositionComp.WorldMatrixInvScaled; MatrixD *xdPtr1 = (MatrixD *)ref xd; xdPtr1.Translation += voxelMap.SizeInMetresHalf; shape.Transformation = xd; BoundingBoxD worldBoundaries = shape.GetWorldBoundaries(); ComputeShapeBounds(voxelMap, ref worldBoundaries, Vector3.Zero, voxelMap.Storage.Size, out vectori, out vectori2); Vector3I voxelCoord = vectori - 1; Vector3I vectori4 = (Vector3I)(vectori2 + 1); voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1); voxelMap.Storage.ClampVoxelCoord(ref vectori4, 1); if (m_cache == null) { m_cache = new MyStorageData(MyStorageDataTypeFlags.All); } m_cache.Resize(voxelCoord, vectori4); MyVoxelRequestFlags requestFlags = MyVoxelRequestFlags.AdviseCache | MyVoxelRequestFlags.ConsiderContent; voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, voxelCoord, vectori4, ref requestFlags); vectori5.X = vectori.X; while (vectori5.X <= vectori2.X) { vectori5.Y = vectori.Y; while (true) { if (vectori5.Y > vectori2.Y) { int *numPtr3 = (int *)ref vectori5.X; numPtr3[0]++; break; } vectori5.Z = vectori.Z; while (true) { if (vectori5.Z > vectori2.Z) { int *numPtr2 = (int *)ref vectori5.Y; numPtr2[0]++; break; } Vector3I p = vectori5 - vectori; int linearIdx = m_cache.ComputeLinear(ref p); byte index = m_cache.Material(linearIdx); if (materialsToChange[index]) { Vector3D vectord; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref vectori5, out vectord); if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff)) { m_cache.Material(ref p, materialIdx); } } int *numPtr1 = (int *)ref vectori5.Z; numPtr1[0]++; } } } } } } }
public static unsafe void CutOutShapeWithProperties(MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary <MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false, bool applyDamageMaterial = false, bool onlyApplyMaterial = false, bool skipCache = false) { if ((!MySession.Static.EnableVoxelDestruction || ((voxelMap == null) || (voxelMap.Storage == null))) || (shape == null)) { voxelsCountInPercent = 0f; voxelMaterial = null; } else { Vector3I vectori3; Vector3I vectori4; Vector3I maxCorner; Vector3I minCorner; int num = 0; int num2 = 0; MatrixD transformation = shape.Transformation; MatrixD xd2 = transformation * voxelMap.PositionComp.WorldMatrixInvScaled; MatrixD *xdPtr1 = (MatrixD *)ref xd2; xdPtr1.Translation += voxelMap.SizeInMetresHalf; shape.Transformation = xd2; BoundingBoxD worldBoundaries = shape.GetWorldBoundaries(); ComputeShapeBounds(voxelMap, ref worldBoundaries, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner); bool flag = (exactCutOutMaterials != null) | applyDamageMaterial; Vector3I voxelCoord = minCorner - 1; Vector3I vectori2 = (Vector3I)(maxCorner + 1); voxelMap.Storage.ClampVoxelCoord(ref voxelCoord, 1); voxelMap.Storage.ClampVoxelCoord(ref vectori2, 1); if (m_cache == null) { m_cache = new MyStorageData(MyStorageDataTypeFlags.All); } m_cache.Resize(voxelCoord, vectori2); MyVoxelRequestFlags requestFlags = (skipCache ? ((MyVoxelRequestFlags)0) : MyVoxelRequestFlags.AdviseCache) | (flag ? MyVoxelRequestFlags.ConsiderContent : ((MyVoxelRequestFlags)0)); voxelMap.Storage.ReadRange(m_cache, flag ? MyStorageDataTypeFlags.All : MyStorageDataTypeFlags.Content, 0, voxelCoord, vectori2, ref requestFlags); if (exactCutOutMaterials != null) { vectori3 = (Vector3I)(m_cache.Size3D / 2); voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref vectori3)); } else { vectori3 = (Vector3I)((voxelCoord + vectori2) / 2); voxelMaterial = voxelMap.Storage.GetMaterialAt(ref vectori3); } MyVoxelMaterialDefinition key = null; vectori4.X = minCorner.X; while (vectori4.X <= maxCorner.X) { vectori4.Y = minCorner.Y; while (true) { if (vectori4.Y > maxCorner.Y) { int *numPtr3 = (int *)ref vectori4.X; numPtr3[0]++; break; } vectori4.Z = minCorner.Z; while (true) { if (vectori4.Z > maxCorner.Z) { int *numPtr2 = (int *)ref vectori4.Y; numPtr2[0]++; break; } Vector3I p = vectori4 - voxelCoord; int linearIdx = m_cache.ComputeLinear(ref p); byte num4 = m_cache.Content(linearIdx); if (num4 != 0) { Vector3D voxelPosition = (Vector3D)((vectori4 - voxelMap.StorageMin) * 1.0); float volume = shape.GetVolume(ref voxelPosition); if (volume != 0f) { int num7 = Math.Max(num4 - ((int)(volume * 255f)), 0); int num8 = num4 - num7; if ((num4 / 10) != (num7 / 10)) { if (!onlyCheck && !onlyApplyMaterial) { m_cache.Content(linearIdx, (byte)num7); } num += num4; num2 += num8; byte materialIndex = m_cache.Material(linearIdx); if (num7 == 0) { m_cache.Material(linearIdx, 0xff); } if (materialIndex != 0xff) { if (flag) { key = MyDefinitionManager.Static.GetVoxelMaterialDefinition(materialIndex); } if (exactCutOutMaterials != null) { int num10; exactCutOutMaterials.TryGetValue(key, out num10); exactCutOutMaterials[key] = num10 + (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? ((int)(num8 * 3.9f)) : num8); } } } } } int *numPtr1 = (int *)ref vectori4.Z; numPtr1[0]++; } } } if ((((num2 > 0) & updateSync) && Sync.IsServer) && !onlyCheck) { shape.SendDrillCutOutRequest(voxelMap, applyDamageMaterial); } if ((num2 > 0) && !onlyCheck) { RemoveSmallVoxelsUsingChachedVoxels(); MyStorageDataTypeFlags all = MyStorageDataTypeFlags.All; if (MyFakes.LOG_NAVMESH_GENERATION && (MyAIComponent.Static.Pathfinding != null)) { MyAIComponent.Static.Pathfinding.GetPathfindingLog().LogStorageWrite(voxelMap, m_cache, all, voxelCoord, vectori2); } voxelMap.Storage.WriteRange(m_cache, all, voxelCoord, vectori2, false, skipCache); } voxelsCountInPercent = (num > 0f) ? (((float)num2) / ((float)num)) : 0f; if (num2 > 0) { BoundingBoxD cutOutBox = shape.GetWorldBoundaries(); MySandboxGame.Static.Invoke(delegate { if (voxelMap.Storage != null) { voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All); NotifyVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, ref cutOutBox); } }, "CutOutShapeWithProperties notify"); } shape.Transformation = transformation; } }
public IEnumerable<MyEnvironmentSector> GetSectorsInRange(MyShape shape) { var bb = shape.GetWorldBoundaries(); var hierarchyComp = Container.Get<MyHierarchyComponentBase>() as MyHierarchyComponent<MyEntity>; var entities = new List<MyEntity>(); hierarchyComp.QueryAABB(ref bb, entities); return entities.Cast<MyEnvironmentSector>(); }
public static void CutOutShapeWithProperties( MyVoxelBase voxelMap, MyShape shape, out float voxelsCountInPercent, out MyVoxelMaterialDefinition voxelMaterial, Dictionary<MyVoxelMaterialDefinition, int> exactCutOutMaterials = null, bool updateSync = false, bool onlyCheck = false) { if (MySession.Static.EnableVoxelDestruction == false) { voxelsCountInPercent = 0; voxelMaterial = null; return; } ProfilerShort.Begin("MyVoxelGenerator::CutOutShapeWithProperties()"); int originalSum = 0; int removedSum = 0; // Some shapes just ignore transforms so we round the bbox conservativelly by converting it to sphere var bbox = shape.GetWorldBoundaries(); var center = bbox.Center; var radius = (center - bbox.Min).Length(); MatrixD mat = voxelMap.PositionComp.WorldMatrix; MatrixD inverse; //Vector3D translation = mat.Translation; //mat.Translation = Vector3D.Zero; // invert is used to bring voxel coordinates back to world. inverse = voxelMap.PositionComp.WorldMatrixInvScaled;//MatrixD.Invert(ref mat, out inverse); Vector3 offset = voxelMap.StorageMin + voxelMap.SizeInMetresHalf; Vector3D.Transform(ref center, ref inverse, out center); // The transform is centered, but the code expects voxel local coordinates. center += voxelMap.SizeInMetresHalf; bbox = new BoundingBoxD(center - radius, center + radius); Vector3I minCorner, maxCorner; ComputeShapeBounds(voxelMap, ref bbox, Vector3.Zero, voxelMap.Storage.Size, out minCorner, out maxCorner); var cacheMin = minCorner - 1; var cacheMax = maxCorner + 1; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cacheMin, ref cacheMax); { var shapeCenter = bbox.Center; Vector3I exactCenter; MyVoxelCoordSystems.WorldPositionToVoxelCoord(Vector3.Zero, ref shapeCenter, out exactCenter); exactCenter -= cacheMin; exactCenter = Vector3I.Clamp(exactCenter, Vector3I.Zero, m_cache.Size3D - 1); voxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref exactCenter)); } ProfilerShort.Begin("Main loop"); for (var it = new Vector3I.RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cacheMin; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_EMPTY) // if there is nothing to remove continue; Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToLocalPosition(ref it.Current, out vpos); // center vpos -= offset; // transform back to world space. Vector3D.Transform(ref vpos, ref mat, out vpos); var volume = shape.GetVolume(ref vpos); if (volume == 0f) // if there is no intersection continue; var maxRemove = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); var voxelMat = MyDefinitionManager.Static.GetVoxelMaterialDefinition(m_cache.Material(ref relPos)); var toRemove = (int)(maxRemove * voxelMat.DamageRatio); var newVal = MathHelper.Clamp(original - toRemove, 0, original-maxRemove); var removed = Math.Abs(original - newVal); if (!onlyCheck) m_cache.Content(ref relPos, (byte)newVal); originalSum += original; removedSum += removed; if (exactCutOutMaterials != null) { int value = 0; exactCutOutMaterials.TryGetValue(voxelMat, out value); value += (MyFakes.ENABLE_REMOVED_VOXEL_CONTENT_HACK ? (int)(removed * 3.9f) : removed); exactCutOutMaterials[voxelMat] = value; } } if (removedSum > 0 && updateSync && Sync.IsServer) { shape.SendDrillCutOutRequest(voxelMap); } ProfilerShort.BeginNextBlock("Write"); if (removedSum > 0 && !onlyCheck) { // Clear all small voxel that may have been created during explosion. They can be created even outside the range of // explosion sphere, e.g. if you have three voxels in a row A, B, C, where A is 255, B is 60, and C is 255. During the // explosion you change C to 0, so now we have 255, 60, 0. Than another explosion that will change A to 0, so we // will have 0, 60, 0. But B was always outside the range of the explosion. So this is why we need to do -1/+1 and remove // B voxels too. //!! TODO AR & MK : check if this is needed !! RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } ProfilerShort.End(); voxelsCountInPercent = (originalSum > 0f) ? (float)removedSum / (float)originalSum : 0f; if (removedSum > 0) CheckNeighbourStaticGridsAfterVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape); ProfilerShort.End(); }