public static bool IsInside(this IGradeShape shape, Vector3D position, float margin) { if (shape.IsInside(position)) { return(true); } if (margin < 0.01f) { return(false); } const int lenSteps = 2; const int dirSteps = 16; for (var i = lenSteps; i >= 1; i--) { for (var j = 0; j < dirSteps; j++) { if (shape.IsInside(position + (margin * i / lenSteps) * GetRandomVector3Normalized())) { return(true); } } } return(false); }
public void Unblit(out IGradeShape fillShape, out IGradeShape excavateShape) { fillShape = excavateShape = null; var def = MyDefinitionManager.Get <RailGradeComponentDefinition>(Definition); if (def == null) { return; } if (def.Support.HasValue) { var s = def.Support.Value; fillShape = CompositeGradeShape.Composite(Edges .Select(e => def.Support.Value.CreateShape(e, false)).ToArray()); } if (def.Excavate.HasValue) { var s = def.Excavate.Value; excavateShape = CompositeGradeShape.Composite(Edges .Select(e => def.Excavate.Value.CreateShape(e, true)).ToArray()); } }
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 void Unblit(out IGradeShape fillShape, out IGradeShape excavateShape) { fillShape = Support; excavateShape = Excavation; }