Esempio n. 1
0
        private void Run()
        {
            Voxel.FindFreeSpace(Deposit, MinRadius, out m_freePosition);
            CapsuleD capsule = new CapsuleD(m_freePosition, Deposit, 1f);
            Vector3D closest; CapsuleDExtensions.Intersects(ref capsule, Voxel, out closest);

            NearSurface = Vector3D.DistanceSquared(Deposit, closest) < 100d;
            Completed   = true;
        }
Esempio n. 2
0
        private void SetNextSurfacePoint()
        {
            CapsuleD surfaceFinder;

            surfaceFinder.Radius = 1f;
            float maxRingSize = m_grid.LocalVolume.Radius; maxRingSize *= maxRingSize;
            bool  overMax     = false;

            surfaceFinder.P0 = m_grid.GetCentre();
            Vector3D targetWorld = m_target.WorldPosition();

            for (int i = 0; i < 1000; i++)
            {
                ExpandingRings.Ring ring = ExpandingRings.GetRing(m_ringIndex);
                if (m_squareIndex >= ring.Squares.Length)
                {
                    ring          = ExpandingRings.GetRing(++m_ringIndex);
                    m_squareIndex = 0;
                }
                Vector2I square = ring.Squares[m_squareIndex++];

                Vector3 direct1; Vector3.Multiply(ref m_perp1, square.X, out direct1);
                Vector3 direct2; Vector3.Multiply(ref m_perp2, square.Y, out direct2);

                surfaceFinder.P1 = targetWorld + direct1 + direct2;
                if (CapsuleDExtensions.Intersects(ref surfaceFinder, (MyVoxelBase)m_target.Entity, out m_surfacePoint))
                {
                    Log.DebugLog("test from " + surfaceFinder.P0 + " to " + surfaceFinder.P1 + ", hit voxel at " + m_surfacePoint);
                    m_finalMine = Vector3D.DistanceSquared(m_surfacePoint, m_target.WorldPosition()) < 1d;
                    m_stage     = Stage.Mine;
                    return;
                }
                Log.DebugLog("test from " + surfaceFinder.P0 + " to " + surfaceFinder.P1 + ", did not hit voxel. P1 constructed from " + targetWorld + ", " + direct1 + ", " + direct2);

                if (ring.DistanceSquared > maxRingSize)
                {
                    if (overMax)
                    {
                        Log.AlwaysLog("Infinite loop", Logger.severity.FATAL);
                        throw new Exception("Infinte loop");
                    }
                    overMax = true;
                    Log.DebugLog("Over max ring size, starting next level", Logger.severity.INFO);
                    m_squareIndex = 0;
                    m_ringIndex   = 0;
                }
            }

            Log.AlwaysLog("Infinite loop", Logger.severity.FATAL);
            throw new Exception("Infinte loop");
        }
Esempio n. 3
0
        protected void SetOutsideTarget(Vector3D direction)
        {
            PseudoBlock navBlock = m_navBlock;

            MyVoxelBase voxel = (MyVoxelBase)m_target.Entity;
            CapsuleD    capsule;
            Vector3D    offset; Vector3D.Multiply(ref direction, voxel.PositionComp.LocalVolume.Radius * 2d, out offset);

            capsule.P1 = navBlock.WorldPosition;
            Vector3D.Add(ref capsule.P1, ref offset, out capsule.P0);
            capsule.Radius = m_grid.LocalVolume.Radius * 4f;

            Vector3D hitPos;

            if (!CapsuleDExtensions.Intersects(ref capsule, voxel, out hitPos))
            {
                Log.DebugLog("capsule: " + capsule.String() + ", does not intersect voxel", Logger.severity.DEBUG);
                hitPos = capsule.P0;
            }

            //Log.DebugLog((tunnel ? "Tunnel target: " : "Backout target: ") + hitPos, Logger.severity.DEBUG);
            m_target.SetWorld(ref hitPos);
        }
