public static JointParameters ComputeEdgeParameters(AnnotatedNode from, AnnotatedNode to) { var result = new JointParameters(); var dirNext = to.Position - from.Position; result.Length = dirNext.Normalize(); var dotFrom = Math.Abs(Vector3.Normalize(from.Tangent).Dot((Vector3)dirNext)); var dotTo = Math.Abs(Vector3.Normalize(to.Tangent).Dot((Vector3)dirNext)); result.BendRadians = Math.Acos(Math.Min(dotFrom, dotTo)); var planet = MyGamePruningStructureSandbox.GetClosestPlanet(@from.Position); // ReSharper disable once InvertIf if (planet?.PositionComp != null) { var center = planet.PositionComp.WorldVolume.Center; var elevationA = Vector3D.Distance(from.Position, center); var elevationB = Vector3D.Distance(to.Position, center); var deltaElevation = elevationB - elevationA; var grade = deltaElevation / result.Length; result.Grade = grade; } return(result); }
private static CubicSphericalCurve PrepareSphericalBez(MatrixD m1, MatrixD m2) { CurveExtensions.AlignFwd(ref m1, ref m2); return(new CubicSphericalCurve( MyGamePruningStructureSandbox.GetClosestPlanet(m1.Translation)?.PositionComp.WorldVolume.Center ?? Vector3D.Zero, m1, m2)); }
public static double PlanetaryWavePhaseFactor(Vector3D worldPos, double periodMeters) { var planetCenter = MyGamePruningStructureSandbox.GetClosestPlanet(worldPos)?.GetPosition() ?? Vector3D.Zero; var planetDir = worldPos - planetCenter; var currRadius = planetDir.Normalize(); var angle = Math.Acos(planetDir.X); var surfaceDistance = angle * currRadius; var elevationDistance = currRadius; return((surfaceDistance + elevationDistance) / periodMeters); }
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 double GetElevation(this Vector3D v) { var planet = MyGamePruningStructureSandbox.GetClosestPlanet(v); return(planet != null?Vector3D.Distance(v, planet.PositionComp.WorldVolume.Center) : v.Length()); }