Exemplo n.º 1
0
        public static bool IntersectMovingSphereAABB(Sphere s, LVector3 d, AABB b, out LFloat t)
        {
            // Compute the AABB resulting from expanding b by sphere radius r
            AABB e    = b;
            int  _val = s.r._val;

            e.min._x -= _val;
            e.min._y -= _val;
            e.min._z -= _val;
            e.max._x += _val;
            e.max._y += _val;
            e.max._z += _val;

            // Intersect ray against expanded AABB e. Exit with no intersection if ray
            // misses e, else get intersection point p and time t as result
            LVector3 p;

            if (!IntersectRayAABB(s.c, d, e, out t, out p) || t > LFloat.one)
            {
                return(false);
            }

            // Compute which min and max faces of b the intersection point p lies
            // outside of. Note, u and v cannot have the same bits set and
            // they must have at least one bit set amongst them
            int u = 0, v = 0;

            if (p.x < b.min.x)
            {
                u |= 1;
            }
            if (p.x > b.max.x)
            {
                v |= 1;
            }
            if (p.y < b.min.y)
            {
                u |= 2;
            }
            if (p.y > b.max.y)
            {
                v |= 2;
            }
            if (p.z < b.min.z)
            {
                u |= 4;
            }
            if (p.z > b.max.z)
            {
                v |= 4;
            }

            // ‘Or’ all set bits together into a bit mask (note: here u + v == u | v)
            int m = u + v;

            // Define line segment [c, c+d] specified by the sphere movement
            Segment seg = new Segment(s.c, s.c + d);

            // If all 3 bits set (m == 7) then p is in a vertex region
            if (m == 7)
            {
                // Must now intersect segment [c, c+d] against the capsules of the three
                // edges meeting at the vertex and return the best time, if one or more hit
                LFloat tmin = LFloat.FLT_MAX;
                if (IntersectSegmentCapsule(seg, Corner(b, v), Corner(b, v ^ 1), s.r, out t))
                {
                    tmin = Min(t, tmin);
                }
                if (IntersectSegmentCapsule(seg, Corner(b, v), Corner(b, v ^ 2), s.r, out t))
                {
                    tmin = Min(t, tmin);
                }
                if (IntersectSegmentCapsule(seg, Corner(b, v), Corner(b, v ^ 4), s.r, out t))
                {
                    tmin = Min(t, tmin);
                }
                if (tmin == LFloat.FLT_MAX)
                {
                    return(false);                        // No intersection
                }
                t = tmin;
                return(true); // Intersection at time t == tmin
            }

            // If only one bit set in m, then p is in a face region
            if ((m & (m - 1)) == 0)
            {
                // Do nothing. Time t from intersection with
                // expanded box is correct intersection time
                return(true);
            }

            // p is in an edge region. Intersect against the capsule at the edge
            return(IntersectSegmentCapsule(seg, Corner(b, u ^ 7), Corner(b, v), s.r, out t));
        }
Exemplo n.º 2
0
        // Intersect sphere s0 moving in direction d over time interval t0 <= t <= t1, against
        // a stationary sphere s1. If found intersecting, return time t of collision
        public static bool TestMovingSphereSphere(Sphere s0, LVector3 d, LFloat t0, LFloat t1, Sphere s1, out LFloat t)
        {
            // Compute sphere bounding motion of s0 during time interval from t0 to t1
            Sphere b   = new Sphere();//TODO 移除掉new
            LFloat mid = (t0 + t1) * LFloat.half;

            b.c = s0.c + d * mid;
            b.r = (mid - t0) * d.magnitude + s0.r;
            t   = LFloat.zero;
            // If bounding sphere not overlapping s1, then no collision in this interval
            if (!TestSphereSphere(b, s1))
            {
                return(false);
            }

            // Cannot rule collision out: recurse for more accurate testing. To terminate the
            // recursion, collision is assumed when time interval becomes sufficiently small
            if (t1 - t0 < LFloat.INTERVAL_EPSI_LON)
            {
                t = t0;
                return(true);
            }

            // Recursively test first half of interval; return collision if detected
            if (TestMovingSphereSphere(s0, d, t0, mid, s1, out t))
            {
                return(true);
            }

            // Recursively test second half of interval
            return(TestMovingSphereSphere(s0, d, mid, t1, s1, out t));
        }