21#ifndef EBGEOMETRY_OFFSETRAYFORMS_HPP
22#define EBGEOMETRY_OFFSETRAYFORMS_HPP
112 const T denom =
dot(a_n, a_ray.m_direction);
113 const T num = a_d -
dot(a_n, a_ray.m_origin);
123 const T t = num / denom;
131 else if (t <
m_out) {
145 if (!a_other.hit()) {
155 if (a_other.m_in <
m_in) {
157 m_nIn = a_other.m_nIn;
160 if (a_other.m_out >
m_out) {
161 m_out = a_other.m_out;
182 const Vec3T<T> oc = a_ray.m_origin - a_center;
183 const T b =
dot(oc, a_ray.m_direction);
184 const Vec3T<T> perp = oc - b * a_ray.m_direction;
185 const T h = a_radius * a_radius -
dot(perp, perp);
187 if (!(a_radius > T(0)) || h < T(0)) {
191 const T s = std::sqrt(h);
197 p.
m_nIn = (a_ray.at(p.
m_in) - a_center) / a_radius;
198 p.
m_nOut = (a_ray.at(p.
m_out) - a_center) / a_radius;
218 if (!(a_radius > T(0))) {
222 const Vec3T<T> oa = a_ray.m_origin - a_point;
223 const Vec3T<T> dp = a_ray.m_direction -
dot(a_ray.m_direction, a_axis) * a_axis;
226 const T qa =
dot(dp, dp);
227 const T qb =
dot(dp, op);
232 const Vec3T<T> perp = op - (qb / qa) * dp;
233 const T h = qa * (a_radius * a_radius -
dot(perp, perp));
239 const T s = std::sqrt(h);
241 p.
m_in = (-qb - s) / qa;
242 p.
m_out = (-qb + s) / qa;
246 else if (
dot(op, op) > a_radius * a_radius) {
272 Piece<T> p = RayDetail::ballPiece(a_ray, a_a, a_radius);
274 p.
unite(RayDetail::ballPiece(a_ray, a_b, a_radius));
282 Piece<T> tube = RayDetail::tubePiece(a_ray, a_a, u, a_radius);
285 tube.
clip(a_ray, -u, -
dot(u, a_a));
286 tube.
clip(a_ray, u,
dot(u, a_b));
311 for (
size_t dir = 0; dir < 3; dir++) {
312 if (!(a_lo[dir] <= a_hi[dir])) {
343 if (!RayDetail::boxPiece(a_ray, a_lo - grow, a_hi + grow).hit()) {
355 for (
size_t dir = 0; dir < 3; dir++) {
357 const Piece<T> box = RayDetail::boxPiece(a_ray, a_lo - along, a_hi + along);
372 if (p.
hit() && p.
m_nIn[dirIn] != T(0) && p.
m_nOut[dirOut] != T(0)) {
376 for (
size_t dir = 0; dir < 3; dir++) {
377 const size_t d1 = (dir + 1) % 3;
378 const size_t d2 = (dir + 2) % 3;
380 for (
int corner = 0; corner < 4; corner++) {
383 a[d1] = ((corner & 1) != 0) ? a_hi[d1] : a_lo[d1];
384 a[d2] = ((corner & 2) != 0) ? a_hi[d2] : a_lo[d2];
390 p.
unite(RayDetail::capsulePiece(a_ray, a, b, a_radius));
407template <
class T,
class Edges>
422 area +=
dot(
cross(a_a - first, a_b - a_a), a_n);
451template <
class T,
class Edges>
457 const Edges& a_edges,
463 bool& a_inSlab)
noexcept
465 const T dn =
dot(a_n, a_ray.m_direction);
466 const T h0 =
dot(a_n, a_ray.m_origin - a_p0);
472 const T a = (-a_radius - h0) / dn;
473 const T b = (a_radius - h0) / dn;
478 else if (std::abs(h0) > a_radius) {
484 a_inSlab = s0 < a_tMin && s1 >= a_tMin;
486 if (s1 < a_tMin || !(s0 < a_best)) {
490 const T area = (dn != T(0)) ? RayDetail::twiceArea(a_n, a_edges) : T(0);
495 const T sign = (area > T(0)) ? T(1) : T(-1);
497 const Vec3T<T> qIn = a_ray.at(tIn) -
dot(a_n, a_ray.at(tIn) - a_p0) * a_n;
498 const Vec3T<T> qOut = a_ray.at(s1) -
dot(a_n, a_ray.at(s1) - a_p0) * a_n;
501 bool separated =
false;
506 const T in = sign *
dot(
cross(e, qIn - a_a), a_n);
507 const T out = sign *
dot(
cross(e, qOut - a_a), a_n);
508 const T r = a_radius * e.
length();
510 over = over && in >= T(0);
511 separated = separated || (in < -r && out < -r);
514 if (s0 >= a_tMin && over) {
516 a_normal = ((dn < T(0)) ? T(1) : T(-1)) * a_n;
532 const T m2 =
dot(m, m);
533 const T along =
dot(a_ray.m_origin - a_a, m);
535 if (m2 > T(0) && along * along > a_radius * a_radius * m2) {
539 const Piece<T> capsule = RayDetail::capsulePiece(a_ray, a_a, a_b, a_radius);
541 if (capsule.
hit() && capsule.
m_in >= a_tMin && capsule.
m_in < best) {
544 a_normal = capsule.
m_nIn;
565template <
class T,
class Edges>
570 const RayT<T>& a_ray,
const Vec3T<T>& a_n,
const Vec3T<T>& a_p0,
const Edges& a_edges,
const T a_radius)
noexcept
574 const T area = RayDetail::twiceArea(a_n, a_edges);
577 const T sign = (area > T(0)) ? T(1) : T(-1);
581 prism.
clip(a_ray, a_n,
dot(a_n, a_p0) + a_radius);
582 prism.
clip(a_ray, -a_n, -
dot(a_n, a_p0) + a_radius);
587 const T len = side.
length();
590 prism.
clip(a_ray, side / len,
dot(side / len, a_a));
598 p.
unite(RayDetail::capsulePiece(a_ray, a_a, a_b, a_radius));
652 m_inverseDirection(T(1) / a_ray.m_direction[0], T(1) / a_ray.m_direction[1], T(1) / a_ray.m_direction[2]),
665 entry(
const T (&a_lo)[3],
const T (&a_hi)[3])
const noexcept
672 return BVH::QueryDetail::slabEntry<T>(lo, hi, o, inv,
m_tMin);
688 for (
size_t k = 0; k < K; k++) {
707 const T lo[3] = {a_row.m_lo[0][a_k], a_row.m_lo[1][a_k], a_row.m_lo[2][a_k]};
708 const T hi[3] = {a_row.m_hi[0][a_k], a_row.m_hi[1][a_k], a_row.m_hi[2][a_k]};
710 return this->
entry(lo, hi);
722 const Vec3T<T>& l = a_box.getLowCorner();
723 const Vec3T<T>& h = a_box.getHighCorner();
725 const T lo[3] = {l[0], l[1], l[2]};
726 const T hi[3] = {h[0], h[1], h[2]};
728 return this->
entry(lo, hi);
793 uint32_t last = first;
798 if (
m_out[last] > a_out) {
808 m_out[first] = a_out;
811 const uint32_t removed = last - first - 1U;
813 for (uint32_t k = first + 1U; k + removed <
m_count; k++) {
837 for (uint32_t k =
m_count; k > first; k--) {
844 m_out[first] = a_out;
892template <
class T,
size_t K,
size_t W>
908 template <
class State,
class Face,
class Bound>
917 const Bound& a_bound)
noexcept
919 const auto bvh = a_mesh.getRoot();
920 const auto groups = bvh.getPrimitives();
922 const auto leaf = [&groups, &a_face](State& a_s,
size_t a_offset,
size_t a_count)
noexcept {
923 for (
size_t i = a_offset; i < a_offset + a_count; i++) {
924 const auto& group = groups[
static_cast<uint32_t
>(i)];
926 for (
size_t lane = 0; lane < W; lane++) {
927 const Vec3T<T> v[3] = {group.getVertex(lane, 0), group.getVertex(lane, 1), group.getVertex(lane, 2)};
929 const auto edges = [&v](
const auto& a_f)
noexcept {
935 const auto distance2 = [&group, lane](
const Vec3T<T>& a_point)
noexcept {
936 const T d = group.signedDistanceAt(
static_cast<uint32_t
>(lane), a_point);
941 a_face(a_s, group.getNormal(lane), v[0], edges, distance2, group.getFaceId(lane));
946 bvh.traverse(
GrownRayQuery<T>(a_ray, a_tMin, a_grow), a_state, leaf, a_bound);
955template <
class T,
size_t K>
971 template <
class State,
class Face,
class Bound>
980 const Bound& a_bound)
noexcept
982 const auto bvh = a_mesh.getRoot();
983 const auto mesh = a_mesh.getMesh();
984 const auto faceIds = bvh.getPrimitives();
986 const auto leaf = [&faceIds, &mesh, &a_face](State& a_s,
size_t a_offset,
size_t a_count)
noexcept {
987 for (
size_t i = a_offset; i < a_offset + a_count; i++) {
988 const uint32_t
id = faceIds[
static_cast<uint32_t
>(i)];
990 MeshFaces::visit(mesh,
id, a_s, a_face);
994 bvh.traverse(
GrownRayQuery<T>(a_ray, a_tMin, a_grow), a_state, leaf, a_bound);
1007 template <
class Mesh,
class State,
class Face>
1010 visit(
const Mesh& a_mesh,
const uint32_t a_id, State& a_state,
const Face& a_face)
noexcept
1012 const auto& face = a_mesh.getFace(a_id);
1014 const auto edges = [&a_mesh, &face](
const auto& a_f)
noexcept {
1016 const auto& edge = a_mesh.getEdge(iter());
1018 a_f(edge.getVertex(a_mesh).getPosition(), edge.getNextEdge(a_mesh).getVertex(a_mesh).getPosition());
1022 const auto distance2 = [&a_mesh, &face](
const Vec3T<T>& a_point)
noexcept {
1023 return face.unsignedDistance2(a_point, a_mesh);
1026 a_face(a_state, face.getNormal(), face.getCentroid(), edges, distance2, a_id);
1046 template <
class State,
class Face,
class Bound>
1055 const Bound& )
noexcept
1057 const auto mesh = a_mesh.getMesh();
1059 for (uint32_t i = 0; i < mesh.numFaces(); i++) {
1106template <
class T,
class S>
1117 const auto& a_edges,
1118 const auto& a_distance2,
1119 const uint32_t a_id)
noexcept {
1120 if (a_state.m_inside) {
1126 bool inSlab =
false;
1128 const bool entered =
1129 RayDetail::offsetFaceEntry(a_ray, a_n, a_p0, a_edges, a_radius, a_tMin, a_state.m_t, t,
normal, inSlab);
1132 if (inSlab && a_distance2(a_ray.at(a_tMin)) <= a_radius * a_radius) {
1133 a_state.m_inside =
true;
1134 a_state.m_t = a_tMin;
1141 a_state.m_face = a_id;
1142 a_state.m_normal =
normal;
1146 const auto bound = [](
const NearestOffsetFace<T>& a_state)
noexcept -> T {
return a_state.m_t; };
1165template <
class T,
class S>
1176 a_union.m_count = 0;
1177 a_union.m_horizon = a_tMax;
1182 const auto& a_edges,
1184 const uint32_t )
noexcept {
1185 const Piece<T> p = RayDetail::offsetFacePiece(a_ray, a_n, a_p0, a_edges, a_radius);
1187 if (p.
hit() && p.
m_out >= a_tMin && p.
m_in <= a_state.m_horizon) {
1192 const auto bound = [](
const OffsetFaceUnion<T>& a_state)
noexcept -> T {
return a_state.m_horizon; };
1211template <
class T,
class S>
1220 const bool a_firstOnly,
1223 RayDetail::shapeSpans(a_mesh, a_ray, a_tMin, a_tMax, a_options, a_firstOnly, a_spans);
1243template <
class T,
size_t K,
size_t W>
1253template <
class T,
size_t K>
1272template <
class T,
class C>
1284template <
class T,
bool IsAnnulus,
class C>
1285struct DeferredOperand<Fused::Node<Fused::ShiftOp<T, IsAnnulus>, C>, std::enable_if_t<IsMeshLevel<C>::value>>
1297template <
class S,
class =
void>
1312 static constexpr bool Convex =
true;
1325 return RayDetail::ballPiece(a_ray, a_shape.getCenter(), a_shape.getRadius() + a_level);
1339 static constexpr bool Convex =
true;
1352 return RayDetail::capsulePiece(a_ray, a_shape.getCenter1(), a_shape.getCenter2(), a_shape.getRadius() + a_level);
1366 static constexpr bool Convex =
true;
1379 return RayDetail::tubePiece(
1380 a_ray, a_shape.getCenter(),
Vec3T<T>::unit(a_shape.getAxis()), a_shape.getRadius() + a_level);
1394 static constexpr bool Convex =
true;
1409 p.
clip(a_ray, a_shape.getNormal(),
dot(a_shape.getNormal(), a_shape.getPoint()) + a_level);
1425 static constexpr bool Convex =
true;
1438 const Vec3T<T>& lo = a_shape.getLowCorner();
1439 const Vec3T<T>& hi = a_shape.getHighCorner();
1441 if (a_level > T(0)) {
1442 return RayDetail::roundedBoxPiece(a_ray, lo, hi, a_level);
1447 return RayDetail::boxPiece(a_ray, lo + shrink, hi - shrink);
1475template <
class T,
size_t K,
size_t W>
1485template <
class T,
size_t K>
1504template <
class S,
class =
void>
1514struct HasLevelForm<S, std::void_t<decltype(LevelForm<S>::Convex)>> : std::true_type
1524template <
class T,
class C>
1525struct LevelForm<Fused::Node<Fused::AffineOp<T>, C>, std::enable_if_t<HasLevelForm<C>::value>>
1530 static constexpr bool Convex =
false;
1535 static constexpr bool Mesh =
false;
1582 const T f =
m_shape.signedDistance(a_point);
1607struct IsComposition<
LevelView<S>> : std::bool_constant<CalledOutOfLine<S>>
1622template <
class T,
class S>
1674 const RayT<T>& a_ray,
const T a_t,
const Vec3T<T>& a_normal,
const bool a_entering,
const uint32_t a_primitive)
1701template <
class T,
class S>
1706 const Vec3T<T> n = RayDetail::gradientNormal(a_view.
m_shape, a_point, a_h);
1708 return (a_view.
m_annulus && RayDetail::valueAt(a_view.
m_shape, a_point) < T(0)) ? -n : n;
1712template <
class T,
class S>
1716levelSpans(
const LevelView<S>& a_view,
1736struct RayForm<RayDetail::LevelView<S>, std::enable_if_t<RayDetail::HasLevelForm<S>::value>>
1763 if constexpr (Form::Convex) {
1766 const int n = RayDetail::convexLevelSpans(a_view, a_ray, spans);
1768 for (
int i = 0; i < n; i++) {
1771 if (s.
m_in >= a_tMin && s.
m_in <= a_tMax) {
1772 return RayDetail::levelHitAt(a_ray, s.
m_in, s.
m_nIn,
true, 0U);
1776 return RayDetail::levelHitAt(a_ray, s.
m_out, s.
m_nOut,
false, 0U);
1782 else if constexpr (Form::Mesh) {
1783 if (a_view.m_annulus || a_view.m_level ==
T(0)) {
1784 if (a_view.m_level ==
T(0) && !a_view.m_annulus) {
1785 return RayDetail::shapeHit(a_view.m_shape, a_ray, a_tMin, a_tMax, a_options);
1788 return annulusHit(a_view, a_ray, a_tMin, a_tMax);
1794 [&a_view, &a_ray, &a_options](
const T a_t0,
const T a_t1,
const bool a_all,
RaySpansT<T>& a_spans)
noexcept {
1795 RayDetail::levelSpans(a_view, a_ray, a_t0, a_t1, a_options, !a_all, a_spans);
1798 const auto resolve = [&a_view, &a_ray, &a_options](
const T a_t,
const uint32_t a_leaf)
noexcept {
1800 return RayDetail::leafHit(a_view.m_shape, a_ray, a_t, a_options);
1803 return annulusLeafHit(
View{a_view.
m_shape, std::abs(a_view.m_level),
true}, a_ray, a_t, a_options);
1806 return RayDetail::traceSpans(trace, resolve, a_ray, a_tMin, a_tMax);
1809 const auto& map = a_view.m_shape.layout().m_op;
1814 const auto inner = mappedView(a_view);
1853 if constexpr (Form::Convex) {
1856 const int n = RayDetail::convexLevelSpans(a_view, a_ray, spans);
1858 a_spans.reset(a_tMax);
1860 for (
int i = 0; i < n; i++) {
1861 a_spans.addClipped(spans[i].m_in, spans[i].m_out, a_tMin, a_tMax);
1864 else if constexpr (Form::Mesh) {
1865 const T level = a_view.m_level;
1867 if (!a_view.m_annulus && level ==
T(0)) {
1868 RayDetail::meshSpans(a_view.m_shape, a_ray, a_tMin, a_tMax, a_options, a_firstOnly, a_spans);
1873 if (a_view.m_annulus) {
1874 annulusSpans(a_view, a_ray, a_tMin, a_tMax, a_firstOnly, a_spans);
1881 const View faces{a_view.
m_shape, std::abs(level),
true};
1886 RayDetail::meshSpans(a_view.m_shape, a_ray, a_tMin, a_tMax, a_options, a_firstOnly, a_spans);
1887 annulusSpans(faces, a_ray, a_tMin, a_spans.m_horizon, a_firstOnly, grown);
1888 RayDetail::nameLeaf(1U, grown);
1889 RayDetail::uniteInto(a_spans, grown);
1892 RayDetail::keepFirst(a_spans);
1896 RayDetail::meshSpans(a_view.m_shape, a_ray, a_tMin, a_tMax, a_options,
false, a_spans);
1897 annulusSpans(faces, a_ray, a_tMin, a_spans.m_horizon,
false, grown);
1898 RayDetail::nameLeaf(1U, grown);
1899 RayDetail::complement(grown, a_tMin, scratch);
1900 RayDetail::intersectInto(a_spans, scratch, grown);
1904 const auto& map = a_view.m_shape.layout().m_op;
1909 RayDetail::shapeSpans(
1910 mappedView(a_view), mapped.
m_ray, mapped.
m_t0, mapped.
m_t1, a_options, a_firstOnly, a_spans);
1911 RayDetail::mapBack(mapped, a_tMin, a_tMax, a_spans);
1923 mappedView(
const View& a_view)
noexcept
1925 const auto& op = a_view.m_shape.layout().m_op;
1926 const auto operand = RayDetail::fusedOperand<0>(a_view.m_shape);
1929 operand, a_view.
m_level / op.m_valueScale, a_view.m_annulus};
1942 static inline HitT<T>
1943 annulusHit(
const View& a_view,
const RayT<T>& a_ray,
const T a_tMin,
const T a_tMax)
noexcept
1945 if (!(a_view.m_level > T(0))) {
1949 const RayDetail::NearestOffsetFace<T> found =
1950 RayDetail::nearestOffsetFace(a_view.m_shape, a_ray, a_tMin, a_tMax, a_view.m_level);
1952 if (!found.m_inside) {
1953 return (found.m_face == UINT32_MAX) ? HitT<T>()
1954 : RayDetail::
levelHitAt(a_ray, found.m_t, found.m_normal, true, found.m_face);
1957 RayDetail::OffsetFaceUnion<T> merged;
1959 RayDetail::offsetFaceUnion(a_view.m_shape, a_ray, a_tMin, a_tMax, a_view.m_level, merged);
1961 if (merged.m_count > 0U && merged.m_out[0] < merged.m_horizon) {
1962 return RayDetail::levelHitAt(a_ray, merged.m_out[0], merged.m_nOut[0],
false, 0U);
1967 if (merged.m_horizon < a_tMax) {
1969 hit.m_t = merged.m_horizon;
1986 static inline HitT<T>
1987 annulusLeafHit(
const View& a_view,
const RayT<T>& a_ray,
const T a_t,
const RayOptions<T>& a_options)
noexcept
1989 const auto box = a_view.computeBoundingVolume();
1990 const T width = a_options.m_tolerance * RayDetail::scaleOf(box.getLowCorner(), box.getHighCorner(), a_options);
1992 HitT<T> hit = annulusHit(a_view, a_ray, a_t - width, a_t + width);
1995 hit.m_normal = RayDetail::levelNormal(a_view, a_ray.at(a_t), width);
2013 annulusSpans(
const View& a_view,
2014 const RayT<T>& a_ray,
2017 const bool a_firstOnly,
2018 RaySpansT<T>& a_spans)
noexcept
2020 a_spans.reset(a_tMax);
2022 if (!(a_view.m_level > T(0))) {
2027 const RayDetail::NearestOffsetFace<T> found =
2028 RayDetail::nearestOffsetFace(a_view.m_shape, a_ray, a_tMin, a_tMax, a_view.m_level);
2030 if (!found.m_inside) {
2031 if (found.m_face != UINT32_MAX) {
2032 a_spans.add(SpanEndT<T>{found.m_t, 0U,
SpanEndT<T>::Exact}, RayDetail::openAt(found.m_t));
2034 a_spans.m_horizon = found.m_t;
2041 RayDetail::OffsetFaceUnion<T> merged;
2043 RayDetail::offsetFaceUnion(a_view.m_shape, a_ray, a_tMin, a_tMax, a_view.m_level, merged);
2045 merged.toSpans(a_tMin, a_spans);
2049namespace RayDetail {
2066template <
class T,
class S>
2075 const bool a_firstOnly,
2096template <
class T,
class S>
2100levelSpansWithin(
const LevelView<S>& a_view,
2105 const bool a_firstOnly,
2108 const T horizon = a_within.m_horizon * a_scale;
2110 a_spans.reset(horizon);
2114 for (uint32_t i = 0; i < a_within.m_count && a_within.m_spans[i].m_in.m_t * a_scale <= horizon; i++) {
2115 const T t0 = a_within.
m_spans[i].
m_in.m_t * a_scale;
2116 const T t1 =
Math::min(a_within.m_spans[i].m_out.m_t * a_scale, horizon);
2118 RayDetail::levelSpans(a_view, a_ray, t0, t1, a_options, a_firstOnly, piece);
2131 if (a_spans.m_horizon <= t1) {
2149template <
class T,
class S>
2153levelHit(
const LevelView<S>& a_view,
2154 const RayT<T>& a_ray,
2157 const RayOptions<T>& a_options)
noexcept
2159 return RayForm<LevelView<S>>
::firstHit(a_view, a_ray, a_tMin, a_tMax, a_options);
2176template <
class T,
class S>
2180levelLeafHit(
const LevelView<S>& a_view,
const RayT<T>& a_ray,
const T a_t,
const RayOptions<T>& a_options)
noexcept
2182 const auto box = a_view.computeBoundingVolume();
2183 const T width = a_options.m_tolerance * RayDetail::scaleOf(box.getLowCorner(), box.getHighCorner(), a_options);
2187 T from = a_t - width;
2190 for (
int k = 0; k < 3; k++) {
2191 const HitT<T> hit = RayDetail::levelHit(a_view, a_ray, from, a_t + width, a_options);
2197 if (!nearest.hit() || std::abs(hit.m_t - a_t) < std::abs(nearest.m_t - a_t)) {
2201 if (hit.m_t >= a_t) {
2205 from = hit.m_t + T(1e-3) * width;
2208 if (!nearest.hit()) {
2209 nearest.m_normal = RayDetail::levelNormal(a_view, a_ray.at(a_t), width);
2224template <
class T,
bool IsAnnulus,
class C>
2225struct RayForm<Fused::
Node<Fused::ShiftOp<T, IsAnnulus>, C>, std::enable_if_t<RayDetail::HasLevelForm<C>::value>>
2245 return RayDetail::levelHit(view(a_shape), a_ray, a_tMin, a_tMax, a_options);
2268 RayDetail::levelSpans(view(a_shape), a_ray, a_tMin, a_tMax, a_options, a_firstOnly, a_spans);
2279 view(
const Node& a_shape)
noexcept
2281 return RayDetail::LevelView<C>{RayDetail::fusedOperand<0>(a_shape), a_shape.layout().m_op.m_amount, IsAnnulus};
File containing various analytic signed distance fields.
What PackedBVH::traverse() tracks through a tree: query types, the child-box rows they test,...
Declaration of iterators for DCEL surface tessellations.
Fused CSG: the operations of the expression builder (EBGeometry_Expr.hpp) as types,...
#define EBGEOMETRY_DEVICE_NOINLINE
Keep a function out of line in the device pass (CUDA/HIP); nothing on the host.
Definition EBGeometry_GPU.hpp:110
#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.
Declaration of signed distance functions for DCEL meshes.
The span arithmetic that traces a composition along a ray: each operand's spans (where the ray is ins...
Ray queries on any shape: where a ray, or the segment between two points, first crosses its surface (...
Axis-aligned bounding box (AABB) enclosing a set of 3D points.
Definition EBGeometry_BoundingVolumes.hpp:37
Vec3T< T > & getLowCorner() noexcept
Get a modifiable reference to the low corner of the AABB.
Vec3T< T > & getHighCorner() noexcept
Get a modifiable reference to the high corner of the AABB.
Signed distance field for an axis-aligned box (AABB).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:351
Signed distance field for a capsule (pill shape): a cylinder capped with hemispheres.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1117
Half-edge iterator class for navigating the half edge mesh.
Definition EBGeometry_DCEL_Iterator.hpp:51
bool ok() const noexcept
Function which checks if the iteration can be continued.
Signed distance function for a DCEL mesh. Does not use BVHs.
Definition EBGeometry_MeshDistanceFunctions.hpp:79
A fused composition: an operation applied to its operands, itself a shape (isShape).
Definition EBGeometry_Fused.hpp:313
Signed distance field for an infinitely long cylinder.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:947
A FlatMeshSDF must be trivially copyable: that is what lets a rebasedView() be byte-copied into a dev...
Definition EBGeometry_MeshDistanceFunctions.hpp:249
Signed distance function for a plane.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:60
Signed distance field for a sphere.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:199
Signed distance function for a pure triangle mesh using SoA-grouped primitives in a compact (lineariz...
Definition EBGeometry_MeshDistanceFunctions.hpp:514
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:258
T length() const noexcept
Compute vector length.
static constexpr Vec3T< T > ones() noexcept
Return a vector with x = y = z = 1.
static constexpr Vec3T< T > unit(const size_t a_dir) noexcept
Return the unit basis vector for the given coordinate axis.
static constexpr Vec3T< T > zeros() noexcept
Return a vector with x = y = z = 0.
AffineCoefficients< T > affineCoefficients(const Affine3T< T > &a_map) noexcept
An affine map's coefficients, laid out as affinePoint() reads them.
Definition EBGeometry_CSGOps.hpp:389
constexpr T clamp(const T &a_value, const T &a_lo, const T &a_hi) noexcept
A value limited to [lo, hi].
Definition EBGeometry_Math.hpp:78
constexpr T max(const T &a_a, const T &a_b) noexcept
The larger of two values.
Definition EBGeometry_Math.hpp:61
constexpr T min(const T &a_a, const T &a_b) noexcept
The smaller of two values.
Definition EBGeometry_Math.hpp:44
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
T length(const Vec2T< T > &v) noexcept
Euclidean length of a 2D vector.
typename ExprDetail::ShapeInfo< S >::precision ShapePrecision
The precision of a shape type: T for a shape whose box type is AABBT<T>.
Definition EBGeometry_Expr.hpp:158
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.
Vec3T< T > normal(const F &a_function, const Vec3T< T > &a_point, const T &a_delta) noexcept
Outward unit normal of a function's level set, by central finite differences.
DistanceQuality
How far the value of a signed distance function can be trusted, from strongest to weakest.
Definition EBGeometry_DistanceQuality.hpp:25
@ Bound
The value's magnitude never exceeds the distance to the surface: it may underestimate,...
@ Unresolved
The query ran out of steps or passes before it could decide (a ray grazing the surface,...
@ Miss
The ray does not cross the surface in the interval.
@ Hit
The ray crosses the surface; HitT says where.
HitT< T > firstHit(const S &a_shape, const RayT< T > &a_ray, typename RayT< T >::Scalar a_tMin, typename RayT< T >::Scalar a_tMax, const RayOptions< T > &a_options=RayOptions< T >()) noexcept
The first crossing of a shape's surface along a ray, entering or leaving.
Fixed-size array with host- and device-callable members.
Definition EBGeometry_Array.hpp:33
The boxes of the K children of one interior node, in SoA layout: m_lo[axis][child] and m_hi[axis][chi...
Definition EBGeometry_BVHQuery.hpp:47
An affine map's 12 coefficients: the three rows of its matrix, then its shift.
Definition EBGeometry_CSGOps.hpp:373
T m_values[12]
Row 0, row 1 and row 2 of the matrix, then the shift.
Definition EBGeometry_CSGOps.hpp:377
Where a ray first crosses a surface.
Definition EBGeometry_Ray.hpp:96
bool m_entering
Whether the ray enters the object there (it was outside just before), rather than leaving it.
Definition EBGeometry_Ray.hpp:129
bool m_exact
Whether the crossing is exact (found by a ray form), rather than found to within RayOptions::m_tolera...
Definition EBGeometry_Ray.hpp:135
bool hit() const noexcept
Whether the ray crosses the surface.
T m_t
Distance along the ray: of the crossing for a hit, of the last point reached for an unresolved query,...
Definition EBGeometry_Ray.hpp:106
Vec3T< T > m_normal
The outward unit normal at the crossing: from the shape's ray form, or the normalized gradient of its...
Definition EBGeometry_Ray.hpp:124
uint32_t m_primitive
The finest element the shape can name at the crossing: the face of a mesh SDF, the deciding leaf of a...
Definition EBGeometry_Ray.hpp:118
HitStatus m_status
Whether the ray crosses the surface.
Definition EBGeometry_Ray.hpp:100
Vec3T< T > m_point
The point at m_t (for a hit or an unresolved query).
Definition EBGeometry_Ray.hpp:111
Numeric limits, with the meanings of the std::numeric_limits members of the same names.
Definition EBGeometry_Math.hpp:91
Whether an intersection traces a fused node's operand only within the spans of its other operands,...
Definition EBGeometry_CSGRayForms.hpp:180
A BVH ray query whose boxes are grown by a radius: what a mesh's offset faces are walked with.
Definition EBGeometry_OffsetRayForms.hpp:612
GrownRayQuery(const RayT< T > &a_ray, const T a_tMin, const T a_grow) noexcept
The query along a ray.
Definition EBGeometry_OffsetRayForms.hpp:650
Array< T, K > keys(const BVH::ChildBoxes< T, K > &a_row) const noexcept
Where the ray enters the K grown child boxes.
Definition EBGeometry_OffsetRayForms.hpp:684
Vec3T< T > m_inverseDirection
1 / direction, per component.
Definition EBGeometry_OffsetRayForms.hpp:631
T key(const BVH::ChildBoxes< T, K > &a_row, const size_t a_k) const noexcept
Where the ray enters one grown child box.
Definition EBGeometry_OffsetRayForms.hpp:705
T m_tMin
Start of the ray.
Definition EBGeometry_OffsetRayForms.hpp:636
Vec3T< T > m_origin
Ray origin.
Definition EBGeometry_OffsetRayForms.hpp:626
T entry(const T(&a_lo)[3], const T(&a_hi)[3]) const noexcept
Where the ray enters a grown box.
Definition EBGeometry_OffsetRayForms.hpp:665
T m_grow
How much each box is grown.
Definition EBGeometry_OffsetRayForms.hpp:641
T key(const BoundingVolumes::AABBT< T > &a_box) const noexcept
Where the ray enters a grown box.
Definition EBGeometry_OffsetRayForms.hpp:720
T Scalar
Floating-point precision.
Definition EBGeometry_OffsetRayForms.hpp:616
T Key
Key type: a distance along the ray.
Definition EBGeometry_OffsetRayForms.hpp:621
Whether a shape's level sets are a mesh's (its faces offset), or a fused affine map of one: costly to...
Definition EBGeometry_OffsetRayForms.hpp:1234
A level set of a shape, {f <= c}, or an annulus of it, {f <= c} less {f < -c}: a shape whose ray form...
Definition EBGeometry_OffsetRayForms.hpp:1547
T m_level
The level c: the offset, or the annulus's half-thickness.
Definition EBGeometry_OffsetRayForms.hpp:1566
S m_shape
The shape.
Definition EBGeometry_OffsetRayForms.hpp:1561
T signedDistance(const Vec3T< T > &a_point) const noexcept
The value: f - c, or |f| - c.
Definition EBGeometry_OffsetRayForms.hpp:1580
ShapePrecision< S > T
Floating-point precision.
Definition EBGeometry_OffsetRayForms.hpp:1551
static constexpr DistanceQuality distanceQuality
The quality of its value: the operand's.
Definition EBGeometry_OffsetRayForms.hpp:1556
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's box, grown by the level.
Definition EBGeometry_OffsetRayForms.hpp:1593
bool m_annulus
Whether this is an annulus.
Definition EBGeometry_OffsetRayForms.hpp:1571
A ray seen through an affine map, with the interval it is traced over: what the operand of the map is...
Definition EBGeometry_RaySpans.hpp:437
RayT< T > m_ray
The mapped ray, with a unit direction.
Definition EBGeometry_RaySpans.hpp:441
T m_t1
End of the interval, along the mapped ray.
Definition EBGeometry_RaySpans.hpp:456
T m_t0
Start of the interval, along the mapped ray.
Definition EBGeometry_RaySpans.hpp:451
T m_scale
Distance along the mapped ray per distance along the original.
Definition EBGeometry_RaySpans.hpp:446
static void walk(const FlatMeshSDF< T > &a_mesh, const RayT< T > &, const T, const T, State &a_state, const Face &a_face, const Bound &) noexcept
Walk every face.
Definition EBGeometry_OffsetRayForms.hpp:1049
static void walk(const MeshSDF< T, K > &a_mesh, const RayT< T > &a_ray, const T a_tMin, const T a_grow, State &a_state, const Face &a_face, const Bound &a_bound) noexcept
Walk the faces whose boxes, grown by a_grow, the ray enters before the bound.
Definition EBGeometry_OffsetRayForms.hpp:974
static void visit(const Mesh &a_mesh, const uint32_t a_id, State &a_state, const Face &a_face) noexcept
Call a_face for one DCEL face.
Definition EBGeometry_OffsetRayForms.hpp:1010
static void walk(const TriMeshSDF< T, K, W > &a_mesh, const RayT< T > &a_ray, const T a_tMin, const T a_grow, State &a_state, const Face &a_face, const Bound &a_bound) noexcept
Walk the faces whose boxes, grown by a_grow, the ray enters before the bound.
Definition EBGeometry_OffsetRayForms.hpp:911
How a mesh's faces are walked along a ray, each given as its normal, a point in its plane,...
Definition EBGeometry_OffsetRayForms.hpp:883
What a mesh's nearest offset-face walk finds.
Definition EBGeometry_OffsetRayForms.hpp:1072
T m_t
The nearest entry at or after the start, or the end of the interval.
Definition EBGeometry_OffsetRayForms.hpp:1076
Vec3T< T > m_normal
Its outward normal.
Definition EBGeometry_OffsetRayForms.hpp:1086
uint32_t m_face
Its face, or UINT32_MAX.
Definition EBGeometry_OffsetRayForms.hpp:1081
bool m_inside
Whether an offset face holds the start: the ray starts inside the grown surface.
Definition EBGeometry_OffsetRayForms.hpp:1091
The union of the offset faces a ray meets, as disjoint spans merged as they come, at most Capacity: a...
Definition EBGeometry_OffsetRayForms.hpp:741
T m_out[Capacity]
Exits.
Definition EBGeometry_OffsetRayForms.hpp:755
uint32_t m_count
How many are held.
Definition EBGeometry_OffsetRayForms.hpp:765
Vec3T< T > m_nOut[Capacity]
Outward normals at the exits, of the piece each exit is on.
Definition EBGeometry_OffsetRayForms.hpp:760
T m_horizon
The union is known on [t0, m_horizon].
Definition EBGeometry_OffsetRayForms.hpp:770
void insert(T a_in, T a_out, Vec3T< T > a_nOut) noexcept
Take a piece.
Definition EBGeometry_OffsetRayForms.hpp:780
T m_in[Capacity]
Entries.
Definition EBGeometry_OffsetRayForms.hpp:750
static constexpr uint32_t Capacity
Most spans held.
Definition EBGeometry_OffsetRayForms.hpp:745
void toSpans(const T a_t0, RaySpansT< T > &a_spans) const noexcept
The union as a list over [a_t0, horizon].
Definition EBGeometry_OffsetRayForms.hpp:859
Where a ray is inside a convex piece: [m_in, m_out], with the outward normals there; empty if m_in > ...
Definition EBGeometry_OffsetRayForms.hpp:54
T m_out
Where it leaves.
Definition EBGeometry_OffsetRayForms.hpp:63
bool hit() const noexcept
Whether the ray meets the piece.
Definition EBGeometry_OffsetRayForms.hpp:81
Vec3T< T > m_nOut
Outward normal where it leaves.
Definition EBGeometry_OffsetRayForms.hpp:73
T m_in
Where the ray enters.
Definition EBGeometry_OffsetRayForms.hpp:58
void clip(const RayT< T > &a_ray, const Vec3T< T > &a_n, const T a_d) noexcept
Clip to the half-space n . x <= d.
Definition EBGeometry_OffsetRayForms.hpp:110
Vec3T< T > m_nIn
Outward normal where it enters.
Definition EBGeometry_OffsetRayForms.hpp:68
void unite(const Piece &a_other) noexcept
Unite with another piece, the union being convex: the nearer entry and the farther exit.
Definition EBGeometry_OffsetRayForms.hpp:143
static Piece empty() noexcept
An empty piece.
Definition EBGeometry_OffsetRayForms.hpp:92
How a query marches, where a shape has no ray form.
Definition EBGeometry_Ray.hpp:155
A span: where the ray enters, and where it leaves.
Definition EBGeometry_Ray.hpp:258
SpanEndT< T > m_out
Where it leaves.
Definition EBGeometry_Ray.hpp:267
SpanEndT< T > m_in
Where the ray enters.
Definition EBGeometry_Ray.hpp:262
Where a ray is inside an object over an interval [t0, t1]: its spans, in order, each from where it en...
Definition EBGeometry_Ray.hpp:248
uint32_t m_count
How many are held.
Definition EBGeometry_Ray.hpp:278
T m_horizon
The list is complete on [t0, m_horizon]: nothing about the object beyond it is known.
Definition EBGeometry_Ray.hpp:283
Span m_spans[Capacity]
The spans, in order and disjoint.
Definition EBGeometry_Ray.hpp:273
A ray: the points origin + t * direction.
Definition EBGeometry_Ray.hpp:54
Vec3T< T > at(T a_t) const noexcept
The point at a distance along the ray.
One end of a span: where a ray enters or leaves an object.
Definition EBGeometry_Ray.hpp:200
@ Exact
A crossing found exactly, by a ray form.
Definition EBGeometry_Ray.hpp:207