private static void SetupReading( int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod, out float lodVoxelSizeHalf, out BoundingBox queryBox, out BoundingSphere querySphere) { ProfilerShort.Begin("SetupReading"); lodVoxelSizeHalf = MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * (1 << lodIndex); Vector3 localMin, localMax; { Vector3D localPositionD; var min = minInLod << lodIndex; var max = maxInLod << lodIndex; MyVoxelCoordSystems.VoxelCoordToLocalPosition(ref min, out localPositionD); localMin = localPositionD; MyVoxelCoordSystems.VoxelCoordToLocalPosition(ref max, out localPositionD); localMax = localPositionD; localMin -= lodVoxelSizeHalf; localMax += lodVoxelSizeHalf; } queryBox = new BoundingBox(localMin, localMax); BoundingSphere.CreateFromBoundingBox(ref queryBox, out querySphere); 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(); }