Commit eaf7915e authored by Philip Trettner's avatar Philip Trettner
Browse files

added some sphere intersections, fixed line aabb intersection

parent 36a28c1f
......@@ -237,8 +237,7 @@ template <class A, class B>
// if A is a _boundary, check if B is completely contained within (then false), otherwise same as intersects solid_of(A)
template <class A, class B>
[[nodiscard]] constexpr auto intersects(A const& a, B const& b)
-> enable_if<std::is_same_v<typename object_traits<A>::tag_t, boundary_tag>, bool>
[[nodiscard]] constexpr auto intersects(A const& a, B const& b) -> enable_if<std::is_same_v<typename object_traits<A>::tag_t, boundary_tag>, bool>
{
using ScalarT = typename A::scalar_t;
auto const solidA = solid_of(a);
......@@ -289,8 +288,7 @@ template <class A, class B>
// if hits intersection parameter is available, use that
template <class A, class B>
[[nodiscard]] constexpr auto intersection(A const& a, B const& b) ->
typename decltype(intersection_parameter(a, b))::template as_hits<typename A::pos_t>
[[nodiscard]] constexpr auto intersection(A const& a, B const& b) -> typename decltype(intersection_parameter(a, b))::template as_hits<typename A::pos_t>
{
auto ts = intersection_parameter(a, b);
typename A::pos_t hits[ts.max_hits] = {};
......@@ -300,14 +298,14 @@ template <class A, class B>
}
// if an optional hit_interval intersection parameter is available, use that
template <class A, class B>
template <class A, class B, std::enable_if_t<decltype(intersection_parameter(std::declval<A>(), std::declval<B>()).value())::is_hit_interval, int> = 0>
[[nodiscard]] constexpr auto intersection(A const& a, B const& b)
-> std::enable_if<decltype(intersection_parameter(a, b).value())::is_hit_interval, // condition
optional<segment<object_traits<A>::domain_dimension, typename object_traits<A>::scalar_t>>> // return type
-> optional<segment<object_traits<A>::domain_dimension, typename object_traits<A>::scalar_t>>
{
using seg_t = segment<object_traits<A>::domain_dimension, typename object_traits<A>::scalar_t>;
auto ts = intersection_parameter(a, b);
if (ts.has_value())
return {{a[ts.value().start], a[ts.value().end]}};
return seg_t{a[ts.value().start], a[ts.value().end]};
return {};
}
......@@ -355,7 +353,7 @@ template <int D, class ScalarT, class Obj>
return {};
}
TG_ASSERT(inter.size() == 1); // no other number remains
TG_ASSERT(inter.size() == 1); // no other number remains
if (contains(obj, l[inter.first() + ScalarT(1)])) // the line continues into the object
return {{inter.first(), tg::max<ScalarT>()}};
return {{tg::min<ScalarT>(), inter.first()}};
......@@ -494,13 +492,13 @@ template <int D, class ScalarT>
{
if (dist <= ScalarT(0))
return {{tg::min<ScalarT>(), tg::max<ScalarT>()}}; // completely contained
return {}; // completely outside
return {}; // completely outside
}
const auto t = -dist / dotND;
if (dotND < ScalarT(0))
return {{t, tg::max<ScalarT>()}}; // line goes into the halfspace
return {{tg::min<ScalarT>(), t}}; // line goes out of the halfspace
return {{tg::min<ScalarT>(), t}}; // line goes out of the halfspace
}
template <int D, class ScalarT>
[[nodiscard]] constexpr optional<ScalarT> closest_intersection_parameter(ray<D, ScalarT> const& r, halfspace<D, ScalarT> const& h)
......@@ -652,16 +650,14 @@ template <class ScalarT>
{
using caps_t = hemisphere_boundary_no_caps<3, ScalarT>;
const auto n = direction(c);
return detail::merge_hits(l, caps_t(c.axis.pos0, c.radius, -n), caps_t(c.axis.pos1, c.radius, n),
cylinder_boundary_no_caps<3, ScalarT>(c.axis, c.radius));
return detail::merge_hits(l, caps_t(c.axis.pos0, c.radius, -n), caps_t(c.axis.pos1, c.radius, n), cylinder_boundary_no_caps<3, ScalarT>(c.axis, c.radius));
}
template <class Obj, class ScalarT, class TraitsT>
[[nodiscard]] constexpr bool intersects(Obj const& lr, capsule<3, ScalarT, TraitsT> const& c)
{
static_assert(object_traits<Obj>::is_infinite, "For finite objects, complete containment within boundary has to be considered as well");
using caps_t = sphere_boundary<3, ScalarT>; // spheres are faster than hemispheres and equivalent for the yes/no decision
return detail::intersects_any(lr, caps_t(c.axis.pos0, c.radius), caps_t(c.axis.pos1, c.radius),
cylinder_boundary_no_caps<3, ScalarT>(c.axis, c.radius));
return detail::intersects_any(lr, caps_t(c.axis.pos0, c.radius), caps_t(c.axis.pos1, c.radius), cylinder_boundary_no_caps<3, ScalarT>(c.axis, c.radius));
}
// line - cylinder
......@@ -772,7 +768,8 @@ template <class ScalarT>
// exclude intersections with mirrored cone
ScalarT hits[2] = {};
auto numHits = 0;
TG_ASSERT(ic.opening_angle <= tg::angle::from_degree(ScalarT(180)) && "Only convex objects are supported, but an inf_cone with openinge angle > 180 degree is not convex.");
TG_ASSERT(ic.opening_angle <= tg::angle::from_degree(ScalarT(180))
&& "Only convex objects are supported, but an inf_cone with openinge angle > 180 degree is not convex.");
// if it is not used for solid cones, this works:
// auto const coneDir = ic.opening_angle > 180_deg ? -ic.opening_dir : ic.opening_dir;
// if (dot(l[inter[0]] - ic.apex, coneDir) >= ScalarT(0)) ...
......@@ -820,7 +817,8 @@ template <class ScalarT>
// line - pyramid
template <class BaseT, typename = std::enable_if_t<!std::is_same_v<BaseT, sphere<2, typename BaseT::scalar_t, 3>>>>
[[nodiscard]] constexpr hits<2, typename BaseT::scalar_t> intersection_parameter(line<3, typename BaseT::scalar_t> const& l, pyramid_boundary_no_caps<BaseT> const& py)
[[nodiscard]] constexpr hits<2, typename BaseT::scalar_t> intersection_parameter(line<3, typename BaseT::scalar_t> const& l,
pyramid_boundary_no_caps<BaseT> const& py)
{
auto const faces = faces_of(py);
return detail::merge_hits_array(l, faces, std::make_index_sequence<faces.size()>{});
......@@ -859,8 +857,8 @@ template <class ScalarT>
// line - triangle3
template <class ScalarT>
[[nodiscard]] constexpr hits<1, ScalarT> intersection_parameter(line<3, ScalarT> const& l,
triangle<3, ScalarT> const& t,
dont_deduce<ScalarT> eps = 100 * tg::epsilon<ScalarT>)
triangle<3, ScalarT> const& t,
dont_deduce<ScalarT> eps = 100 * tg::epsilon<ScalarT>)
{
auto e1 = t.pos1 - t.pos0;
auto e2 = t.pos2 - t.pos0;
......@@ -1037,6 +1035,36 @@ template <class ScalarT>
return pair{p_above, p_below};
}
// returns intersection circle of sphere and sphere (normal points from a to b)
// for now does not work if spheres are identical (result would be a sphere3 again)
template <class ScalarT>
[[nodiscard]] constexpr optional<sphere_boundary<2, ScalarT, 3>> intersection(sphere_boundary<3, ScalarT> const& a, plane<3, ScalarT> const& b)
{
auto const d = dot(a.center, b.normal) - b.dis;
if (d > a.radius)
return {};
if (d < -a.radius)
return {};
sphere_boundary<2, ScalarT, 3> r;
r.center = a.center - b.normal * d;
r.normal = d >= ScalarT(0) ? b.normal : -b.normal;
r.radius = sqrt(a.radius * a.radius - d * d);
return r;
}
template <class ScalarT>
[[nodiscard]] constexpr optional<sphere_boundary<2, ScalarT, 3>> intersection(plane<3, ScalarT> const& a, sphere_boundary<3, ScalarT> const& b)
{
auto r = intersection(b, a);
if (r.has_value())
{
auto c = r.value();
c.normal = -c.normal; // make sure to point from a to b
return c;
}
return r;
}
template <class ScalarT>
[[nodiscard]] constexpr line<3, ScalarT> intersection(plane<3, ScalarT> const& a, plane<3, ScalarT> const& b)
......@@ -1246,8 +1274,7 @@ template <int D, class ScalarT>
{
for (auto i = 0; i < D; ++i)
{
if ((r.origin[i] > b.max[i] && r.dir[i] >= ScalarT(0)) ||
(r.origin[i] < b.min[i] && r.dir[i] <= ScalarT(0)))
if ((r.origin[i] > b.max[i] && r.dir[i] >= ScalarT(0)) || (r.origin[i] < b.min[i] && r.dir[i] <= ScalarT(0)))
return false;
}
......@@ -1626,10 +1653,7 @@ template <class ScalarT>
// check intersections between line through the axis and the aabb
auto const line = inf_of(c.axis);
auto const len = length(c.axis);
auto const intersects_at = [&](ScalarT t)
{
return intersects(sphere_boundary<2, ScalarT, 3>(line[t], c.radius, line.dir), b);
};
auto const intersects_at = [&](ScalarT t) { return intersects(sphere_boundary<2, ScalarT, 3>(line[t], c.radius, line.dir), b); };
auto const hits = intersection_parameter(line, boundary_of(b));
for (auto const& hit : hits)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment