// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT using System; using ClassicalSharp.Entities; using OpenTK; namespace ClassicalSharp.Physics { /// Contains various methods for intersecting geometry. public static class Intersection { /// Calculates the intersection points of a ray and a rotated bounding box. public static bool RayIntersectsRotatedBox(Vector3 origin, Vector3 dir, Entity target, out float tMin, out float tMax) { // This is the rotated AABB of the model we want to test for intersection // * // / \ we then perform a counter *---* and we can then do // ====>* x * rotation to the rotated AABB | x | a standard AABB test // \ / and ray origin and direction *---* with the rotated ray // * / // / Vector3 rotatedOrigin = target.Position + Utils.RotateY(origin - target.Position, -target.HeadYawRadians); Vector3 rotatedDir = Utils.RotateY(dir, -target.HeadYawRadians); AABB bb = target.PickingBounds; return RayIntersectsBox(rotatedOrigin, rotatedDir, bb.Min, bb.Max, out tMin, out tMax); } //http://www.cs.utah.edu/~awilliam/box/box.pdf /// Calculates the intersection points of a ray and a bounding box. public static bool RayIntersectsBox(Vector3 origin, Vector3 dir, Vector3 min, Vector3 max, out float t0, out float t1) { t0 = t1 = 0; float tmin, tmax, tymin, tymax, tzmin, tzmax; float invDirX = 1 / dir.X; if (invDirX >= 0) { tmin = (min.X - origin.X) * invDirX; tmax = (max.X - origin.X) * invDirX; } else { tmin = (max.X - origin.X) * invDirX; tmax = (min.X - origin.X) * invDirX; } float invDirY = 1 / dir.Y; if (invDirY >= 0) { tymin = (min.Y - origin.Y) * invDirY; tymax = (max.Y - origin.Y) * invDirY; } else { tymin = (max.Y - origin.Y) * invDirY; tymax = (min.Y - origin.Y) * invDirY; } if (tmin > tymax || tymin > tmax) return false; if (tymin > tmin) tmin = tymin; if (tymax < tmax) tmax = tymax; float invDirZ = 1 / dir.Z; if (invDirZ >= 0) { tzmin = (min.Z - origin.Z) * invDirZ; tzmax = (max.Z - origin.Z) * invDirZ; } else { tzmin = (max.Z - origin.Z) * invDirZ; tzmax = (min.Z - origin.Z) * invDirZ; } if (tmin > tzmax || tzmin > tmax) return false; if (tzmin > tmin) tmin = tzmin; if (tzmax < tmax) tmax = tzmax; t0 = tmin; t1 = tmax; return t0 >= 0; } } }