Esempio n. 4
0
        /// <summary>
        /// Tests if the ship is obstructed by any voxel.
        /// </summary>
        /// <param name="input"><see cref="TestInput"/></param>
        /// <param name="result"><see cref="VoxelTestResult"/></param>
        /// <returns>True iff a voxel is obstructing the ship.</returns>
        public bool RayCastIntersectsVoxel(ref TestInput input, out VoxelTestResult result)
        {
            Profiler.StartProfileBlock();

            Logger.DebugLog("direction vector is invalid: " + input.Direction, Logger.severity.FATAL, condition: !input.Direction.IsValid() || Math.Abs(1f - input.Direction.LengthSquared()) > 0.01f);
            Logger.TraceLog(input.ToString());

            if (input.Length < 1f)
            {
                // need to skip as Proximity doesn't work with short capsules
                // should be safe, as the ship got here somehow
                Logger.TraceLog("Input length is small, no voxel test necessary");
                result           = VoxelTestResult.Default;
                result.Distance  = input.Length;
                result.Proximity = 1f;
                return(false);
            }

            Vector3D currentPosition = AutopilotGrid.GetCentre();
            Vector3  startOffset; Vector3.Multiply(ref input.Direction, StartRayCast, out startOffset);
            Vector3D startOffsetD = startOffset;
            Vector3D totalOffset; Vector3D.Add(ref input.Offset, ref startOffsetD, out totalOffset);

            CapsuleD capsule;

            Vector3D.Add(ref currentPosition, ref totalOffset, out capsule.P0);
            Vector3D capsuleDisp;

            {
                capsuleDisp.X = input.Direction.X * input.Length;
                capsuleDisp.Y = input.Direction.Y * input.Length;
                capsuleDisp.Z = input.Direction.Z * input.Length;
            }
            Vector3D.Add(ref capsule.P0, ref capsuleDisp, out capsule.P1);
            capsule.Radius = AutopilotGrid.PositionComp.LocalVolume.Radius;
            //Logger.DebugLog("current position: " + currentPosition + ", offset: " + offset + ", line: " + rayDirectionLength + ", start: " + capsule.P0 + ", end: " + capsule.P1);

            result = VoxelTestResult.Default;
            Vector3D hitPosition;
            float    proximity = (float)CapsuleDExtensions.ProximityToVoxel(ref capsule, out result.ObstructingVoxel, out hitPosition, true, input.Length);

            result.Proximity = 10f * proximity;             // lie because we have not done a proper test but could have a very nice result
            if (proximity > 1f)
            {
                Logger.TraceLog("Large capsule DOES NOT intersect voxel: " + capsule.String() + ", proximity: " + proximity + "/" + result.Proximity);
                result.Distance = input.Length;
                Profiler.EndProfileBlock();
                return(false);
            }
            Logger.TraceLog("Large capsule DOES intersect voxel: " + capsule.String() + ", proximity: " + proximity + "/" + result.Proximity);

            IEnumerable <CubeGridCache> myCaches = AttachedGrid.AttachedGrids(AutopilotGrid, AttachedGrid.AttachmentKind.Physics, true).Select(CubeGridCache.GetFor);

            Vector3 v; input.Direction.CalculatePerpendicularVector(out v);
            Vector3 w; Vector3.Cross(ref input.Direction, ref v, out w);
            Matrix  to3D = new Matrix(v.X, v.Y, v.Z, 0f,
                                      w.X, w.Y, w.Z, 0f,
                                      input.Direction.X, input.Direction.Y, input.Direction.Z, 0f,
                                      0f, 0f, 0f, 1f);
            Matrix to2D; Matrix.Invert(ref to3D, out to2D);

            Vector2IMatrix <Vector3D> apShipRejections;

            ResourcePool.Get(out apShipRejections);

            MatrixD worldMatrix = AutopilotGrid.WorldMatrix;
            float   gridSize    = AutopilotGrid.GridSize;

            foreach (CubeGridCache cache in myCaches)
            {
                if (cache == null)
                {
                    Logger.DebugLog("Missing a cache", Logger.severity.DEBUG);
                    Profiler.EndProfileBlock();
                    return(false);
                }
                foreach (Vector3I cell in cache.OccupiedCells())
                {
                    Vector3  local = cell * gridSize;
                    Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world);
                    Vector3D offsetWorld; Vector3D.Add(ref world, ref totalOffset, out offsetWorld);
                    Vector3D relative; Vector3D.Subtract(ref offsetWorld, ref currentPosition, out relative);
                    Vector3  relativeF = relative;
                    Vector3  rejection; Vector3.Reject(ref relativeF, ref input.Direction, out rejection);
                    Vector3  planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents);
                    Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.FATAL, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f);
                    Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y);
                    apShipRejections.Add(ToCell(pc2, gridSize), offsetWorld);
                }
            }

            Vector2IMatrix <bool> testedRejections;

            ResourcePool.Get(out testedRejections);

            const int allowedEmpty = 2;

            foreach (KeyValuePair <Vector2I, Vector3D> cell in apShipRejections.MiddleOut())
            {
                //Logger.DebugLog("Cell was not set: " + cell, Logger.severity.FATAL, condition: cell.Value == Vector3D.Zero);

                if (!testedRejections.Add(cell.Key, true))
                {
                    continue;
                }

                int ringIndex = 0;
                m_insideRing.Clear();

                int biggestRingSq = 0;
                while (true)
                {
                    int consecutiveEmpty     = 0;
                    ExpandingRings.Ring ring = ExpandingRings.GetRing(ringIndex++);
                    foreach (Vector2I ringOffset in ring.Squares)
                    {
                        if (apShipRejections.Contains(ringOffset + cell.Key))
                        {
                            consecutiveEmpty = 0;
                        }
                        else
                        {
                            consecutiveEmpty++;
                            if (consecutiveEmpty > allowedEmpty)
                            {
                                goto GotRing;
                            }
                        }
                    }
                    m_insideRing.AddArray(ring.Squares);
                    biggestRingSq = ring.DistanceSquared;
                }

GotRing:
                foreach (Vector2I ringOffset in m_insideRing)
                {
                    testedRejections.Add(ringOffset + cell.Key, true);
                }

                capsule.P0 = cell.Value;
                Vector3D.Add(ref capsule.P0, ref capsuleDisp, out capsule.P1);
                capsule.Radius   = (1f + (float)Math.Sqrt(biggestRingSq)) * gridSize;
                result.Proximity = (float)CapsuleDExtensions.ProximityToVoxel(ref capsule, out result.ObstructingVoxel, out hitPosition, true, input.Length);
                if (result.Proximity <= 1f)
                {
                    Logger.TraceLog("Block capsule does hit voxel: " + capsule.String() + ", proxmity: " + result.Proximity);
                    double distance;  Vector3D.Distance(ref capsule.P0, ref hitPosition, out distance);
                    result.Distance = (float)distance;
                    apShipRejections.Clear();
                    testedRejections.Clear();
                    ResourcePool.Return(apShipRejections);
                    ResourcePool.Return(testedRejections);
                    Profiler.EndProfileBlock();
                    return(true);
                }
            }

            Logger.TraceLog("Ship's path is clear from voxels, proximity: " + result.Proximity);
            apShipRejections.Clear();
            testedRejections.Clear();
            ResourcePool.Return(apShipRejections);
            ResourcePool.Return(testedRejections);
            Profiler.EndProfileBlock();
            return(false);
        }