bool Math::RayIntersectRectangle(const Ray3D &Ray, const Rectangle3f &Rect)
{
for(UINT PlaneIndex = 0; PlaneIndex < 6; PlaneIndex++)
{
Vec3f Pt;
UINT Axis;
if(PlaneIndex < 3)
{
Pt = Rect.Min;
Axis = PlaneIndex;
}
else
{
Pt = Rect.Max;
Axis = PlaneIndex - 3;
}
const float t = (Pt[Axis] - Ray.P0[Axis]) / Ray.D[Axis];
const Vec3f IntersectPt = Ray.P0 + Ray.D * t;
if(Rect.PtWithinDistance(IntersectPt, 1e-4f))
{
return true;
}
}
return false;
}
bool Math::RayIntersectTriangle(const Vec3f &RayPt, const Vec3f &RayDir, const Vec3f &T0, const Vec3f &T1, const Vec3f &T2, Vec3f &IntersectPt)
{
Vec3f u, v, n; Vec3f w0, w; float r, a, b;
u = T1 - T0;
v = T2 - T0;
n = Vec3f::Cross(u, v);
w0 = RayPt - T0;
a = -Vec3f::Dot(n, w0);
b = Vec3f::Dot(n, RayDir);
if(b == 0.0f)
{
return false;
}
r = a / b;
if (r < 0.0f) {
return false; }
IntersectPt = RayPt + r * RayDir;
float uu, uv, vv, wu, wv, D;
uu = Vec3f::Dot(u, u);
uv = Vec3f::Dot(u, v);
vv = Vec3f::Dot(v, v);
w = IntersectPt - T0;
wu = Vec3f::Dot(w, u);
wv = Vec3f::Dot(w, v);
D = 1.0f / (uv * uv - uu * vv);
float s, t;
s = (uv * wv - vv * wu) * D;
if (s < 0.0f || s > 1.0f) {
return false;
}
t = (uv * wu - uu * wv) * D;
if (t < 0.0f || (s + t) > 1.0f) {
return false;
}
return true;
}
bool Math::LineIntersectTriangle(const Vec3f &LinePt, const Vec3f &LineDir, const Vec3f &T0, const Vec3f &T1, const Vec3f &T2, Vec3f &IntersectPt)
{
Vec3f u, v, n; Vec3f w0, w; float r, a, b;
u = T1 - T0;
v = T2 - T0;
n = Vec3f::Cross(u, v);
w0 = LinePt - T0;
a = -Vec3f::Dot(n, w0);
b = Vec3f::Dot(n, LineDir);
if(b == 0.0f)
{
return false;
}
r = a / b;
IntersectPt = LinePt + r * LineDir;
float uu, uv, vv, wu, wv, D;
uu = Vec3f::Dot(u, u);
uv = Vec3f::Dot(u, v);
vv = Vec3f::Dot(v, v);
w = IntersectPt - T0;
wu = Vec3f::Dot(w, u);
wv = Vec3f::Dot(w, v);
D = uv * uv - uu * vv;
float s, t;
s = (uv * wv - vv * wu) / D;
if (s < 0.0f || s > 1.0f) {
return false;
}
t = (uv * wu - uu * wv) / D;
if (t < 0.0f || (s + t) > 1.0f) {
return false;
}
return true;
}
bool Math::SegmentIntersectTriangle(const Vec3f &P0, const Vec3f &P1, const Vec3f &T0, const Vec3f &T1, const Vec3f &T2, Vec3f &IntersectPt)
{
bool Result = LineIntersectTriangle(P0, P1 - P0, T0, T1, T2, IntersectPt);
if(Result)
{
return Vec3f::WithinRect(IntersectPt, Rectangle3f::ConstructFromTwoPoints(P0, P1));
}
else
{
return false;
}
}
bool Rectangle3f::ParametricRayIntersect(const Vec3f &RayOrigin, const Vec3f &RayDir, float &TMin, float &TMax) const
{
TMin = 0.0f;
TMax = 1e10f;
for (UINT AxisIndex = 0; AxisIndex < 3; AxisIndex++)
{
float invRayDir = 1.0f / RayDir[AxisIndex];
float TNear = (Min[AxisIndex] - RayOrigin[AxisIndex]) * invRayDir;
float TFar = (Max[AxisIndex] - RayOrigin[AxisIndex]) * invRayDir;
if (TNear > TFar)
{
swap(TNear, TFar);
}
TMin = TNear > TMin ? TNear : TMin;
TMax = TFar < TMax ? TFar : TMax;
if (TMin > TMax)
{
return false;
}
}
return true;
}