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));
 }
Beispiel #3
0
        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());
        }