Пример #1
0
        /// <summary>
        /// Checks for an intersection between a ray and an AxisAlignedBoundingBox.
        /// Uses the algorithm "Fast Ray/Axis-Aligned Bounding Box Overlap Tests using Ray Slopes".
        /// </summary>
        /// <param name="b">BoundingBox to check</param>
        /// <returns>True if an intersection exists</returns>
        public bool Intersects(AxisAlignedBoundingBox b)
        {
            if (dirty)
            {
                PreCalculate();
            }

            switch (classification)
            {
            case RayType.MMM:
                if ((origin.X < b.Min.X) || (origin.Y < b.Min.Y) || (origin.Z < b.Min.Z) ||
                    (jbyi * b.Min.X - b.Max.Y + c_xy > 0) ||
                    (ibyj * b.Min.Y - b.Max.X + c_yx > 0) ||
                    (jbyk * b.Min.Z - b.Max.Y + c_zy > 0) ||
                    (kbyj * b.Min.Y - b.Max.Z + c_yz > 0) ||
                    (kbyi * b.Min.X - b.Max.Z + c_xz > 0) ||
                    (ibyk * b.Min.Z - b.Max.X + c_zx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MMP:
                if ((origin.X < b.Min.X) || (origin.Y < b.Min.Y) || (origin.Z > b.Max.Z) ||
                    (jbyi * b.Min.X - b.Max.Y + c_xy > 0) ||
                    (ibyj * b.Min.Y - b.Max.X + c_yx > 0) ||
                    (jbyk * b.Max.Z - b.Max.Y + c_zy > 0) ||
                    (kbyj * b.Min.Y - b.Min.Z + c_yz < 0) ||
                    (kbyi * b.Min.X - b.Min.Z + c_xz < 0) ||
                    (ibyk * b.Max.Z - b.Max.X + c_zx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MPM:
                if ((origin.X < b.Min.X) || (origin.Y > b.Max.Y) || (origin.Z < b.Min.Z) ||
                    (jbyi * b.Min.X - b.Min.Y + c_xy < 0) ||
                    (ibyj * b.Max.Y - b.Max.X + c_yx > 0) ||
                    (jbyk * b.Min.Z - b.Min.Y + c_zy < 0) ||
                    (kbyj * b.Max.Y - b.Max.Z + c_yz > 0) ||
                    (kbyi * b.Min.X - b.Max.Z + c_xz > 0) ||
                    (ibyk * b.Min.Z - b.Max.X + c_zx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MPP:
                if ((origin.X < b.Min.X) || (origin.Y > b.Max.Y) || (origin.Z > b.Max.Z) ||
                    (jbyi * b.Min.X - b.Min.Y + c_xy < 0) ||
                    (ibyj * b.Max.Y - b.Max.X + c_yx > 0) ||
                    (jbyk * b.Max.Z - b.Min.Y + c_zy < 0) ||
                    (kbyj * b.Max.Y - b.Min.Z + c_yz < 0) ||
                    (kbyi * b.Min.X - b.Min.Z + c_xz < 0) ||
                    (ibyk * b.Max.Z - b.Max.X + c_zx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.PMM:
                if ((origin.X > b.Max.X) || (origin.Y < b.Min.Y) || (origin.Z < b.Min.Z) ||
                    (jbyi * b.Max.X - b.Max.Y + c_xy > 0) ||
                    (ibyj * b.Min.Y - b.Min.X + c_yx < 0) ||
                    (jbyk * b.Min.Z - b.Max.Y + c_zy > 0) ||
                    (kbyj * b.Min.Y - b.Max.Z + c_yz > 0) ||
                    (kbyi * b.Max.X - b.Max.Z + c_xz > 0) ||
                    (ibyk * b.Min.Z - b.Min.X + c_zx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.PMP:
                if ((origin.X > b.Max.X) || (origin.Y < b.Min.Y) || (origin.Z > b.Max.Z) ||
                    (jbyi * b.Max.X - b.Max.Y + c_xy > 0) ||
                    (ibyj * b.Min.Y - b.Min.X + c_yx < 0) ||
                    (jbyk * b.Max.Z - b.Max.Y + c_zy > 0) ||
                    (kbyj * b.Min.Y - b.Min.Z + c_yz < 0) ||
                    (kbyi * b.Max.X - b.Min.Z + c_xz < 0) ||
                    (ibyk * b.Max.Z - b.Min.X + c_zx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.PPM:
                if ((origin.X > b.Max.X) || (origin.Y > b.Max.Y) || (origin.Z < b.Min.Z) ||
                    (jbyi * b.Max.X - b.Min.Y + c_xy < 0) ||
                    (ibyj * b.Max.Y - b.Min.X + c_yx < 0) ||
                    (jbyk * b.Min.Z - b.Min.Y + c_zy < 0) ||
                    (kbyj * b.Max.Y - b.Max.Z + c_yz > 0) ||
                    (kbyi * b.Max.X - b.Max.Z + c_xz > 0) ||
                    (ibyk * b.Min.Z - b.Min.X + c_zx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.PPP:
                if ((origin.X > b.Max.X) || (origin.Y > b.Max.Y) || (origin.Z > b.Max.Z) ||
                    (jbyi * b.Max.X - b.Min.Y + c_xy < 0) ||
                    (ibyj * b.Max.Y - b.Min.X + c_yx < 0) ||
                    (jbyk * b.Max.Z - b.Min.Y + c_zy < 0) ||
                    (kbyj * b.Max.Y - b.Min.Z + c_yz < 0) ||
                    (kbyi * b.Max.X - b.Min.Z + c_xz < 0) ||
                    (ibyk * b.Max.Z - b.Min.X + c_zx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.OMM:
                if ((origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Z < b.Min.Z) ||
                    (jbyk * b.Min.Z - b.Max.Y + c_zy > 0) ||
                    (kbyj * b.Min.Y - b.Max.Z + c_yz > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.OMP:
                if ((origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Z > b.Max.Z) ||
                    (jbyk * b.Max.Z - b.Max.Y + c_zy > 0) ||
                    (kbyj * b.Min.Y - b.Min.Z + c_yz < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.OPM:
                if ((origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y > b.Max.Y) || (origin.Z < b.Min.Z) ||
                    (jbyk * b.Min.Z - b.Min.Y + c_zy < 0) ||
                    (kbyj * b.Max.Y - b.Max.Z + c_yz > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.OPP:
                if ((origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y > b.Max.Y) || (origin.Z > b.Max.Z) ||
                    (jbyk * b.Max.Z - b.Min.Y + c_zy < 0) ||
                    (kbyj * b.Max.Y - b.Min.Z + c_yz < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MOM:
                if ((origin.Y < b.Min.Y) || (origin.Y > b.Max.Y) ||
                    (origin.X < b.Min.X) || (origin.Z < b.Min.Z) ||
                    (kbyi * b.Min.X - b.Max.Z + c_xz > 0) ||
                    (ibyk * b.Min.Z - b.Max.X + c_zx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MOP:
                if ((origin.Y < b.Min.Y) || (origin.Y > b.Max.Y) ||
                    (origin.X < b.Min.X) || (origin.Z > b.Max.Z) ||
                    (kbyi * b.Min.X - b.Min.Z + c_xz < 0) ||
                    (ibyk * b.Max.Z - b.Max.X + c_zx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.POM:
                if ((origin.Y < b.Min.Y) || (origin.Y > b.Max.Y) ||
                    (origin.X > b.Max.X) || (origin.Z < b.Min.Z) ||
                    (kbyi * b.Max.X - b.Max.Z + c_xz > 0) ||
                    (ibyk * b.Min.Z - b.Min.X + c_zx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.POP:
                if ((origin.Y < b.Min.Y) || (origin.Y > b.Max.Y) ||
                    (origin.X > b.Max.X) || (origin.Z > b.Max.Z) ||
                    (kbyi * b.Max.X - b.Min.Z + c_xz < 0) ||
                    (ibyk * b.Max.Z - b.Min.X + c_zx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MMO:
                if ((origin.Z < b.Min.Z) || (origin.Z > b.Max.Z) ||
                    (origin.X < b.Min.X) || (origin.Y < b.Min.Y) ||
                    (jbyi * b.Min.X - b.Max.Y + c_xy > 0) ||
                    (ibyj * b.Min.Y - b.Max.X + c_yx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MPO:
                if ((origin.Z < b.Min.Z) || (origin.Z > b.Max.Z) ||
                    (origin.X < b.Min.X) || (origin.Y > b.Max.Y) ||
                    (jbyi * b.Min.X - b.Min.Y + c_xy < 0) ||
                    (ibyj * b.Max.Y - b.Max.X + c_yx > 0))
                {
                    return(false);
                }
                return(true);

            case RayType.PMO:
                if ((origin.Z < b.Min.Z) || (origin.Z > b.Max.Z) ||
                    (origin.X > b.Max.X) || (origin.Y < b.Min.Y) ||
                    (jbyi * b.Max.X - b.Max.Y + c_xy > 0) ||
                    (ibyj * b.Min.Y - b.Min.X + c_yx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.PPO:
                if ((origin.Z < b.Min.Z) || (origin.Z > b.Max.Z) ||
                    (origin.X > b.Max.X) || (origin.Y > b.Max.Y) ||
                    (jbyi * b.Max.X - b.Min.Y + c_xy < 0) ||
                    (ibyj * b.Max.Y - b.Min.X + c_yx < 0))
                {
                    return(false);
                }
                return(true);

            case RayType.MOO:
                if ((origin.X < b.Min.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y) ||
                    (origin.Z < b.Min.Z) || (origin.Z > b.Max.Z))
                {
                    return(false);
                }
                return(true);

            case RayType.POO:
                if ((origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y) ||
                    (origin.Z < b.Min.Z) || (origin.Z > b.Max.Z))
                {
                    return(false);
                }
                return(true);

            case RayType.OMO:
                if ((origin.Y < b.Min.Y) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Z < b.Min.Z) || (origin.Z > b.Max.Z))
                {
                    return(false);
                }
                if ((origin.Y > b.Max.Y) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Z < b.Min.Z) || (origin.Z > b.Max.Z))
                {
                    return(false);
                }
                if ((origin.Z < b.Min.Z) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y))
                {
                    return(false);
                }
                if ((origin.Z > b.Max.Z) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y))
                {
                    return(false);
                }
                return(true);

            case RayType.OPO:
                if ((origin.Y > b.Max.Y) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Z < b.Min.Z) || (origin.Z > b.Max.Z))
                {
                    return(false);
                }
                if ((origin.Z < b.Min.Z) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y))
                {
                    return(false);
                }
                if ((origin.Z > b.Max.Z) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y))
                {
                    return(false);
                }
                return(true);

            case RayType.OOM:
                if ((origin.Z < b.Min.Z) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y))
                {
                    return(false);
                }
                if ((origin.Z > b.Max.Z) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y))
                {
                    return(false);
                }
                return(true);

            case RayType.OOP:
                if ((origin.Z > b.Max.Z) ||
                    (origin.X < b.Min.X) || (origin.X > b.Max.X) ||
                    (origin.Y < b.Min.Y) || (origin.Y > b.Max.Y))
                {
                    return(false);
                }
                return(true);
            }
            return(false);
        }