Ejemplo n.º 1
0
        public static RectInt RotateRectInt(RectInt ri, Vector2Int pivot, int quarterTurnsClockwise)
        {
            // Get the corners
            var a       = ri.position;
            var trueMax = ri.TrueMax();
            var b       = new Vector2Int(trueMax.x, ri.position.y);
            var c       = new Vector2Int(ri.position.x, trueMax.y);
            var d       = trueMax;

            // Rotate each one.
            a = Rotate(a, pivot, quarterTurnsClockwise);
            b = Rotate(b, pivot, quarterTurnsClockwise);
            c = Rotate(c, pivot, quarterTurnsClockwise);
            d = Rotate(d, pivot, quarterTurnsClockwise);
            // Rebuild RectInt
            ri = GrokRectInt(a, b, c, d);
            return(ri);
        }
Ejemplo n.º 2
0
 // TODO: mimic logical & operation from Phil.Core.RectInt
 public static bool TryGetRectIntersection(RectInt a, RectInt b, out RectInt intersection)
 {
     if (!a.Overlaps(b))
     {
         intersection = new RectInt(0, 0, 0, 0);
         return(false);
     }
     else
     {
         var aMax     = a.TrueMax();
         var bMax     = b.TrueMax();
         int maxLeft  = Mathf.Max(a.xMin, b.xMin);
         int minRight = Mathf.Min(aMax.x, bMax.x);
         int minTop   = Mathf.Min(aMax.y, bMax.y);
         int maxBot   = Mathf.Max(a.yMin, b.yMin);
         int width    = minRight - maxLeft + 1;
         int height   = minTop - maxBot + 1;
         intersection = new RectInt(maxLeft, maxBot, width, height);
         return(true);
     }
 }
Ejemplo n.º 3
0
        public static bool RectIntCast(RectInt origin, Vector2Int delta, RectInt obstruction,
                                       out RectInt dst, out Vector2Int contactNormal, out RectInt overlapIntersection, bool debug = false)
        {
            if (delta == Vector2Int.zero)
            {
                contactNormal = Vector2Int.zero;
                if (TryGetRectIntersection(origin, obstruction, out overlapIntersection))
                {
                    dst = origin;
                    return(true);
                }
                else
                {
                    dst = origin;
                    overlapIntersection = new RectInt(Vector2Int.zero, Vector2Int.zero);
                    return(false);
                }
            }

            float strideWidth  = (float)origin.width / 2;
            float strideHeight = (float)origin.height / 2;
            int   slices       = Mathf.Max(
                Mathf.CeilToInt((float)Mathf.Abs(delta.x) / strideWidth),
                Mathf.CeilToInt((float)Mathf.Abs(delta.y) / strideHeight)
                );

            Vector2 floatStride = new Vector2(delta.x, delta.y) / slices;
            // Debug.LogFormat("float stride: {0}", floatStride);
            RectInt?overlapRect = null;
            RectInt coarseRect  = new RectInt(0, 0, 0, 0);

            for (int i = 0; i < slices + 1; i++)
            {
                Vector2Int position = origin.position + Vector2Int.RoundToInt(i * floatStride);
                RectInt    iterRect = new RectInt(position, origin.size);

                if (iterRect.Overlaps(obstruction))
                {
                    TryGetRectIntersection(iterRect, obstruction, out RectInt ol);
                    overlapRect = ol;
                    coarseRect  = iterRect;
                    break;
                }
            }

            if (overlapRect.HasValue == false)
            {
                dst                 = new RectInt(origin.position + delta, origin.size);
                contactNormal       = Vector2Int.zero;
                overlapIntersection = new RectInt();
                return(false);
            }
            var overlap = overlapRect.Value;

            overlapIntersection = overlap;
            if (debug)
            {
                Debug.LogFormat("Coarse rect: {0}", coarseRect);
            }
            if (debug)
            {
                Debug.LogFormat("Overlap rect: {0}", overlap);
            }


            // At this point, one of our rects overlapped
            // Use our delta, coarse rect, and overlap rect to back-out of overlapping
            Vector2Int backTrack = Vector2Int.zero;

            // fine-tune contact normal? right now just returns a cardinal dir or zero.
            contactNormal = Vector2Int.zero;

            {
                Vector2Int backtrackFromHorz     = Vector2Int.zero;
                Vector2Int contactNormalFromHorz = Vector2Int.one;
                if (delta.x != 0)
                {
                    float slope = (float)delta.y / delta.x;
                    if (-delta.x > 0)
                    {
                        int rightResolve = 1 + overlap.TrueMax().x - coarseRect.x;
                        backtrackFromHorz.x = rightResolve;
                        backtrackFromHorz.y = Mathf.RoundToInt(rightResolve * slope);
                        if (debug)
                        {
                            Debug.LogFormat("Right resolve: {0}. backtrackFromHorz: {1}", rightResolve, backtrackFromHorz);
                        }
                        contactNormalFromHorz = Vector2Int.right;
                    }
                    else
                    {
                        int leftResolve = -Mathf.Abs(coarseRect.TrueMax().x - overlap.x + 1);
                        backtrackFromHorz.x = leftResolve;
                        backtrackFromHorz.y = Mathf.RoundToInt(leftResolve * slope);
                        if (debug)
                        {
                            Debug.LogFormat("Left resolve: {0}. backtrackFromHorz: {1}", leftResolve, backtrackFromHorz);
                        }
                        contactNormalFromHorz = Vector2Int.left;
                    }
                }
                Vector2Int backtrackFromVert     = Vector2Int.zero;
                Vector2Int contactNormalFromVert = Vector2Int.zero;
                if (delta.y != 0)
                {
                    // Pure vertical
                    float invSlope = (float)delta.x / delta.y;
                    if (delta.y > 0)
                    {
                        int downResolve = -Mathf.Abs(coarseRect.TrueMax().y - overlap.y + 1);
                        backtrackFromVert.y = downResolve;
                        backtrackFromVert.x = Mathf.RoundToInt(downResolve * invSlope);
                        if (debug)
                        {
                            Debug.LogFormat("Down resolve: {0}. backtrackFromVert: {1}.", downResolve, backtrackFromVert);
                        }
                        contactNormalFromVert = Vector2Int.down;
                    }
                    else
                    {
                        int upResolve = 1 + overlap.TrueMax().y - coarseRect.y;
                        backtrackFromVert.y = upResolve;
                        backtrackFromVert.x = Mathf.RoundToInt(upResolve * invSlope);
                        if (debug)
                        {
                            Debug.LogFormat("Up resolve: {0}. backtrackFromVert: {1}", upResolve, backtrackFromVert);
                        }
                        contactNormalFromVert = Vector2Int.up;
                    }
                }
                bool useVert = (Mathf.Abs(delta.y) > Mathf.Abs(delta.x));
                backTrack     = useVert ? backtrackFromVert : backtrackFromHorz;
                contactNormal = useVert ? contactNormalFromVert : contactNormalFromHorz;
            }
            // Note: we don't handle corner-to-corner collisions here^.

            if (debug)
            {
                Debug.LogFormat("backtrack: {0}", backTrack);
            }

            Vector2Int finalRectPos = coarseRect.position + backTrack;

            dst = new RectInt(finalRectPos, origin.size);

            if (debug)
            {
                Debug.LogFormat("Final rect: {0}", finalRectPos);
            }

            return(true);
        }