private int GetDivideIndex(ref Vector3I renderCellCoord) { // TODO: Optimize int divideIndex = 0; if (m_lodDivisions > 1) { BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot()); Vector3I test = Vector3I.Round(lodAabb.Size / (double)MyVoxelCoordSystems.RenderCellSizeInMeters(m_lod)); //Vector3I lodSizeMinusOne = m_parentClipmap.LodSizeMinusOne(m_lod); //Vector3I lodSize = lodSizeMinusOne + Vector3I.One; Vector3I lodSize = test; Vector3I lodSizeMinusOne = test - 1; Vector3I lodDivision = Vector3I.One * (m_lodDivisions - 1); var cellIterator = new Vector3I_RangeIterator(ref Vector3I.Zero, ref lodDivision); for (; cellIterator.IsValid(); cellIterator.MoveNext()) { Vector3I currentDivision = cellIterator.Current; Vector3I min = currentDivision * lodSize / m_lodDivisions; Vector3I max = (currentDivision + Vector3I.One) * lodSize / m_lodDivisions; if (renderCellCoord.IsInsideInclusive(ref min, ref max)) { break; } } Debug.Assert(cellIterator.IsValid(), "Valid division index not found!"); Vector3I foundCell = cellIterator.Current; divideIndex = GetDivideIndexFromMergeCell(ref foundCell); } return(divideIndex); }
private void storage_RangeChangedPlanet(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged) { ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged"); Vector3I minSector = minChanged / PHYSICS_SECTOR_SIZE_METERS; Vector3I maxSector = maxChanged / PHYSICS_SECTOR_SIZE_METERS; MyVoxelPhysics voxelMap; if (m_physicsShapes != null) { for (var it = new Vector3I_RangeIterator(ref minSector, ref maxSector); it.IsValid(); it.MoveNext()) { if (m_physicsShapes.TryGetValue(it.Current, out voxelMap)) { if (voxelMap != null) { voxelMap.OnStorageChanged(minChanged, maxChanged, dataChanged); } } } } if (Render is MyRenderComponentVoxelMap) { (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged); } OnRangeChanged(minChanged, maxChanged, dataChanged); ProfilerShort.End(); }
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 MyDefinitionId?VoxelMaterialAt(this MyVoxelBase voxel, Vector3D min, Vector3D grow, ref MyStorageData cache) { if (cache == null) { cache = new MyStorageData(); } var shape = new BoundingBoxD(Vector3D.Min(min, min + grow), Vector3D.Max(min, min + grow)); Vector3I voxMin; Vector3I voxMax; Vector3I voxCells; GetVoxelShapeDimensions(voxel, shape, out voxMin, out voxMax, out voxCells); Vector3I_RangeIterator cellsItr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref voxCells); while (cellsItr.IsValid()) { Vector3I cellMinCorner; Vector3I cellMaxCorner; GetCellCorners(ref voxMin, ref voxMax, ref cellsItr, out cellMinCorner, out cellMaxCorner); Vector3I rangeMin = cellMinCorner - 1; Vector3I rangeMax = cellMaxCorner + 1; voxel.Storage.ClampVoxelCoord(ref rangeMin); voxel.Storage.ClampVoxelCoord(ref rangeMax); cache.Resize(rangeMin, rangeMax); voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Material, 0, rangeMin, rangeMax); var mortonCode = -1; var maxMortonCode = cache.Size3D.Size; while (++mortonCode < maxMortonCode) { Vector3I pos; MyMortonCode3D.Decode(mortonCode, out pos); var content = cache.Content(ref pos); if (content <= MyVoxelConstants.VOXEL_CONTENT_EMPTY) { continue; } var material = cache.Material(ref pos); var def = MyDefinitionManager.Static.GetVoxelMaterialDefinition(material); if (def != null) { return(def.Id); } } cellsItr.MoveNext(); } return(null); }
public void PrefetchShapeOnRay(ref LineD ray) { Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.From, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.To, out maxCorner); minCorner /= PHYSICS_SECTOR_SIZE_METERS; maxCorner /= PHYSICS_SECTOR_SIZE_METERS; for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { if (m_physicsShapes.ContainsKey(it.Current)) { m_physicsShapes[it.Current].PrefetchShapeOnRay(ref ray); } } }
private void GeneratePhysicalShapeForBox(ref Vector3I increment, ref BoundingBoxD shapeBox) { if (!shapeBox.Intersects(PositionComp.WorldAABB)) { return; } Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Max, out maxCorner); minCorner /= PHYSICS_SECTOR_SIZE_METERS; maxCorner /= PHYSICS_SECTOR_SIZE_METERS; for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { ProfilerShort.Begin("Myplanet::create physics shape"); CreateVoxelPhysics(ref increment, ref it); ProfilerShort.End(); } }
private bool FindFirstAcceptableEntry() { while (true) { while (m_storageIndex != -1) { Entry current = m_parent.m_storage[m_storageIndex]; if ((current.Point - m_point).LengthSquared() < m_distSq) { return(true); } m_previousIndex = m_storageIndex; m_storageIndex = current.NextEntry; } m_rangeIterator.MoveNext(); if (!FindNextNonemptyBin()) { return(false); } } }
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 override IEnumerable <ProceduralObject> Generate(BoundingSphereD include, BoundingSphereD?exclude) { var root = Vector3D.Transform(include.Center, m_invTransform); var excludeRoot = exclude.HasValue ? Vector3D.Transform(exclude.Value.Center, m_invTransform) : default(Vector3D); var minLocal = root - include.Radius; var maxLocal = root + include.Radius; minLocal = Vector3D.Max(minLocal, Shape.RelevantArea.Min); maxLocal = Vector3D.Min(maxLocal, Shape.RelevantArea.Max); for (var i = 0; i < m_layers.Length; i++) { var layer = m_layers[i]; var includePaddedSquared = include.Radius + layer.AsteroidSpacing * 2; includePaddedSquared *= includePaddedSquared; var excludePaddedSquared = exclude.HasValue ? exclude.Value.Radius - layer.AsteroidSpacing * 2 : 0; excludePaddedSquared *= excludePaddedSquared; var minPos = Vector3I.Floor(minLocal / layer.AsteroidSpacing); var maxPos = Vector3I.Ceiling(maxLocal / layer.AsteroidSpacing); for (var itr = new Vector3I_RangeIterator(ref minPos, ref maxPos); itr.IsValid(); itr.MoveNext()) { var seed = new Vector4I(itr.Current.X, itr.Current.Y, itr.Current.Z, i); var localPos = ((Vector3D)itr.Current + 0.5) * layer.AsteroidSpacing; // Very quick, include/exclude. if (Vector3D.DistanceSquared(root, localPos) > includePaddedSquared) { continue; } if (exclude.HasValue && Vector3D.DistanceSquared(excludeRoot, localPos) < excludePaddedSquared) { continue; } var localWeight = Shape.Weight(localPos) + layer.UsableRegion - 1; if (1 - layer.AsteroidDensity > localWeight) { continue; } var densityNoise = Math.Abs(m_noise.GetValue(localPos + Math.PI)) * localWeight; if (1 - layer.AsteroidDensity > densityNoise) { continue; } localPos.X += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing; localPos.Y += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing; localPos.Z += 0.45 * m_noise.GetValue(localPos) * layer.AsteroidSpacing; localPos.X += 0.35 * Shape.WarpSize.X * m_noiseWarp.GetValue(localPos); localPos.Y += 0.35 * Shape.WarpSize.Y * m_noiseWarp.GetValue(localPos); localPos.Z += 0.05 * Shape.WarpSize.Z * m_noiseWarp.GetValue(localPos); var worldPos = Vector3D.Transform(localPos, m_transform); ProceduralAsteroid procAst; if (!m_asteroids.TryGetValue(seed, out procAst)) { var size = m_noise.GetValue(worldPos) * (layer.AsteroidMaxSize - layer.AsteroidMinSize) + layer.AsteroidMinSize; m_asteroids[seed] = procAst = new ProceduralAsteroid(this, seed, worldPos, size, m_layers[i]); } procAst.SpawnIfNeeded((procAst.m_boundingBox.Center - include.Center).LengthSquared()); yield return(procAst); } } }
private void ComputeBlockMap(MyObjectBuilder_CubeGrid primaryGrid, IEnumerable <MyObjectBuilder_CubeGrid> allGrids, BlockSetInfo info) { m_blocks.Clear(); info.BlockCountByType.Clear(); info.ComponentCost.Clear(); info.PowerConsumptionByGroup.Clear(); BoundingBox = new BoundingBox((Vector3I)primaryGrid.CubeBlocks[0].Min, (Vector3I)primaryGrid.CubeBlocks[0].Min); foreach (var grid in allGrids) { foreach (var block in grid.CubeBlocks) { var blockID = block.GetId(); var def = MyDefinitionManager.Static.GetCubeBlockDefinition(blockID); if (grid == primaryGrid) { Vector3I blockMin = block.Min; Vector3I blockMax; BlockTransformations.ComputeBlockMax(block, ref def, out blockMax); BoundingBox = BoundingBox.Include(blockMin); BoundingBox = BoundingBox.Include(blockMax); for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext()) { m_blocks[rangeItr.Current] = block; } } if (def == null) { if (m_erroredDefinitionIds.Add(blockID)) { Logger.Error("Failed to find definition for block {0}", blockID); } continue; } info.BlockCountByType.AddValue(def.Id, 1); foreach (var c in def.Components) { info.ComponentCost.AddValue(c.Definition, c.Count); } var powerUsage = PowerUtilities.MaxPowerConsumption(def); // if it is off, ignore it. if (Math.Abs(powerUsage.Consumption) > 1e-8 && ((block as MyObjectBuilder_FunctionalBlock)?.Enabled ?? true)) { info.PowerConsumptionByGroup.AddValue(powerUsage.ResourceGroup, powerUsage.Consumption); } } } }
private void ExecuteQuery() { try { var shape = _component._cachedRegion; var worldMin = shape.Center - shape.Radius; var worldMax = shape.Center + shape.Radius; Vector3I voxMin, voxMax; MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMin, out voxMin); MyVoxelCoordSystems.WorldPositionToVoxelCoord(_vox.PositionLeftBottomCorner, ref worldMax, out voxMax); { var tmp = Vector3I.Max(voxMin, voxMax); voxMin = Vector3I.Min(voxMin, voxMax); voxMax = tmp; } { voxMin = voxMin >> _component.Definition.LevelOfDetail; voxMax = (voxMax >> _component.Definition.LevelOfDetail) + 1; } _storage.Resize(voxMin, voxMax); // ReSharper disable once RedundantCast ((IMyStorage)_vox.Storage).ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, _component.Definition.LevelOfDetail, in voxMin, in voxMax); for (var i = 0; i < _countsWorking.Length; i++) { _countsWorking[i] = 0; } for (var itr = new Vector3I_RangeIterator(ref voxMin, ref voxMax); itr.IsValid(); itr.MoveNext()) { var local = itr.Current; var localRoot = local << _component.Definition.LevelOfDetail; Vector3D box; MyVoxelCoordSystems.VoxelCoordToWorldPosition(_vox.PositionLeftBottomCorner, ref localRoot, out box); if (!shape.Intersects(new BoundingBoxD(box, box + (1 << _component.Definition.LevelOfDetail)))) { continue; } var stor = local - voxMin; var idx = _storage.ComputeLinear(ref stor); var content = _storage.Content(idx); if (content == 0) { continue; } if (_component.Definition.Mode == VoxelPowerCountMode.Surface) { if (content == byte.MaxValue) { continue; } content = 1; } _countsWorking[_storage.Material(idx)] += content; } { var tmp = _countsWorking; _countsWorking = Counts; Counts = tmp; } } finally { _currentlyExecuting = false; _component.QueryFinishedAsync(); } }
private float GetDensity(ref Vector3D voxelCoord, int iterations) { // ReSharper disable once ImpureMethodCallOnReadonlyValueField if (Box.Contains(voxelCoord) == ContainmentType.Disjoint) { return(0f); } var inflatedBox = new BoundingBoxD(voxelCoord - 0.5f, voxelCoord + 0.5f); var queryBox = new BoundingBoxD(inflatedBox.Min - 0.1f, inflatedBox.Max + 0.1f + QueryDir * 1000); { var hits = 0; foreach (var k in _tris) { if (!inflatedBox.IntersectsTriangle(k.Origin, k.Origin + k.Edge1, k.Origin + k.Edge2)) { continue; } hits++; break; } if (hits == 0) { return(IsInside(voxelCoord) ? 1 : 0); } } List <int> tmp; if (!_stackBorrow.TryPop(out tmp)) { tmp = new List <int>(); } else { tmp.Clear(); } QueryTriangles(queryBox, tmp); var max = new Vector3I(iterations, iterations, iterations); var hit = 0; for (var itr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); itr.IsValid(); itr.MoveNext()) { var sample = inflatedBox.Min + inflatedBox.Extents * itr.Current / iterations; if (IsInsideHelper(sample, tmp)) { hit++; } } _stackBorrow.Push(tmp); return(hit / (float)((iterations + 1) * (iterations + 1) * (iterations + 1))); }
private unsafe void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary <Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList) { Vector3I vectori3; Vector3I vectori4; bool flag = cache != null; if (flag) { this.CheckCacheValidity(); } Vector3D *vectordPtr1 = (Vector3D *)ref obb.HalfExtent; vectordPtr1[0] += new Vector3D((double)border, 0.0, (double)border); BoundingBoxD aABB = obb.GetAABB(); int num = (int)Math.Round((double)(aABB.HalfExtents.Max() * 2.0)); BoundingBoxD *xdPtr1 = (BoundingBoxD *)ref aABB; xdPtr1 = (BoundingBoxD *)new BoundingBoxD(aABB.Min, aABB.Min + num); ((BoundingBoxD *)ref aABB).Translate(obb.Center - aABB.Center); bbList.Add(new BoundingBoxD(aABB.Min, aABB.Max)); aABB = aABB.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled); aABB.Translate(voxelBase.SizeInMetresHalf); Vector3I voxelCoord = Vector3I.Round(aABB.Min); Vector3I vectori2 = (Vector3I)(voxelCoord + num); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref voxelCoord, out vectori3); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref vectori2, out vectori4); MyOrientedBoundingBoxD xd2 = obb; xd2.Transform(voxelBase.PositionComp.WorldMatrixInvScaled); Vector3D *vectordPtr2 = (Vector3D *)ref xd2.Center; vectordPtr2[0] += voxelBase.SizeInMetresHalf; Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori3, ref vectori4); MyCellCoord coord = new MyCellCoord { Lod = 0 }; int num2 = 0; Vector3 offset = (Vector3)(originPosition - voxelBase.PositionLeftBottomCorner); Vector3 up = -Vector3.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition)); Matrix rotation = Matrix.CreateFromQuaternion(Quaternion.Inverse(Quaternion.CreateFromForwardUp(Vector3.CalculatePerpendicularVector(up), up))); Matrix orientation = (Matrix)voxelBase.PositionComp.WorldMatrix.GetOrientation(); while (iterator.IsValid()) { BoundingBox box; MyIsoMesh mesh; if (flag && cache.TryGetValue(iterator.Current, out mesh)) { if (mesh != null) { this.AddMeshTriangles(mesh, offset, rotation, orientation); } iterator.MoveNext(); continue; } coord.CoordInLod = iterator.Current; MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out box); if (!xd2.Intersects(ref box)) { num2++; iterator.MoveNext(); } else { BoundingBoxD item = new BoundingBoxD(box.Min, box.Max).Translate(-voxelBase.SizeInMetresHalf); bbList.Add(item); Vector3I lodVoxelMin = (coord.CoordInLod * 8) - 1; MyIsoMesh mesh2 = MyPrecalcComponent.IsoMesher.Precalc(storage, 0, lodVoxelMin, (Vector3I)(((lodVoxelMin + 8) + 1) + 1), MyStorageDataTypeFlags.Content, 0); if (flag) { cache[iterator.Current] = mesh2; } if (mesh2 != null) { this.AddMeshTriangles(mesh2, offset, rotation, orientation); } iterator.MoveNext(); } } }
public static bool DoGrading( IReadOnlyList <IRailGradeComponent> components, Vector3D target, float radius, uint availableForDeposit, uint availableForExcavate, uint[] excavatedByMaterial, byte materialToDeposit, out uint totalDeposited, out uint totalExcavated, bool testDynamic, out bool triedToChange, out bool intersectedDynamic) { try { var voxelRadius = (int)Math.Ceiling(radius); { _dynamicEntities.Clear(); _workingVoxels.Clear(); var sphere = new BoundingSphereD(target, voxelRadius + 2); var tmp = MyEntities.GetEntitiesInSphere(ref sphere); using (tmp.GetClearToken()) foreach (var e in tmp) { if (e is MyVoxelBase vox) { _workingVoxels.Add(vox); } if (e.Physics != null && !e.Physics.IsStatic) { _dynamicEntities.Add(e); } } } totalDeposited = 0; totalExcavated = 0; triedToChange = false; intersectedDynamic = false; var fill = new IGradeShape[components.Count]; var excavate = new IGradeShape[components.Count]; for (var i = 0; i < components.Count; i++) { components[i].Unblit(out fill[i], out excavate[i]); } var voxel = MyGamePruningStructureSandbox.GetClosestPlanet(target)?.RootVoxel; if (voxel == null) { return(false); } Vector3I center; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref target, out center); var voxMin = center - voxelRadius - 1; var voxMax = center + voxelRadius + 1; _storage.Resize(voxMin, voxMax); voxel.Storage.ReadRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, 0, voxMin, voxMax); var changed = false; #region Mutate for (var i = 0; i <= voxelRadius && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0); i++) { for (var e = new ShellEnumerator(center - i, center + i); e.MoveNext() && (!triedToChange || availableForExcavate > 0 || availableForDeposit > 0);) { var vCoord = e.Current; var dataCoord = e.Current - voxMin; Vector3D worldCoord; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref vCoord, out worldCoord); var cval = _storage.Get(MyStorageDataTypeEnum.Content, ref dataCoord); byte?excavationDensity = null; if (cval > 0 && (!triedToChange || availableForExcavate > 0)) { float density = 0; foreach (var c in excavate.Where(x => x != null)) { density = Math.Max(density, c.GetDensity(ref worldCoord)); } if (density > 0) { excavationDensity = (byte)((1 - density) * byte.MaxValue); } } byte?fillDensity = null; if (cval < byte.MaxValue && (!triedToChange || availableForDeposit > 0)) { float density = 0; foreach (var c in fill.Where(x => x != null)) { density = Math.Max(density, c.GetDensity(ref worldCoord)); } if (density > 0) { fillDensity = (byte)(density * byte.MaxValue); } } if ((!fillDensity.HasValue || cval >= fillDensity.Value) && (!excavationDensity.HasValue || cval <= excavationDensity.Value)) { continue; } if (excavationDensity.HasValue && excavationDensity.Value < cval) { triedToChange = true; var toExtract = (uint)Math.Min(availableForExcavate, cval - excavationDensity.Value); if (toExtract > 0) { var mid = _storage.Get(MyStorageDataTypeEnum.Material, ref dataCoord); if (excavatedByMaterial != null && mid < excavatedByMaterial.Length) { excavatedByMaterial[mid] += toExtract; } DisableFarming(worldCoord); _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval - toExtract)); totalExcavated += toExtract; availableForExcavate -= toExtract; changed = true; } continue; } if (!fillDensity.HasValue || fillDensity.Value <= cval) { continue; } triedToChange = true; var toFill = Math.Min(availableForDeposit, fillDensity.Value - cval); if (toFill <= 0) { continue; } // would this deposit in midair? { var test = worldCoord; test += 2 * Vector3D.Normalize( MyGravityProviderSystem.CalculateNaturalGravityInPoint(worldCoord)); Vector3I vtest; MyVoxelCoordSystems.WorldPositionToVoxelCoord(voxel.PositionLeftBottomCorner, ref test, out vtest); vtest = Vector3I.Clamp(vtest, voxMin, voxMax) - voxMin; if (vtest != vCoord && _storage.Get(MyStorageDataTypeEnum.Content, ref vtest) == 0) { continue; } } // would it touch something dynamic? if (testDynamic) { var box = new BoundingBoxD(worldCoord - 0.25, worldCoord + 0.25); var bad = false; foreach (var k in _dynamicEntities) { if (k.PositionComp.WorldAABB.Contains(box) == ContainmentType.Disjoint) { continue; } var obb = new OrientedBoundingBoxD(k.PositionComp.LocalAABB, k.WorldMatrix); if (!obb.Intersects(ref box)) { continue; } bad = true; break; } if (bad) { intersectedDynamic = true; continue; } } changed = true; DisableFarming(worldCoord); availableForDeposit = (uint)(availableForDeposit - toFill); totalDeposited += (uint)toFill; _storage.Set(MyStorageDataTypeEnum.Content, ref dataCoord, (byte)(cval + toFill)); if (fillDensity.Value <= cval * 1.25f) { continue; } var t = -Vector3I.One; for (var itrContent = new Vector3I_RangeIterator(ref t, ref Vector3I.One); itrContent.IsValid(); itrContent.MoveNext()) { var tpos = dataCoord + itrContent.Current; // var state = _storage.Get(MyStorageDataTypeEnum.Content, ref tpos); // if (itrContent.Current == Vector3I.Zero || state == 0) _storage.Set(MyStorageDataTypeEnum.Material, ref tpos, materialToDeposit); } } } #endregion Mutate if (changed) { voxel.Storage.WriteRange(_storage, MyStorageDataTypeFlags.ContentAndMaterial, voxMin, voxMax); } return(changed); } finally { _dynamicEntities.Clear(); _workingVoxels.Clear(); } }
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 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(); } } } } } }
private int GetDivideIndex(ref Vector3I renderCellCoord) { // TODO: Optimize int divideIndex = 0; if (m_lodDivisions > 1) { BoundingBoxD lodAabb = m_boundingBoxes.GetAabb(m_boundingBoxes.GetRoot()); Vector3I test = Vector3I.Round(lodAabb.Size / (double)MyVoxelCoordSystems.RenderCellSizeInMeters(m_lod)); //Vector3I lodSizeMinusOne = m_parentClipmap.LodSizeMinusOne(m_lod); //Vector3I lodSize = lodSizeMinusOne + Vector3I.One; Vector3I lodSize = test; Vector3I lodSizeMinusOne = test - 1; Vector3I lodDivision = Vector3I.One * (m_lodDivisions - 1); var cellIterator = new Vector3I_RangeIterator(ref Vector3I.Zero, ref lodDivision); for (; cellIterator.IsValid(); cellIterator.MoveNext()) { Vector3I currentDivision = cellIterator.Current; Vector3I min = currentDivision * lodSize / m_lodDivisions; Vector3I max = (currentDivision + Vector3I.One) * lodSize / m_lodDivisions; if (renderCellCoord.IsInsideInclusive(ref min, ref max)) break; } Debug.Assert(cellIterator.IsValid(), "Valid division index not found!"); Vector3I foundCell = cellIterator.Current; divideIndex = GetDivideIndexFromMergeCell(ref foundCell); } return divideIndex; }
public void Apply(IReadOnlyList <IMyCubeGrid> group) { var totalAABB = BoundingBoxD.CreateInvalid(); // ReSharper disable once LoopCanBeConvertedToQuery foreach (var grid in group) { totalAABB = totalAABB.Include(grid.WorldAABB); } var totalSphere = new BoundingSphereD(totalAABB.Center, totalAABB.HalfExtents.Length()); foreach (var impact in m_impactDirectionRadius) { var speed = impact.Velocity.Length(); var direction = (Vector3D)impact.Velocity / speed; Vector3D start, end; { var rayOffset = totalAABB.HalfExtents * 0.8 * (Vector3D)impact.Shift; // mag2(rayOffset + l*direction) == radius*radius // (rayOffset + l*direction)*(rayOffset + l*direction) // mag2(rayOffset) + 2*l*dot(direction, rayOffset) + l*l*mag2(direction) // mag2(rayOffset) - (radius*radius) + 2*l*dot(direction, rayOffset) + l*l == 0 var c = rayOffset.LengthSquared() - totalSphere.Radius * totalSphere.Radius; var b = 2 * Vector3D.Dot(direction, rayOffset); const float a = 1; var rad = b * b - 4 * a * c; if (rad <= double.Epsilon) { continue; } var lLow = (-b - Math.Sqrt(rad)) / (2 * a); var lHigh = (-b + Math.Sqrt(rad)) / (2 * a); start = totalSphere.Center + rayOffset + lLow * direction; end = totalSphere.Center + rayOffset + lHigh * direction; } var ray = new RayD(start, direction); var bestHitLocation = default(Vector3D); var bestHitDistanceSquared = double.MaxValue; foreach (var grid in group) { if (!grid.WorldAABB.Intersects(ray).HasValue) { continue; } var block = grid.RayCastBlocks(start, end); if (!block.HasValue) { continue; } var world = Vector3D.Transform(block.Value * grid.GridSize, grid.WorldMatrix); var distance = Vector3D.DistanceSquared(world, start); if (distance > bestHitDistanceSquared) { continue; } bestHitDistanceSquared = distance; bestHitLocation = world; } if (bestHitDistanceSquared > double.MaxValue / 2) { continue; } var impactSphere = new BoundingSphereD(bestHitLocation, impact.Radius); var localSphere = new BoundingSphereD(); var damageAmount = impact.Mass * speed * speed * (4.0 / 3.0) * Math.PI; var damageTotals = new Dictionary <IMySlimBlock, double>(); foreach (var grid in group) { if (grid.WorldAABB.Intersects(impactSphere)) { // compute local sphere. localSphere.Center = Vector3D.Transform(impactSphere.Center, grid.WorldMatrixNormalizedInv) / grid.GridSize; localSphere.Radius = impactSphere.Radius / grid.GridSize; var min = Vector3I.Max(Vector3I.Floor(localSphere.Center - localSphere.Radius), grid.Min); var max = Vector3I.Min(Vector3I.Ceiling(localSphere.Center + localSphere.Radius), grid.Max); for (var itr = new Vector3I_RangeIterator(ref min, ref max); itr.IsValid(); itr.MoveNext()) { if (localSphere.Contains(itr.Current) == ContainmentType.Disjoint) { continue; } var block = grid.GetCubeBlock(itr.Current); if (block == null) { continue; } var distanceFactor = 1 - ((Vector3D)itr.Current - localSphere.Center).LengthSquared() / (localSphere.Radius * localSphere.Radius); var blockDamage = damageAmount * distanceFactor * ((block.BlockDefinition as MyCubeBlockDefinition)?.DeformationRatio ?? 1); damageTotals.AddValue(block, blockDamage); } } } // No idea what shape key should be. Logger.Debug("Apply damage to {0} blocks", damageTotals.Count); var hitInfo = new MyHitInfo() { Normal = direction, Position = impactSphere.Center, Velocity = impact.Velocity, ShapeKey = 0 }; foreach (var kv in damageTotals) { kv.Key.DoDamage((float)kv.Value, MyDamageType.Explosion, true, hitInfo); } } }
private void FindForestInitialCandidate() { BoundingBoxD groundBox = m_ground.PositionComp.WorldAABB; Vector3D boxSize = groundBox.Size; boxSize *= 0.1f; groundBox.Inflate(-boxSize); MyBBSetSampler sampler = new MyBBSetSampler(groundBox.Min, groundBox.Max); bool posIsValid = true; Vector3D worldPos = default(Vector3D); int counter = 0; do { // find random position for starting worldPos = sampler.Sample(); var worldPosProjected = worldPos; worldPosProjected.Y = 0.5f; posIsValid = true; counter++; Vector3D areaCheck = new Vector3D(20, 20, 20); foreach (var enqueued in m_initialForestLocations) { // only interested in XZ plane BoundingBoxD tmp = new BoundingBoxD(enqueued - areaCheck, enqueued + areaCheck); tmp.Min.Y = 0; tmp.Max.Y = 1; if (tmp.Contains(worldPosProjected) == ContainmentType.Contains) { posIsValid = false; break; } } } while (!posIsValid && counter != 10); if (!posIsValid) { // could not find any position return; } var lineStart = new Vector3D(worldPos.X, groundBox.Max.Y, worldPos.Z); var lineEnd = new Vector3D(worldPos.X, groundBox.Min.Y, worldPos.Z); LineD line = new LineD(lineStart, lineEnd); VRage.Game.Models.MyIntersectionResultLineTriangleEx? result = null; var correctGroundDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition("Grass"); var materialId = correctGroundDefinition.Index; if (m_ground.GetIntersectionWithLine(ref line, out result, VRage.Game.Components.IntersectionFlags.DIRECT_TRIANGLES)) { Vector3D intersectionPoint = result.Value.IntersectionPointInWorldSpace; Vector3I voxelCoord, minRead, maxRead; MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_ground.PositionLeftBottomCorner, ref intersectionPoint, out voxelCoord); minRead = voxelCoord - Vector3I.One; maxRead = voxelCoord + Vector3I.One; m_ground.Storage.ReadRange(m_voxelCache, MyStorageDataTypeFlags.Material, 0, ref minRead, ref maxRead); var minLocal = Vector3I.Zero; var maxLocal = Vector3I.One * 2; var it = new Vector3I_RangeIterator(ref minLocal, ref maxLocal); while (it.IsValid()) { var vec = it.Current; var material = m_voxelCache.Material(ref vec); if (material == materialId) { // found a location var desired = voxelCoord - Vector3I.One + vec; Vector3D desiredWorldPosition = default(Vector3D); MyVoxelCoordSystems.VoxelCoordToWorldPosition(m_ground.PositionLeftBottomCorner, ref desired, out desiredWorldPosition); m_initialForestLocations.Enqueue(desiredWorldPosition); break; } it.MoveNext(); } } }
public float GetDensity(ref Vector3D worldCoord) { List <MeshGradeShape> maskedBorrow; using (PoolManager.Get(out maskedBorrow)) { const int iterations = MeshGradeShape.DefaultDensityIterations; var intersectsSurface = false; foreach (var c in _components) { if (c.IntersectsSurface(ref worldCoord)) { intersectsSurface = true; maskedBorrow.Add(c); } else if (c.IsInside(worldCoord)) { return(1f); } } if (!intersectsSurface) { return(0f); } List <List <int> > borrowed; using (PoolManager.Get(out borrowed)) { foreach (var k in borrowed) { k.Clear(); } while (borrowed.Count < maskedBorrow.Count) { borrowed.Add(new List <int>()); } var inflatedBox = new BoundingBoxD(worldCoord - 0.5f, worldCoord + 0.5f); var queryBox = new BoundingBoxD(inflatedBox.Min - 0.1f, inflatedBox.Max + 0.1f + MeshGradeShape.QueryDir * 1000); for (var i = 0; i < maskedBorrow.Count; i++) { maskedBorrow[i].QueryTriangles(queryBox, borrowed[i]); } var max = new Vector3I(iterations, iterations, iterations); var hit = 0; for (var itr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref max); itr.IsValid(); itr.MoveNext()) { var sample = inflatedBox.Min + inflatedBox.Extents * itr.Current / iterations; for (var i = 0; i < maskedBorrow.Count; i++) { if (maskedBorrow[i].IsInsideHelper(sample, borrowed[i])) { hit++; break; } } } return(hit / (float)((iterations + 1) * (iterations + 1) * (iterations + 1))); } } }
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(OperationType.Fill, voxelMap, shape); return retValue; }
public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape) { if(MySession.Static.EnableVoxelDestruction == false) { return 0; } 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; } if (changedVolumeAmount > 0) OnVoxelChanged(OperationType.Cut, voxelMap, shape); return changedVolumeAmount; }
private void storage_RangeChangedPlanet(Vector3I minChanged, Vector3I maxChanged, MyStorageDataTypeFlags dataChanged) { ProfilerShort.Begin("MyVoxelMap::storage_RangeChanged"); Vector3I minSector = minChanged / PHYSICS_SECTOR_SIZE_METERS; Vector3I maxSector = maxChanged / PHYSICS_SECTOR_SIZE_METERS; MyVoxelPhysics voxelMap; if (m_physicsShapes != null) { for (var it = new Vector3I_RangeIterator(ref minSector, ref maxSector); it.IsValid(); it.MoveNext()) { if (m_physicsShapes.TryGetValue(it.Current, out voxelMap)) { if (voxelMap != null) voxelMap.OnStorageChanged(minChanged, maxChanged, dataChanged); } } } if (Render is MyRenderComponentVoxelMap) { (Render as MyRenderComponentVoxelMap).InvalidateRange(minChanged, maxChanged); } OnRangeChanged(minChanged, maxChanged, dataChanged); ProfilerShort.End(); }
public static float Laze(this MyVoxelBase voxel, BoundingSphereD area, float amount, ref MyStorageData cache) { if (cache == null) { cache = new MyStorageData(); } Vector3I voxMin; Vector3I voxMax; Vector3I voxCells; var shape = new BoundingBoxD(area.Center - area.Radius, area.Center + area.Radius); GetVoxelShapeDimensions(voxel, shape, out voxMin, out voxMax, out voxCells); ulong totalRemoved = 0uL; Vector3I_RangeIterator cellsItr = new Vector3I_RangeIterator(ref Vector3I.Zero, ref voxCells); while (cellsItr.IsValid()) { Vector3I cellMinCorner; Vector3I cellMaxCorner; GetCellCorners(ref voxMin, ref voxMax, ref cellsItr, out cellMinCorner, out cellMaxCorner); Vector3I rangeMin = cellMinCorner - 1; Vector3I rangeMax = cellMaxCorner + 1; voxel.Storage.ClampVoxelCoord(ref rangeMin); voxel.Storage.ClampVoxelCoord(ref rangeMax); ulong removed = 0uL; cache.Resize(rangeMin, rangeMax); voxel.Storage.ReadRange(cache, MyStorageDataTypeFlags.Content, 0, rangeMin, rangeMax); Vector3I_RangeIterator cellVoxItr = new Vector3I_RangeIterator(ref cellMinCorner, ref cellMaxCorner); while (cellVoxItr.IsValid()) { Vector3I cellVoxIdx = cellVoxItr.Current - rangeMin; byte b = cache.Content(ref cellVoxIdx); if (b != 0) { Vector3I current = cellVoxItr.Current; Vector3D worldPos; MyVoxelCoordSystems.VoxelCoordToWorldPosition(voxel.PositionLeftBottomCorner, ref current, out worldPos); var d = (worldPos - area.Center).Length() / area.Radius; if (d < 1) { int nVal = Math.Max(0, (int)(b - 255f * amount * (1 - d))); cache.Content(ref cellVoxIdx, (byte)nVal); removed += b - (ulong)nVal; } } cellVoxItr.MoveNext(); } if (removed > 0uL) { voxel.Storage.WriteRange(cache, MyStorageDataTypeFlags.Content, rangeMin, rangeMax); } totalRemoved += removed; cellsItr.MoveNext(); } return(totalRemoved / 255f); }
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); } }
private void GeneratePhysicalShapeForBox(ref Vector3I increment, ref BoundingBoxD shapeBox) { if (!shapeBox.Intersects(PositionComp.WorldAABB)) return; Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Min, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref shapeBox.Max, out maxCorner); minCorner /= PHYSICS_SECTOR_SIZE_METERS; maxCorner /= PHYSICS_SECTOR_SIZE_METERS; for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { ProfilerShort.Begin("Myplanet::create physics shape"); CreateVoxelPhysics(ref increment, ref it); ProfilerShort.End(); } }
private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary<Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List<BoundingBoxD> bbList) { bool useCache = cache != null; if (useCache) CheckCacheValidity(); obb.HalfExtent += new Vector3D(border, 0, border); BoundingBoxD bb = obb.GetAABB(); int aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2); bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide); bb.Translate(obb.Center - bb.Center); // For debug bbList.Add(new BoundingBoxD(bb.Min, bb.Max)); bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled); bb.Translate(voxelBase.SizeInMetresHalf); Vector3I min = Vector3I.Round(bb.Min); Vector3I max = min + aabbSideSide; Vector3I geomMin, geomMax; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax); var cullBox = obb; cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled); cullBox.Center += voxelBase.SizeInMetresHalf; ProfilerShort.Begin("WOOOORK"); Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref geomMin, ref geomMax); MyCellCoord coord = new MyCellCoord(); BoundingBox localAabb; coord.Lod = NAVMESH_LOD; int hits = 0; MyIsoMesh gMesh; Vector3 offset = originPosition - voxelBase.PositionLeftBottomCorner; // Calculate rotation Vector3 gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition)); Vector3 forwardVector = Vector3.CalculatePerpendicularVector(gravityVector); Quaternion quaternion = Quaternion.CreateFromForwardUp(forwardVector, gravityVector); Matrix rotation = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion)); Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation(); while (it.IsValid()) { ProfilerShort.Begin("ITERATOR"); if (useCache && cache.TryGetValue(it.Current, out gMesh)) { if (gMesh != null) { AddMeshTriangles(gMesh, offset, rotation, ownRotation); } it.MoveNext(); ProfilerShort.End(); continue; } coord.CoordInLod = it.Current; MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb); if (!cullBox.Intersects(ref localAabb)) { hits++; it.MoveNext(); ProfilerShort.End(); continue; } ProfilerShort.End(); var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf); bbList.Add(debugBB); ProfilerShort.Begin("Mesh Calc"); var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1; var voxelEnd = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1 + 1 // overlap to neighbor so geometry is stitched together within same LOD + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels) var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true); ProfilerShort.End(); if (useCache) cache[it.Current] = generatedMesh; if (generatedMesh != null) { ProfilerShort.Begin("Mesh NOT NULL"); AddMeshTriangles(generatedMesh, offset, rotation, ownRotation); ProfilerShort.End(); } it.MoveNext(); } ProfilerShort.End(); }
public void PrefetchShapeOnRay(ref LineD ray) { Vector3I minCorner, maxCorner; MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.From, out minCorner); MyVoxelCoordSystems.WorldPositionToVoxelCoord(PositionLeftBottomCorner, ref ray.To, out maxCorner); minCorner /= PHYSICS_SECTOR_SIZE_METERS; maxCorner /= PHYSICS_SECTOR_SIZE_METERS; for (var it = new Vector3I_RangeIterator(ref minCorner, ref maxCorner); it.IsValid(); it.MoveNext()) { if (m_physicsShapes.ContainsKey(it.Current)) { m_physicsShapes[it.Current].PrefetchShapeOnRay(ref ray); } } }
private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary <Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList) { bool useCache = cache != null; if (useCache) { CheckCacheValidity(); } obb.HalfExtent += new Vector3D(border, 0, border); BoundingBoxD bb = obb.GetAABB(); int aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2); bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide); bb.Translate(obb.Center - bb.Center); // For debug bbList.Add(new BoundingBoxD(bb.Min, bb.Max)); bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled); bb.Translate(voxelBase.SizeInMetresHalf); Vector3I min = Vector3I.Round(bb.Min); Vector3I max = min + aabbSideSide; Vector3I geomMin, geomMax; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax); var cullBox = obb; cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled); cullBox.Center += voxelBase.SizeInMetresHalf; ProfilerShort.Begin("WOOOORK"); Vector3I_RangeIterator it = new Vector3I_RangeIterator(ref geomMin, ref geomMax); MyCellCoord coord = new MyCellCoord(); BoundingBox localAabb; coord.Lod = NAVMESH_LOD; int hits = 0; MyIsoMesh gMesh; Vector3 offset = originPosition - voxelBase.PositionLeftBottomCorner; // Calculate rotation Vector3 gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition)); Vector3 forwardVector = Vector3.CalculatePerpendicularVector(gravityVector); Quaternion quaternion = Quaternion.CreateFromForwardUp(forwardVector, gravityVector); Matrix rotation = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion)); Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation(); while (it.IsValid()) { ProfilerShort.Begin("ITERATOR"); if (useCache && cache.TryGetValue(it.Current, out gMesh)) { if (gMesh != null) { AddMeshTriangles(gMesh, offset, rotation, ownRotation); } it.MoveNext(); ProfilerShort.End(); continue; } coord.CoordInLod = it.Current; MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb); if (!cullBox.Intersects(ref localAabb)) { hits++; it.MoveNext(); ProfilerShort.End(); continue; } ProfilerShort.End(); var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf); bbList.Add(debugBB); ProfilerShort.Begin("Mesh Calc"); var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1; var voxelEnd = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1 + 1 // overlap to neighbor so geometry is stitched together within same LOD + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels) var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true); ProfilerShort.End(); if (useCache) { cache[it.Current] = generatedMesh; } if (generatedMesh != null) { ProfilerShort.Begin("Mesh NOT NULL"); AddMeshTriangles(generatedMesh, offset, rotation, ownRotation); ProfilerShort.End(); } it.MoveNext(); } ProfilerShort.End(); }
private void Process(CommandFeedback feedback, IMyCubeGrid grid) { if (grid.CustomName == null || !grid.CustomName.StartsWithICase("EqProcBuild")) { return; } var ob = grid.GetObjectBuilder(true) as MyObjectBuilder_CubeGrid; if (ob == null) { return; } this.Info("Begin processing {0}", grid.CustomName); feedback?.Invoke("Processing {0}", grid.CustomName); try { var dummyDel = new List <MyTuple <MyObjectBuilder_CubeBlock, string> >(); var blockKeep = new List <MyObjectBuilder_CubeBlock>(); var blockMap = new Dictionary <Vector3I, MyObjectBuilder_CubeBlock>(Vector3I.Comparer); foreach (var block in ob.CubeBlocks) { var mount = false; foreach (var name in block.ConfigNames()) { if (!name.StartsWithICase(MountDelegated) && !name.StartsWithICase(ReservedSpaceDelegated)) { continue; } dummyDel.Add(MyTuple.Create(block, name)); mount = true; break; } if (mount) { continue; } var blockMin = (Vector3I)block.Min; Vector3I blockMax; BlockTransformations.ComputeBlockMax(block, out blockMax); for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext()) { blockMap[rangeItr.Current] = block; } blockKeep.Add(block); } this.Info("Found {0} blocks to keep, {1} block mounts to remap", blockKeep.Count, dummyDel.Count); foreach (var pair in dummyDel) { var block = pair.Item1; var useName = pair.Item2; IEnumerable <Base6Directions.Direction> dirs = Base6Directions.EnumDirections; var def = MyDefinitionManager.Static.GetCubeBlockDefinition(pair.Item1); var transform = new MatrixI(block.BlockOrientation); if (def?.MountPoints != null) { var mountDirs = new HashSet <Base6Directions.Direction>(); foreach (var mount in def.MountPoints) { mountDirs.Add(Base6Directions.GetDirection(Vector3I.TransformNormal(mount.Normal, ref transform))); } } var args = useName.Split(' '); var keepArgs = new List <string>(args.Length); foreach (var arg in args) { if (arg.StartsWithICase(PartDummyUtils.ArgumentMountDirection)) { Base6Directions.Direction dir; if (Enum.TryParse(arg.Substring(2), out dir)) { dirs = new[] { transform.GetDirection(Base6Directions.GetOppositeDirection(dir)) } } ; else { this.Error("Failed to parse direction argument \"{0}\"", arg); feedback?.Invoke("Error: Failed to parse direction argument \"{0}\"", arg); } } else { keepArgs.Add(arg); } } useName = string.Join(" ", keepArgs); MyObjectBuilder_CubeBlock outputBlock = null; var outputDir = Base6Directions.Direction.Forward; foreach (var dir in dirs) { MyObjectBuilder_CubeBlock tmp; if (!blockMap.TryGetValue(block.Min + Base6Directions.GetIntVector(dir), out tmp)) { continue; } if (tmp.ConfigNames().Any(x => x.StartsWithICase(MountDelegated))) { continue; } if (outputBlock != null) { this.Error("Multiple directions found for {0}", pair.Item2); feedback?.Invoke("Error: Multiple directions found for {0}", pair.Item2); } outputBlock = tmp; outputDir = dir; } if (outputBlock == null || !ApplyDelegate(ob, block, useName, outputBlock, outputDir)) { this.Error("Failed to find delegated mount point for {0}", pair.Item2); feedback?.Invoke("Error: Failed to find delegated mount point for {0}", pair.Item2); } } ob.CubeBlocks = blockKeep; // Grab related grids! var relatedGrids = new HashSet <IMyCubeGrid> { grid }; var scanRelated = new Queue <IMyCubeGrid>(); var relatedGridController = new Dictionary <IMyCubeGrid, IMyCubeBlock>(); scanRelated.Enqueue(grid); while (scanRelated.Count > 0) { var subGrid = scanRelated.Dequeue(); IMyCubeBlock controllerForThisGrid = null; relatedGridController.TryGetValue(subGrid, out controllerForThisGrid); subGrid.GetBlocks(null, (y) => { var x = y?.FatBlock; if (x == null) { return(false); } var childGrid = (x as IMyMechanicalConnectionBlock)?.TopGrid; if (childGrid != null && relatedGrids.Add(childGrid)) { scanRelated.Enqueue(childGrid); relatedGridController[childGrid] = x.CubeGrid == grid ? x : controllerForThisGrid; } var parentGrid = (x as IMyAttachableTopBlock)?.Base?.CubeGrid; // ReSharper disable once InvertIf if (parentGrid != null && relatedGrids.Add(parentGrid)) { scanRelated.Enqueue(parentGrid); relatedGridController[parentGrid] = x.CubeGrid == grid ? x : controllerForThisGrid; } return(false); }); } relatedGrids.Remove(grid); var removedNoController = relatedGrids.RemoveWhere(x => !relatedGridController.ContainsKey(x)); if (removedNoController > 0) { this.Error("Failed to find the mechanical connection block for all subgrids. {0} will be excluded", removedNoController); feedback?.Invoke("Error: Failed to find the mechanical connection block for all subgrids. {0} will be excluded", removedNoController); } // Need to add reserved space for subgrids so they don't overlap. So compute that. Yay! foreach (var rel in relatedGrids) { IMyCubeBlock root; if (!relatedGridController.TryGetValue(rel, out root)) { this.Error("Unable to find the mechanical connection for grid {0}", rel.CustomName); feedback?.Invoke("Error: Unable to find the mechanical connection for grid {0}", rel.CustomName); continue; } MyObjectBuilder_CubeBlock blockDest; if (blockMap.TryGetValue(root.Min, out blockDest)) { var blockLocal = (MatrixD) new MatrixI(blockDest.BlockOrientation).GetFloatMatrix(); blockLocal.Translation = (Vector3I)blockDest.Min * grid.GridSize; var blockWorld = MatrixD.Multiply(blockLocal, grid.WorldMatrix); var worldAABB = rel.WorldAABB; worldAABB = Utilities.TransformBoundingBox(worldAABB, MatrixD.Invert(blockWorld)); var gridAABB = new BoundingBoxI(Vector3I.Floor(worldAABB.Min / grid.GridSize), Vector3I.Ceiling(worldAABB.Max / grid.GridSize)); var code = $"{PartMetadata.ReservedSpacePrefix} NE:{gridAABB.Min.X}:{gridAABB.Min.Y}:{gridAABB.Min.Z} PE:{gridAABB.Max.X}:{gridAABB.Max.Y}:{gridAABB.Max.Z}"; this.Info("Added reserved space for subgrid {0}: Spec is \"{1}\"", rel.CustomName, code); if (blockDest.Name == null || blockDest.Name.Trim().Length == 0) { blockDest.Name = code; } else { blockDest.Name += PartMetadata.MultiUseSentinel + code; } } else { this.Error("Unable to find the OB for grid block {0} ({1}, {2}, {3}). Is it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z); feedback?.Invoke("Unable to the find OB for grid block {0} ({1}, {2}, {3}). Was it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z); } } var allGrids = new List <MyObjectBuilder_CubeGrid>(relatedGrids.Count + 1) { ob }; allGrids.AddRange(relatedGrids.Select(relGrid => relGrid.GetObjectBuilder(false)).OfType <MyObjectBuilder_CubeGrid>()); // Compose description: TODO I'd love if this actually worked :/ // var storage = new MyPartMetadata(); // storage.InitFromGrids(ob, allGrids); // var data = Convert.ToBase64String(MyAPIGateway.Utilities.SerializeToBinary(storage.GetObjectBuilder())); var defOut = new MyObjectBuilder_PrefabDefinition() { Id = new SerializableDefinitionId(typeof(MyObjectBuilder_PrefabDefinition), grid.CustomName), CubeGrids = allGrids.ToArray() }; var fileName = grid.CustomName + ".sbc"; this.Info("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length); feedback?.Invoke("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length); var mishMash = new MyObjectBuilder_Definitions() { Prefabs = new MyObjectBuilder_PrefabDefinition[] { defOut } }; var writer = MyAPIGateway.Utilities.WriteBinaryFileInLocalStorage(fileName, typeof(DesignTools)); var obCode = MyAPIGateway.Utilities.SerializeToXML(mishMash); obCode = obCode.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\""); writer.Write(Encoding.UTF8.GetBytes(obCode)); writer.Close(); } catch (Exception e) { this.Error("Failed to parse. Error:\n{0}", e.ToString()); } }
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); }
private static bool IntersectsInternalExpensive(ref PartFromPrefab partA, ref MatrixI transformA, ref MatrixI invTransformA, ref PartFromPrefab partB, ref MatrixI transformB, ref MatrixI invTransformB, bool testOptional) { using (partA.LockSharedUsing()) using (partB.LockSharedUsing()) { var reservedAAll = Utilities.TransformBoundingBox(partA.ReservedSpace, ref transformA); var reservedBAll = Utilities.TransformBoundingBox(partB.ReservedSpace, ref transformB); var reservedA = new List <MyTuple <ReservedSpace, BoundingBox> >(partA.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partA.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedA.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformA))); } } var reservedB = new List <MyTuple <ReservedSpace, BoundingBox> >(partB.m_reservedSpaces.Count); // ReSharper disable once LoopCanBeConvertedToQuery (preserve ref) foreach (var aabb in partB.m_reservedSpaces) { if (!aabb.IsOptional || testOptional) { reservedB.Add(MyTuple.Create(aabb, Utilities.TransformBoundingBox(aabb.Box, ref transformB))); } } // Reserved spaces intersect? if (partA.m_reservedSpaces.Count > 0 && partB.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(reservedBAll)) { if (reservedA.Any(x => reservedB.Any(y => !y.Item1.IsShared && !x.Item1.IsShared && x.Item2.Intersects(y.Item2)))) { return(true); } } var blockAAll = Utilities.TransformBoundingBox(partA.BoundingBox, ref transformA); var blockBAll = Utilities.TransformBoundingBox(partB.BoundingBox, ref transformB); // Block spaces intersect with reserved space? if (partA.m_reservedSpaces.Count > 0 && reservedAAll.Intersects(blockBAll)) { foreach (var aabb in reservedA) { var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockBAll.Min)); var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockBAll.Max)); for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext()) { if (partB.CubeExists(Vector3I.Transform(vi.Current, invTransformB))) { return(true); } } } } if (partB.m_reservedSpaces.Count > 0 && reservedBAll.Intersects(blockAAll)) { foreach (var aabb in reservedB) { var min = Vector3I.Floor(Vector3.Max(aabb.Item2.Min, blockAAll.Min)); var max = Vector3I.Ceiling(Vector3.Min(aabb.Item2.Max, blockAAll.Max)); for (var vi = new Vector3I_RangeIterator(ref min, ref max); vi.IsValid(); vi.MoveNext()) { if (partA.CubeExists(Vector3I.Transform(vi.Current, invTransformA))) { return(true); } } } } // Block space intersects with block space? if (!blockAAll.Intersects(blockBAll)) { return(false); } if (partA.m_blocks.Count < partB.m_blocks.Count) { foreach (var pos in partA.m_blocks.Keys) { if (partB.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformA), ref invTransformB))) { return(true); } } } else { foreach (var pos in partB.m_blocks.Keys) { if (partA.CubeExists(Vector3I.Transform(Vector3I.Transform(pos, ref transformB), ref invTransformA))) { return(true); } } } return(false); } }
public static ulong CutOutShape(MyVoxelBase voxelMap, MyShape shape) { if (MySession.Static.EnableVoxelDestruction == false) { return(0); } 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; } if (changedVolumeAmount > 0) { OnVoxelChanged(MyVoxelBase.OperationType.Cut, voxelMap, shape); } return(changedVolumeAmount); }
public IEnumerable <MyTuple <Vector4I, Vector4D> > TryGetSpawnIn(BoundingBoxD aabb, Func <BoundingBoxD, bool> test = null) { var rootCellsMin = Vector3I.Floor(aabb.Min / m_cubeSideMax); var rootCellsMax = Vector3I.Floor(aabb.Max / m_cubeSideMax); for (var rootCells = new Vector3I_RangeIterator(ref rootCellsMin, ref rootCellsMax); rootCells.IsValid(); rootCells.MoveNext()) { foreach (var k in GetSpawnsIn(new Vector4I(rootCells.Current, 0), aabb, test)) { yield return(k); } } }