ClassiCube/ClassicalSharp/Math/Physics/IntersectionUtils.cs

72 lines
2.6 KiB
C#

// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
using System;
using ClassicalSharp.Entities;
using OpenTK;
namespace ClassicalSharp.Physics {
/// <summary> Contains various methods for intersecting geometry. </summary>
public static class Intersection {
/// <summary> Calculates the intersection points of a ray and a rotated bounding box. </summary>
internal 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
/// <summary> Calculates the intersection points of a ray and a bounding box. </summary>
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;
}
}
}