EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_TriangleRay.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Robert Marskar <robert.marskar@sintef.no>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
13#ifndef EBGEOMETRY_TRIANGLERAY_HPP
14#define EBGEOMETRY_TRIANGLERAY_HPP
15
16// Our includes
17#include "EBGeometry_GPU.hpp"
18#include "EBGeometry_Math.hpp"
19#include "EBGeometry_SIMD.hpp"
21
22namespace EBGeometry {
23
27namespace TriangleRay {
28
49template <class V, class Source>
50[[nodiscard]] EBGEOMETRY_HOST_DEVICE
52inline V
53crossing(const Source& a_triangle,
54 const TriangleDistance::Vec3V<V>& a_origin,
55 const TriangleDistance::Vec3V<V>& a_direction,
56 const V a_tMin,
57 const V a_tMax) noexcept
58{
59 using SIMD::abs;
60 using SIMD::both;
61 using SIMD::select;
62 using TriangleDistance::constant;
63 using TriangleDistance::cross;
64 using TriangleDistance::dot;
66
67 using T = typename SIMD::Scalar<V>::type;
68
69 const Vec3V<V> v0 = a_triangle.vertex(0);
70 const Vec3V<V> e1 = a_triangle.vertex(1) - v0;
71 const Vec3V<V> e2 = a_triangle.vertex(2) - v0;
72
73 const Vec3V<V> pv = cross(a_direction, e2);
74 const V det = dot(e1, pv);
75 const V inv = constant<V>(1) / det;
76
77 const Vec3V<V> s = a_origin - v0;
78 const V u = dot(s, pv) * inv;
79
80 const Vec3V<V> q = cross(s, e1);
81 const V v = dot(a_direction, q) * inv;
82 const V t = dot(e2, q) * inv;
83
84 // The barycentric tests are widened by the rounding error of the crossing point, a distance delta of a few
85 // ulps of the coordinates, as each coordinate measures it: by the triangle's height over the opposite
86 // edge, twice the area over that edge's length. A point on an edge shared by two triangles is then inside
87 // both, however far the ray comes from; the widening does not grow for a ray nearly in the triangle's
88 // plane. Each test is multiplied through by a lower bound on twice the area (the largest component of
89 // e1 x e2), so that it needs no square root or division, and every edge's length is bounded by
90 // |e1| + |e2| in the L1 norm: both only widen it a little more. A zero det (a ray in the plane) makes u, v
91 // and t infinite or NaN, which every test below rejects.
92 const Vec3V<V> n = cross(e1, e2);
93 const V nx = abs(n.x);
94 const V ny = abs(n.y);
95 const V nz = abs(n.z);
96 const V nxy = select(nx > ny, nx, ny);
97 const V area2 = select(nxy > nz, nxy, nz);
98 const V ulps = V(T(4) * Math::Limits<T>::epsilon());
99 const V delta = ulps * (abs(a_origin.x) + abs(a_origin.y) + abs(a_origin.z) + abs(v0.x) + abs(v0.y) + abs(v0.z));
100 const V slack = ulps * area2 + delta * (abs(e1.x) + abs(e1.y) + abs(e1.z) + abs(e2.x) + abs(e2.y) + abs(e2.z));
101
102 const auto inside = both(both(u * area2 + slack >= constant<V>(0), v * area2 + slack >= constant<V>(0)),
103 (constant<V>(1) - u - v) * area2 + slack >= constant<V>(0));
104 const auto inRange = both(t >= a_tMin, a_tMax >= t);
105 const auto crosses = both(both(inside, inRange), abs(det) > constant<V>(0));
106
107 return select(crosses, t, V(Math::Limits<T>::infinity()));
108}
109
110} // namespace TriangleRay
111
112} // namespace EBGeometry
113
114#endif
GPU portability layer: host/device decoration macros and backend detection.
#define EBGEOMETRY_HOST_ALWAYS_INLINE
Always inline a function in a host pass (GCC and Clang); nothing in a device pass.
Definition EBGeometry_GPU.hpp:123
#define EBGEOMETRY_HOST_DEVICE
Mark a function as callable from both host and device code (no-op on host compilers).
Definition EBGeometry_GPU.hpp:80
Scalar helpers and numeric limits that compile for both host and device.
Thin wrappers over SSE4.1, AVX and AVX-512 registers, so that one kernel template serves every SIMD w...
The triangle distance kernels, written once for a scalar and for every SIMD::Pack.
bool both(const bool a_lhs, const bool a_rhs) noexcept
Whether both conditions hold (scalar form).
Definition EBGeometry_SIMD.hpp:62
T select(const bool a_mask, const T a_ifTrue, const T a_ifFalse) noexcept
Pick a_ifTrue where a_mask holds, else a_ifFalse (scalar form).
Definition EBGeometry_SIMD.hpp:49
float abs(const float a_x) noexcept
Absolute value (scalar form).
Definition EBGeometry_SIMD.hpp:98
EBGEOMETRY_HOST_ALWAYS_INLINE V crossing(const Source &a_triangle, const TriangleDistance::Vec3V< V > &a_origin, const TriangleDistance::Vec3V< V > &a_direction, const V a_tMin, const V a_tMax) noexcept
Where a ray crosses a triangle, or one triangle per lane (Möller–Trumbore).
Definition EBGeometry_TriangleRay.hpp:53
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
constexpr Vec3T< T > cross(const Vec3T< T > &u, const Vec3T< T > &v) noexcept
Cross product of two 3D vectors.
T dot(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Dot product of two 2D vectors.
Numeric limits, with the meanings of the std::numeric_limits members of the same names.
Definition EBGeometry_Math.hpp:91
V type
The scalar type.
Definition EBGeometry_SIMD.hpp:177
A 3D vector of V, where V is a scalar or a SIMD::Pack: x, y and z each hold one lane per triangle.
Definition EBGeometry_TriangleDistance.hpp:39