Example #1
0
        // Intersect AABBs ‘a’ and ‘b’ moving with constant velocities va and vb.
        // On intersection, return time of first and last contact in tfirst and tlast
        public static bool IntersectMovingAABBAABB(AABB a, AABB b, LVector3 va, LVector3 vb,
                                                   out LFloat tfirst, out LFloat tlast)
        {
            // Exit early if ‘a’ and ‘b’ initially overlapping
            if (TestAABBAABB(a, b))
            {
                tfirst = tlast = LFloat.zero;
                return(true);
            }

            // Use relative velocity; effectively treating 'a' as stationary
            LVector3 v = vb - va;

            // Initialize times of first and last contact
            tfirst = LFloat.zero;
            tlast  = LFloat.one;

            // For each axis, determine times of first and last contact, if any
            for (int i = 0; i < 3; i++)
            {
                if (v[i] < LFloat.zero)
                {
                    if (b.max[i] < a.min[i])
                    {
                        return(false);                     // Nonintersecting and moving apart
                    }
                    if (a.max[i] < b.min[i])
                    {
                        tfirst = Max((a.max[i] - b.min[i]) / v[i], tfirst);
                    }
                    if (b.max[i] > a.min[i])
                    {
                        tlast = Min((a.min[i] - b.max[i]) / v[i], tlast);
                    }
                }

                if (v
                    [i] > LFloat.zero)
                {
                    if (b.min[i] > a.max[i])
                    {
                        return(false);                     // Nonintersecting and moving apart
                    }
                    if (b.max[i] < a.min[i])
                    {
                        tfirst = Max((a.min[i] - b.max[i]) / v[i], tfirst);
                    }
                    if (a.max[i] > b.min[i])
                    {
                        tlast = Min((a.max[i] - b.min[i]) / v[i], tlast);
                    }
                }

// No overlap possible if time of first contact occurs after time of last contact
                if (tfirst > tlast)
                {
                    return(false);
                }
            }

            return(true);
        }
Example #2
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));
        }