Implement ray-cylinder intersection

This commit is contained in:
Nikita Lisitsa 2021-12-23 10:57:11 +03:00
parent e0312b66b1
commit 12b6b3169c

View file

@ -6,6 +6,7 @@
#include <psemek/geom/ray.hpp>
#include <psemek/geom/box.hpp>
#include <psemek/geom/sphere.hpp>
#include <psemek/geom/cylinder.hpp>
#include <psemek/geom/orientation.hpp>
#include <psemek/geom/contains.hpp>
#include <psemek/geom/gauss.hpp>
@ -222,10 +223,42 @@ namespace psemek::geom
return {ir->first, ir->second};
}
template <typename T, std::size_t N>
interval<T> intersection(ray<T, N> const & r, cylinder<T, N> const & c)
{
auto Z2 = length_sqr(c.axis);
auto CZ = dot(c.center - r.origin, c.axis);
auto DZ = dot(r.direction, c.axis);
if (DZ == 0)
return {};
auto prmin = (-Z2 + CZ) / DZ;
auto prmax = ( Z2 + CZ) / DZ;
if (DZ < 0)
std::swap(prmin, prmax);
auto n = normalized(c.axis);
auto q = r.origin - c.center;
auto ir = solve_quadratic(length_sqr(r.direction) - sqr(dot(r.direction, n)),
2 * dot(q, r.direction) - 2 * dot(q, n) * dot(r.direction, n),
length_sqr(q) - sqr(dot(q, n)) - sqr(c.radius));
if (!ir)
return {};
return {std::max(ir->first, prmin), std::min(ir->second, prmax)};
}
template <typename T, std::size_t N>
bool intersect(ray<T, N> const & r, sphere<T, N> const & s)
{
return intersection(r, s).empty();
}
template <typename T, std::size_t N>
bool intersect(ray<T, N> const & r, cylinder<T, N> const & c)
{
return intersection(r, c).empty();
}
}