Back to Intersection between shapes
#ifndef PASTELGEOMETRY_INTERSECT_LINE_TRIANGLE_HPP
#define PASTELGEOMETRY_INTERSECT_LINE_TRIANGLE_HPP
#include "pastel/geometry/intersect/intersect_line_triangle.h"
#include "pastel/geometry/shape/line.h"
#include "pastel/geometry/shape/triangle.h"
#include "pastel/geometry/shape/plane.h"
#include "pastel/sys/mytypes.h"
#include "pastel/sys/vector.h"
#include "pastel/sys/vector/vector_tools.h"
namespace Pastel
{
template <typename Real>
bool intersect(
const Line<Real, 2>& line,
const PASTEL_TRIANGLE(Real, 2)& triangle,
Vector<Real, 2>& hitList)
{
const Vector<Real, 2>& a = triangle[0];
const Vector<Real, 2>& b = triangle[1];
const Vector<Real, 2>& c = triangle[2];
Real tMaxMin = -Infinity();
Real tMinMax = Infinity();
// Note: line-plane intersections
// do not require normalized plane normals.
// Side a.
Plane<Real, 2> aPlane(a, cross(b - a));
Real t;
if (intersect(line, aPlane, t))
{
if (side(line.position(), aPlane) >= 0)
{
if (t > tMaxMin)
{
tMaxMin = t;
}
}
else
{
if (t < tMinMax)
{
tMinMax = t;
}
}
}
if (tMaxMin > tMinMax)
{
return false;
}
// Side b.
Plane<Real, 2> bPlane(b, cross(c - b));
if (intersect(line, bPlane, t))
{
if (side(line.position(), bPlane) >= 0)
{
if (t > tMaxMin)
{
tMaxMin = t;
}
}
else
{
if (t < tMinMax)
{
tMinMax = t;
}
}
}
if (tMaxMin > tMinMax)
{
return false;
}
// Side c.
Plane<Real, 2> cPlane(c, cross(a - c));
if (intersect(line, cPlane, t))
{
if (side(line.position(), cPlane) >= 0)
{
if (t > tMaxMin)
{
tMaxMin = t;
}
}
else
{
if (t < tMinMax)
{
tMinMax = t;
}
}
}
if (tMaxMin > tMinMax)
{
return false;
}
hitList.set(tMaxMin, tMinMax);
return true;
}
template <typename Real>
bool intersect(
const Line<Real, 3>& line,
const PASTEL_TRIANGLE(Real, 3)& triangle,
Real& tIntersection,
Real& uIntersection,
Real& vIntersection)
{
// Moeller-Trumbore line-triangle intersection algorithm
// from the book "Real-time rendering", page 581
Vector<Real, 3> e1 =
triangle[1] - triangle[0];
Vector<Real, 3> e2 =
triangle[2] - triangle[0];
Vector<Real, 3> p =
cross(line.direction(), e2);
Real a = dot(e1, p);
// Test for parallel plane case
/*
static constexpr Real EPSILON(stringAsReal<Real>("0.01"));
// EPSILON
if (a * a <= dot(p, p) * dot(e1, e1) * EPSILON * EPSILON)
{
return false;
}
*/
// EPSILON
if (a == 0)
{
return false;
}
// Find barycentric coordinates of the
// plane-line intersection point
// to test if it is inside the triangle
Real f = inverse(a);
Vector<Real, 3> s =
line.position() - triangle[0];
const Real u = dot(s, p) * f;
if (u < 0 || u > 1)
{
// Intersection point not inside the triangle
return false;
}
Vector<Real, 3> q = cross(s, e1);
const Real v = dot(line.direction(), q) * f;
if (v < 0 || u + v > 1)
{
// Intersection point not inside the triangle
return false;
}
// Intersection point inside the triangle
// => intersection
const Real t = dot(e2, q) * f;
tIntersection = t;
uIntersection = u;
vIntersection = v;
return true;
}
}
#endif