public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); 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); m_cache.Resize(cellMinCorner, cellMaxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner); for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cellMinCorner; Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); float volume = shape.GetVolume(ref vpos); if (volume > 0.5f) { m_cache.Material(ref relPos, materialIdx); // set material } } voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner); } }
public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape) { Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); ulong changedVolumeAmount = 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; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); ulong removedSum = 0; m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax); for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); 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 toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL)); var newVal = Math.Min(toRemove, original); ulong removed = (ulong)Math.Abs(original - newVal); m_cache.Content(ref relPos, (byte)newVal); removedSum += removed; } if (removedSum > 0) { RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } changedVolumeAmount += removedSum; } return(changedVolumeAmount); }
public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { using (voxelMap.Pin()) { if (!voxelMap.MarkedForClose) { Vector3I vectori; Vector3I maxCorner; Vector3I minCorner; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out vectori); 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()) { MySandboxGame.Static.Invoke(delegate { if (voxelMap.Storage != null) { voxelMap.Storage.NotifyChanged(minCorner, maxCorner, MyStorageDataTypeFlags.All); } }, "PaintInShape notify"); break; } GetCellCorners(ref minCorner, ref maxCorner, ref it, out vectori2, out vectori3); m_cache.Resize(vectori2, vectori3); MyVoxelRequestFlags considerContent = MyVoxelRequestFlags.ConsiderContent; voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.All, 0, vectori2, vectori3, ref considerContent); Vector3I_RangeIterator iterator2 = new Vector3I_RangeIterator(ref vectori2, ref vectori3); while (true) { Vector3D vectord; if (!iterator2.IsValid()) { voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, vectori2, vectori3, false, true); it.MoveNext(); break; } Vector3I p = iterator2.Current - vectori2; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref iterator2.Current, out vectord); if ((shape.GetVolume(ref vectord) > 0.5f) && (m_cache.Material(ref p) != 0xff)) { m_cache.Material(ref p, materialIdx); } iterator2.MoveNext(); } } } } }
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(); }
public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { Vector3I minCorner, maxCorner, numCells; ulong retValue = 0; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); //voxel must be at least 1 m from side to be closed (e.g. without holes in it) minCorner = Vector3I.Max(Vector3I.One, minCorner); maxCorner = Vector3I.Max(minCorner, maxCorner); 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); Vector3I originalMinCorner = cellMinCorner; Vector3I originalMaxCorner = cellMaxCorner; voxelMap.Storage.ClampVoxelCoord(ref cellMinCorner, 0); voxelMap.Storage.ClampVoxelCoord(ref cellMaxCorner, 0); ClampingInfo minCornerClamping = CheckForClamping(originalMinCorner, cellMinCorner); ClampingInfo maxCornerClamping = CheckForClamping(originalMaxCorner, cellMaxCorner); m_cache.Resize(cellMinCorner, cellMaxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cellMinCorner, ref cellMaxCorner); ulong filledSum = 0; for (var it = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cellMinCorner; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_FULL) // if there is nothing to add { continue; } //if there was some claping, fill the clamp region with material if ((it.Current.X == cellMinCorner.X && minCornerClamping.X) || (it.Current.X == cellMaxCorner.X && maxCornerClamping.X) || (it.Current.Y == cellMinCorner.Y && minCornerClamping.Y) || (it.Current.Y == cellMaxCorner.Y && maxCornerClamping.Y) || (it.Current.Z == cellMinCorner.Z && minCornerClamping.Z) || (it.Current.Z == cellMaxCorner.Z && maxCornerClamping.Z)) { m_cache.Material(ref relPos, materialIdx); continue; } Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); var volume = shape.GetVolume(ref vpos); if (volume <= 0f) // there is nothing to fill { continue; } m_cache.Material(ref relPos, materialIdx); // set material var toFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); long newVal = MathHelper.Clamp(original + toFill, 0, Math.Max(original, toFill)); m_cache.Content(ref relPos, (byte)newVal); filledSum += (ulong)(newVal - original); } if (filledSum > 0) { RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref cellMinCorner, ref cellMaxCorner); } retValue += filledSum; } if (retValue > 0) { OnVoxelChanged(MyVoxelBase.OperationType.Fill, voxelMap, shape); } return(retValue); }
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 ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape) { Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); ulong changedVolumeAmount = 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; voxelMap.Storage.ClampVoxelCoord(ref cacheMin); voxelMap.Storage.ClampVoxelCoord(ref cacheMax); ulong removedSum = 0; m_cache.Resize(cacheMin, cacheMax); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, 0, ref cacheMin, ref cacheMax); for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); 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 toRemove = (int)(MyVoxelConstants.VOXEL_CONTENT_FULL - (volume * MyVoxelConstants.VOXEL_CONTENT_FULL)); var newVal = Math.Min(toRemove, original); ulong removed = (ulong)Math.Abs(original - newVal); m_cache.Content(ref relPos, (byte)newVal); removedSum += removed; } if (removedSum > 0) { RemoveSmallVoxelsUsingChachedVoxels(); // must stay because of the around when filling voxels voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Content, ref cacheMin, ref cacheMax); } changedVolumeAmount += removedSum; } return changedVolumeAmount; }
public static void PaintInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { Vector3I minCorner, maxCorner, numCells; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); 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); m_cache.Resize(cellMinCorner, cellMaxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.Material, 0, ref cellMinCorner, ref cellMaxCorner); for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cellMinCorner; Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); float volume = shape.GetVolume(ref vpos); if (volume > 0.5f) m_cache.Material(ref relPos, materialIdx); // set material } voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.Material, ref cellMinCorner, ref cellMaxCorner); } }
public static ulong FillInShape(MyVoxelBase voxelMap, MyShape shape, byte materialIdx) { Vector3I minCorner, maxCorner, numCells; ulong retValue = 0; GetVoxelShapeDimensions(voxelMap, shape, out minCorner, out maxCorner, out numCells); 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); Vector3I originalMinCorner = cellMinCorner; Vector3I originalMaxCorner = cellMaxCorner; voxelMap.Storage.ClampVoxelCoord(ref cellMinCorner, VOXEL_CLAMP_BORDER_DISTANCE); voxelMap.Storage.ClampVoxelCoord(ref cellMaxCorner, VOXEL_CLAMP_BORDER_DISTANCE); ClampingInfo minCornerClamping = CheckForClamping(originalMinCorner, cellMinCorner); ClampingInfo maxCornerClamping = CheckForClamping(originalMaxCorner, cellMaxCorner); m_cache.Resize(cellMinCorner, cellMaxCorner); voxelMap.Storage.ReadRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, 0, ref cellMinCorner, ref cellMaxCorner); ulong filledSum = 0; for (var it = new Vector3I.RangeIterator(ref cellMinCorner, ref cellMaxCorner); it.IsValid(); it.MoveNext()) { var relPos = it.Current - cellMinCorner; // get original amount var original = m_cache.Content(ref relPos); if (original == MyVoxelConstants.VOXEL_CONTENT_FULL) // if there is nothing to add continue; //if there was some claping, fill the clamp region with material if ((it.Current.X == cellMinCorner.X && minCornerClamping.X) || (it.Current.X == cellMaxCorner.X && maxCornerClamping.X) || (it.Current.Y == cellMinCorner.Y && minCornerClamping.Y) || (it.Current.Y == cellMaxCorner.Y && maxCornerClamping.Y) || (it.Current.Z == cellMinCorner.Z && minCornerClamping.Z) || (it.Current.Z == cellMaxCorner.Z && maxCornerClamping.Z)) { m_cache.Material(ref relPos, materialIdx); continue; } Vector3D vpos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxelMap.PositionLeftBottomCorner, ref it.Current, out vpos); var volume = shape.GetVolume(ref vpos); if (volume <= 0f) // there is nothing to fill continue; m_cache.Material(ref relPos, materialIdx); // set material var toFill = (int)(volume * MyVoxelConstants.VOXEL_CONTENT_FULL); long newVal = MathHelper.Clamp(original + toFill, 0, Math.Max(original, toFill)); m_cache.Content(ref relPos, (byte)newVal); filledSum += (ulong)(newVal - original); } if (filledSum > 0) { RemoveSmallVoxelsUsingChachedVoxels(); voxelMap.Storage.WriteRange(m_cache, MyStorageDataTypeFlags.ContentAndMaterial, ref cellMinCorner, ref cellMaxCorner); } retValue += filledSum; } return retValue; }
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(); }
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(); }
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 unsafe void DisableItemsInShape(this MyEnvironmentSector sector, MyShape shape) { if (sector.DataView == null) return; for (int sectorInd = 0; sectorInd < sector.DataView.LogicalSectors.Count; sectorInd++) { var logicalSector = sector.DataView.LogicalSectors[sectorInd]; var logicalItems = logicalSector.Items; var cnt = logicalItems.Count; fixed (ItemInfo* items = logicalItems.GetInternalArray()) for (int i = 0; i < cnt; ++i) { var worldPos = sector.SectorCenter + items[i].Position; if (shape.GetVolume(ref worldPos) > 0f) { logicalSector.EnableItem(i, false); } } } }
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 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(); } } } } } }