EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_CSGRayForms.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
18#ifndef EBGEOMETRY_CSGRAYFORMS_HPP
19#define EBGEOMETRY_CSGRAYFORMS_HPP
20
21// Std includes
22#include <cstddef>
23#include <cstdint>
24#include <type_traits>
25#include <utility>
26
27// Our includes
30#include "EBGeometry_CSGOps.hpp"
31#include "EBGeometry_Fused.hpp"
33#include "EBGeometry_Ray.hpp"
34
35namespace EBGeometry {
36
37namespace Fused {
38
39namespace Detail {
40
46template <class Op>
47struct TracedExactly : std::false_type
48{
49};
50
55template <bool IsUnion>
56struct TracedExactly<CombineOp<IsUnion>> : std::true_type
57{
58};
59
63template <>
64struct TracedExactly<ComplementOp> : std::true_type
65{
66};
67
72template <class T>
73struct TracedExactly<AffineOp<T>> : std::true_type
74{
75};
76
77} // namespace Detail
78
79} // namespace Fused
80
81namespace RayDetail {
82
88template <class S>
89struct IsTracedFused : std::false_type
90{
91};
92
98template <class Op, class... Cs>
99struct IsTracedFused<Fused::Node<Op, Cs...>> : Fused::Detail::TracedExactly<Op>
100{
101};
102
109template <class S>
111{
115 static constexpr uint32_t value = 1;
116};
117
123template <class Op, class... Cs>
124struct LeafCount<Fused::Node<Op, Cs...>>
125{
129 static constexpr uint32_t value = Fused::Detail::TracedExactly<Op>::value ? (LeafCount<Cs>::value + ...) : 1U;
130};
131
139template <size_t I, class... Cs>
141
147template <class C, class... Cs>
148struct FirstLeaf<0, C, Cs...>
149{
153 static constexpr uint32_t value = 0;
154};
155
162template <size_t I, class C, class... Cs>
163struct FirstLeaf<I, C, Cs...>
164{
168 static constexpr uint32_t value = LeafCount<C>::value + FirstLeaf<I - 1, Cs...>::value;
169};
170
178template <class C, class = void>
179struct DeferredOperand : std::false_type
180{
181};
182
193template <class C, class T>
195{
199 static constexpr int value = (HasRayFirstHit<C, T>::value && !DeferredOperand<C>::value) ? 0 : 1;
200};
201
207template <class D, class T>
208struct MarchedOperand<Fused::Node<Fused::ComplementOp, D>, T>
209{
213 static constexpr int value = (HasRayFirstHit<D, T>::value && !DeferredOperand<D>::value) ? 0 : 2;
214};
215
223template <class T, class... Cs>
225{
229 static constexpr bool found = false;
230
234 static constexpr size_t value = 0;
235};
236
243template <class T, class C, class... Cs>
244struct FirstTraced<T, C, Cs...>
245{
249 static constexpr bool found = MarchedOperand<C, T>::value == 0 || FirstTraced<T, Cs...>::found;
250
254 static constexpr size_t value =
255 MarchedOperand<C, T>::value == 0 ? 0 : (FirstTraced<T, Cs...>::found ? 1 + FirstTraced<T, Cs...>::value : 0);
256};
257
267template <size_t I, class Op, class... Cs>
268[[nodiscard]] EBGEOMETRY_HOST_DEVICE
269inline auto
271{
272 using C = typename Fused::Detail::TypeAt<I, Cs...>::type;
273
274 return CSGDetail::fromStored<C>(Fused::Detail::get<I>(a_node.layout().m_operands), a_node.location());
275}
276
292template <size_t I, class T, class Op, class... Cs>
294inline void
296 const RayT<T>& a_ray,
297 const T a_t0,
298 const T a_t1,
299 const RayOptions<T>& a_options,
300 const bool a_firstOnly,
301 RaySpansT<T>& a_spans) noexcept
302{
303 using C = typename Fused::Detail::TypeAt<I, Cs...>::type;
304
305 RayDetail::shapeSpans(RayDetail::fusedOperand<I>(a_node), a_ray, a_t0, a_t1, a_options, a_firstOnly, a_spans);
306
307 if constexpr (IsTracedFused<C>::value) {
308 RayDetail::offsetLeaves(FirstLeaf<I, Cs...>::value, a_spans);
309 }
310 else {
311 RayDetail::nameLeaf(FirstLeaf<I, Cs...>::value, a_spans);
312 }
313}
314
331template <size_t I, class T, class Op, class... Cs>
333inline void
335 const RayT<T>& a_ray,
336 const T a_t0,
337 const RayOptions<T>& a_options,
338 const bool a_firstOnly,
339 RaySpansT<T>& a_spans,
340 RaySpansT<T>& a_operand) noexcept
341{
342 if constexpr (I < sizeof...(Cs)) {
343 RayDetail::fusedOperandSpans<I>(a_node, a_ray, a_t0, a_spans.m_horizon, a_options, a_firstOnly, a_operand);
344 RayDetail::uniteInto(a_spans, a_operand);
345
346 if (a_firstOnly) {
347 RayDetail::keepFirst(a_spans);
348 }
349
350 RayDetail::fusedUnite<I + 1>(a_node, a_ray, a_t0, a_options, a_firstOnly, a_spans, a_operand);
351 }
352}
353
375template <size_t I, bool Marched, size_t Skip, class T, class Op, class... Cs>
377inline void
379 const RayT<T>& a_ray,
380 const T a_t0,
381 const RayOptions<T>& a_options,
382 const bool a_firstOnly,
383 RaySpansT<T>& a_spans,
384 RaySpansT<T>& a_operand,
385 RaySpansT<T>& a_scratch) noexcept
386{
387 if constexpr (I < sizeof...(Cs)) {
388 using C = typename Fused::Detail::TypeAt<I, Cs...>::type;
389
390 constexpr int kind = MarchedOperand<C, T>::value;
391
392 if constexpr (I != Skip && (kind != 0) == Marched) {
393 if constexpr (kind == 1) {
394 RayDetail::spansWithin(
395 RayDetail::fusedOperand<I>(a_node), a_ray, a_spans, a_options, a_firstOnly, a_scratch, a_operand);
396 RayDetail::nameLeaf(FirstLeaf<I, Cs...>::value, a_operand);
397 RayDetail::intersectInto(a_spans, a_operand, a_scratch);
398 }
399 else if constexpr (kind == 2) {
400 // All the complemented operand's spans within the list: its complement there is the same. The trace
401 // uses a_scratch as its scratch, which the complement then overwrites.
402 RayDetail::spansWithin(RayDetail::fusedOperand<0>(RayDetail::fusedOperand<I>(a_node)),
403 a_ray,
404 a_spans,
405 a_options,
406 false,
407 a_scratch,
408 a_operand);
409 RayDetail::nameLeaf(FirstLeaf<I, Cs...>::value, a_operand);
410 RayDetail::complement(a_operand, a_t0, a_scratch);
411 RayDetail::intersectInto(a_spans, a_scratch, a_operand);
412 }
413 else {
414 RayDetail::fusedOperandSpans<I>(a_node, a_ray, a_t0, a_spans.m_horizon, a_options, false, a_operand);
415 RayDetail::intersectInto(a_spans, a_operand, a_scratch);
416 }
417 }
418
419 RayDetail::fusedIntersect<I + 1, Marched, Skip>(
420 a_node, a_ray, a_t0, a_options, a_firstOnly, a_spans, a_operand, a_scratch);
421 }
422}
423
438template <size_t I, class T, class Op, class... Cs>
439[[nodiscard]] EBGEOMETRY_HOST_DEVICE
440inline HitT<T>
442 const RayT<T>& a_ray,
443 const T a_t,
444 const uint32_t a_leaf,
445 const RayOptions<T>& a_options) noexcept
446{
447 using C = typename Fused::Detail::TypeAt<I, Cs...>::type;
448
449 if constexpr (IsTracedFused<C>::value) {
450 return RayForm<C>::leafHit(
451 RayDetail::fusedOperand<I>(a_node), a_ray, a_t, a_leaf - FirstLeaf<I, Cs...>::value, a_options);
452 }
453 else {
454 return RayDetail::leafHit(RayDetail::fusedOperand<I>(a_node), a_ray, a_t, a_options);
455 }
456}
457
473template <class T, class Op, class... Cs, size_t... Is>
474[[nodiscard]] EBGEOMETRY_HOST_DEVICE
475inline HitT<T>
477 const RayT<T>& a_ray,
478 const T a_t,
479 const uint32_t a_leaf,
480 const RayOptions<T>& a_options,
481 std::index_sequence<Is...>) noexcept
482{
483 HitT<T> hit;
484
485 const auto holds = [a_leaf](const uint32_t a_first, const uint32_t a_count) noexcept {
486 return a_leaf >= a_first && a_leaf < a_first + a_count;
487 };
488
490 ? (hit = RayDetail::fusedOperandLeafHit<Is>(a_node, a_ray, a_t, a_leaf, a_options), true)
491 : false) ||
492 ...);
493
494 return hit;
495}
496
497} // namespace RayDetail
498
510template <class Op, class... Cs>
511struct RayForm<Fused::Node<Op, Cs...>, std::enable_if_t<Fused::Detail::TracedExactly<Op>::value>>
512{
516 using Node = Fused::Node<Op, Cs...>;
517
521 using T = typename Node::T;
522
532 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
533 static inline HitT<T>
534 firstHit(const Node& a_shape, const RayT<T>& a_ray, T a_tMin, T a_tMax, const RayOptions<T>& a_options) noexcept
535 {
536 const auto trace =
537 [&a_shape, &a_ray, &a_options](const T a_t0, const T a_t1, const bool a_all, RaySpansT<T>& a_spans) noexcept {
538 spans(a_shape, a_ray, a_t0, a_t1, a_options, !a_all, a_spans);
539 };
540
541 const auto resolve = [&a_shape, &a_ray, &a_options](const T a_t, const uint32_t a_leaf) noexcept {
542 return leafHit(a_shape, a_ray, a_t, a_leaf, a_options);
543 };
544
545 HitT<T> hit = RayDetail::traceSpans(trace, resolve, a_ray, a_tMin, a_tMax);
546
547 hit.m_primitive = 0U;
548
549 return hit;
550 }
551
564 static inline void
565 spans(const Node& a_shape,
566 const RayT<T>& a_ray,
567 T a_tMin,
568 T a_tMax,
569 const RayOptions<T>& a_options,
570 bool a_firstOnly,
571 RaySpansT<T>& a_spans) noexcept
572 {
573 if constexpr (std::is_same_v<Op, Fused::UnionOp>) {
574 RaySpansT<T> operand;
575
576 RayDetail::fusedOperandSpans<0>(a_shape, a_ray, a_tMin, a_tMax, a_options, a_firstOnly, a_spans);
577
578 if (a_firstOnly) {
579 RayDetail::keepFirst(a_spans);
580 }
581
582 RayDetail::fusedUnite<1>(a_shape, a_ray, a_tMin, a_options, a_firstOnly, a_spans, operand);
583 }
584 else if constexpr (std::is_same_v<Op, Fused::IntersectionOp>) {
585 // An intersection needs all of each traced operand's spans: where the first one ends, the ray may still
586 // be inside the others. The marched ones go last, marched only where the others leave the intersection
587 // open.
588 constexpr size_t first = RayDetail::FirstTraced<T, Cs...>::value;
589
590 RaySpansT<T> operand;
591 RaySpansT<T> scratch;
592
593 RayDetail::fusedOperandSpans<first>(a_shape, a_ray, a_tMin, a_tMax, a_options, false, a_spans);
594 RayDetail::fusedIntersect<0, false, first>(
595 a_shape, a_ray, a_tMin, a_options, a_firstOnly, a_spans, operand, scratch);
596 RayDetail::fusedIntersect<0, true, first>(
597 a_shape, a_ray, a_tMin, a_options, a_firstOnly, a_spans, operand, scratch);
598 }
599 else if constexpr (std::is_same_v<Op, Fused::ComplementOp>) {
600 RaySpansT<T> operand;
601
602 RayDetail::fusedOperandSpans<0>(a_shape, a_ray, a_tMin, a_tMax, a_options, false, operand);
603 RayDetail::complement(operand, a_tMin, a_spans);
604 }
605 else {
606 const CSGOps::AffineCoefficients<T> map = CSGOps::affineCoefficients(a_shape.layout().m_op.m_map);
607 const RayDetail::MappedRay<T> mapped = RayDetail::mapRay(map.m_values, a_ray, a_tMin, a_tMax);
608
609 RayDetail::fusedOperandSpans<0>(a_shape, mapped.m_ray, mapped.m_t0, mapped.m_t1, a_options, a_firstOnly, a_spans);
610 RayDetail::mapBack(mapped, a_tMin, a_tMax, a_spans);
611 }
612 }
613
624 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
625 static inline HitT<T>
626 leafHit(const Node& a_shape, const RayT<T>& a_ray, T a_t, uint32_t a_leaf, const RayOptions<T>& a_options) noexcept
627 {
628 if constexpr (std::is_same_v<Op, Fused::UnionOp> || std::is_same_v<Op, Fused::IntersectionOp> ||
629 std::is_same_v<Op, Fused::ComplementOp>) {
630 return RayDetail::fusedLeafHit(a_shape, a_ray, a_t, a_leaf, a_options, std::index_sequence_for<Cs...>{});
631 }
632 else {
633 const CSGOps::AffineCoefficients<T> map = CSGOps::affineCoefficients(a_shape.layout().m_op.m_map);
634 const RayDetail::MappedRay<T> mapped = RayDetail::mapRay(map.m_values, a_ray, a_t, a_t);
635
636 HitT<T> hit = RayDetail::fusedLeafHit(
637 a_shape, mapped.m_ray, mapped.m_t0, a_leaf, a_options, std::index_sequence_for<Cs...>{});
638
639 hit.m_normal = RayDetail::mapNormalBack(map.m_values, hit.m_normal);
640
641 return hit;
642 }
643 }
644};
645
659template <class T, class P, size_t K>
660struct RayForm<BVHUnion<T, P, K>>
661{
671 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
672 static inline HitT<T>
674 const BVHUnion<T, P, K>& a_shape, const RayT<T>& a_ray, T a_tMin, T a_tMax, const RayOptions<T>& a_options) noexcept
675 {
676 const auto trace =
677 [&a_shape, &a_ray, &a_options](const T a_t0, const T a_t1, const bool a_all, RaySpansT<T>& a_spans) noexcept {
678 spans(a_shape, a_ray, a_t0, a_t1, a_options, !a_all, a_spans);
679 };
680
681 const auto resolve = [&a_shape, &a_ray, &a_options](const T a_t, const uint32_t a_leaf) noexcept {
682 return leafHit(a_shape, a_ray, a_t, a_leaf, a_options);
683 };
684
685 return RayDetail::traceSpans(trace, resolve, a_ray, a_tMin, a_tMax);
686 }
687
700 static inline void
701 spans(const BVHUnion<T, P, K>& a_shape,
702 const RayT<T>& a_ray,
703 T a_tMin,
704 T a_tMax,
705 const RayOptions<T>& a_options,
706 bool a_firstOnly,
707 RaySpansT<T>& a_spans) noexcept
708 {
709 using Root = typename BVHUnion<T, P, K>::Root;
710
711 a_spans.reset(a_tMax);
712
713 RaySpansT<T> operand;
714
715 const PoolLocation location = a_shape.location();
716 const Root bvh = a_shape.getBVH();
717 const auto unbounded = a_shape.getUnboundedPrimitives();
718 const auto primitives = bvh.getPrimitives();
719
720 // Each primitive is traced only up to what the union so far is known up to, beyond which it can change
721 // nothing known.
722 const auto add = [&a_ray, a_tMin, &a_options, a_firstOnly, &location, &operand](
723 RaySpansT<T>& a_union, const CSGDetail::Stored<P>& a_primitive, const uint32_t a_leaf) noexcept {
724 RayDetail::shapeSpans(CSGDetail::fromStored<P>(a_primitive, location),
725 a_ray,
726 a_tMin,
727 a_union.m_horizon,
728 a_options,
729 a_firstOnly,
730 operand);
731 RayDetail::nameLeaf(a_leaf, operand);
732 RayDetail::uniteInto(a_union, operand);
733
734 if (a_firstOnly) {
735 RayDetail::keepFirst(a_union);
736 }
737 };
738
739 for (uint32_t i = 0; i < unbounded.size(); i++) {
740 add(a_spans, unbounded[i], i);
741 }
742
743 const uint32_t numUnbounded = unbounded.size();
744
745 const auto leaf =
746 [&primitives, &add, numUnbounded](RaySpansT<T>& a_union, const size_t a_offset, const size_t a_count) noexcept {
747 for (size_t i = a_offset; i < a_offset + a_count; i++) {
748 add(a_union, primitives[static_cast<uint32_t>(i)], numUnbounded + static_cast<uint32_t>(i));
749 }
750 };
751
752 // A box the ray enters beyond what the union is known up to can change nothing known.
753 const auto bound = [](const RaySpansT<T>& a_union) noexcept -> T { return a_union.m_horizon; };
754
755 bvh.traverse(BVH::RayQuery<T>(a_ray.m_origin, a_ray.m_direction, a_tMin), a_spans, leaf, bound);
756 }
757
767 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
768 static inline HitT<T>
770 const RayT<T>& a_ray,
771 T a_t,
772 uint32_t a_leaf,
773 const RayOptions<T>& a_options) noexcept
774 {
775 const PoolLocation location = a_shape.location();
776 const auto unbounded = a_shape.getUnboundedPrimitives();
777
778 const auto primitives = a_shape.getBVH().getPrimitives();
779
780 const CSGDetail::Stored<P> stored =
781 (a_leaf < unbounded.size()) ? unbounded[a_leaf] : primitives[a_leaf - unbounded.size()];
782
783 // The hit names the member crossed, not what the member would name (a mesh's face): a union's parts are
784 // its members, as a tape's are its leaves.
785 HitT<T> hit = RayDetail::leafHit(CSGDetail::fromStored<P>(stored, location), a_ray, a_t, a_options);
786
787 hit.m_primitive = a_leaf;
788
789 return hit;
790 }
791};
792
793} // namespace EBGeometry
794
795// The ray forms of the offsets and annuli, which build on these: whoever has the fused operations' ray forms
796// has theirs too. Included last, since that header includes this one.
798
799#endif
Ray forms (see RayForm) for the analytic shapes that have a closed-form crossing: PlaneSDF,...
BVH-accelerated unions of many primitives of one type: BVHUnion and BVHSmoothUnion.
The arithmetic of each CSG operation, shared by the Tape's evaluator and the fused operations.
auto fusedOperand(const Fused::Node< Op, Cs... > &a_node) noexcept
Operand I of a fused node, as the shape it is.
Definition EBGeometry_CSGRayForms.hpp:270
HitT< T > fusedOperandLeafHit(const Fused::Node< Op, Cs... > &a_node, const RayT< T > &a_ray, const T a_t, const uint32_t a_leaf, const RayOptions< T > &a_options) noexcept
The crossing at a distance along a ray on one of operand I's leaves of a fused node.
Definition EBGeometry_CSGRayForms.hpp:441
HitT< T > fusedLeafHit(const Fused::Node< Op, Cs... > &a_node, const RayT< T > &a_ray, const T a_t, const uint32_t a_leaf, const RayOptions< T > &a_options, std::index_sequence< Is... >) noexcept
The crossing at a distance along a ray on a leaf of a fused node: in the operand holding the leaf.
Definition EBGeometry_CSGRayForms.hpp:476
void fusedIntersect(const Fused::Node< Op, Cs... > &a_node, const RayT< T > &a_ray, const T a_t0, const RayOptions< T > &a_options, const bool a_firstOnly, RaySpansT< T > &a_spans, RaySpansT< T > &a_operand, RaySpansT< T > &a_scratch) noexcept
Intersect a fused node's operands I, I + 1, ... other than operand Skip into a list: those it traces,...
Definition EBGeometry_CSGRayForms.hpp:378
void fusedOperandSpans(const Fused::Node< Op, Cs... > &a_node, const RayT< T > &a_ray, const T a_t0, const T a_t1, const RayOptions< T > &a_options, const bool a_firstOnly, RaySpansT< T > &a_spans) noexcept
Operand I's list of a fused node, its crossings named among the node's leaves.
Definition EBGeometry_CSGRayForms.hpp:295
void fusedUnite(const Fused::Node< Op, Cs... > &a_node, const RayT< T > &a_ray, const T a_t0, const RayOptions< T > &a_options, const bool a_firstOnly, RaySpansT< T > &a_spans, RaySpansT< T > &a_operand) noexcept
Unite a fused node's operands I, I + 1, ... into a list.
Definition EBGeometry_CSGRayForms.hpp:334
Fused CSG: the operations of the expression builder (EBGeometry_Expr.hpp) as types,...
#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
The ray forms (see RayForm) of the mesh SDFs. TriMeshSDF: its BVH walked along the ray (PackedBVH::tr...
Ray forms of offsets and annuli: the level sets of their operands' values.
Ray queries on any shape: where a ray, or the segment between two points, first crosses its surface (...
BVH-accelerated union of many primitives of one type.
Definition EBGeometry_BVHUnion.hpp:178
Forward declaration of the linearised BVH, defined below.
Definition EBGeometry_PackedBVH.hpp:357
A fused composition: an operation applied to its operands, itself a shape (isShape).
Definition EBGeometry_Fused.hpp:313
ShapePrecision< typename Detail::TypeAt< 0, Cs... >::type > T
Floating-point precision.
Definition EBGeometry_Fused.hpp:321
typename StoredAs< P >::type Stored
Shorthand for the type a BVH union stores for a primitive of type P.
Definition EBGeometry_BVHUnion.hpp:73
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
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
A ray tracked through a BVH: the key of a box is the distance along the ray at which it enters the bo...
Definition EBGeometry_BVHQuery.hpp:286
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
An affine map (translation, rotation, scaling, reflection, or a composition of them): the operand's v...
Definition EBGeometry_Fused.hpp:709
Union or intersection: the minimum or the maximum of the operands' values, in order.
Definition EBGeometry_Fused.hpp:455
Complement: -v, inside and outside swapped.
Definition EBGeometry_Fused.hpp:656
Whether a fused operation is traced exactly from its operands' spans: union, intersection (and so dif...
Definition EBGeometry_CSGRayForms.hpp:48
Type I of a list of types.
Definition EBGeometry_Fused.hpp:144
Where a ray first crosses a surface.
Definition EBGeometry_Ray.hpp:96
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
Where a pool-resident descriptor resolves its offsets, and the rules for moving it.
Definition EBGeometry_Pool.hpp:99
Whether an intersection traces a fused node's operand only within the spans of its other operands,...
Definition EBGeometry_CSGRayForms.hpp:180
The first leaf of operand I among a fused node's leaves.
Definition EBGeometry_CSGRayForms.hpp:140
The first of a fused node's operands an intersection does not march, which it traces first: 0 if it m...
Definition EBGeometry_CSGRayForms.hpp:225
static constexpr size_t value
The operand.
Definition EBGeometry_CSGRayForms.hpp:234
static constexpr bool found
Whether there is one.
Definition EBGeometry_CSGRayForms.hpp:229
Whether a shape is a fused node traced from its operands' spans.
Definition EBGeometry_CSGRayForms.hpp:90
How many leaves a shape has, as a fused composition numbers the crossings of its operands: its operan...
Definition EBGeometry_CSGRayForms.hpp:111
static constexpr uint32_t value
The count.
Definition EBGeometry_CSGRayForms.hpp:115
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
Whether an intersection marches (or defers, see DeferredOperand) a fused node's operand,...
Definition EBGeometry_CSGRayForms.hpp:195
static constexpr int value
The kind.
Definition EBGeometry_CSGRayForms.hpp:199
static HitT< T > leafHit(const BVHUnion< T, P, K > &a_shape, const RayT< T > &a_ray, T a_t, uint32_t a_leaf, const RayOptions< T > &a_options) noexcept
The crossing at a distance along a ray on one of the union's primitives.
Definition EBGeometry_CSGRayForms.hpp:769
static void spans(const BVHUnion< T, P, K > &a_shape, const RayT< T > &a_ray, T a_tMin, T a_tMax, const RayOptions< T > &a_options, bool a_firstOnly, RaySpansT< T > &a_spans) noexcept
Where a ray is inside the union over an interval, each crossing named by its primitive: the unbounded...
Definition EBGeometry_CSGRayForms.hpp:701
static HitT< T > firstHit(const BVHUnion< T, P, K > &a_shape, const RayT< T > &a_ray, T a_tMin, T a_tMax, const RayOptions< T > &a_options) noexcept
The first crossing of the union along a ray.
Definition EBGeometry_CSGRayForms.hpp:673
static void spans(const Node &a_shape, const RayT< T > &a_ray, T a_tMin, T a_tMax, const RayOptions< T > &a_options, bool a_firstOnly, RaySpansT< T > &a_spans) noexcept
Where a ray is inside the composition over an interval, its crossings named by the leaves they lie on...
Definition EBGeometry_CSGRayForms.hpp:565
typename Node::T T
Floating-point precision.
Definition EBGeometry_CSGRayForms.hpp:521
static HitT< T > leafHit(const Node &a_shape, const RayT< T > &a_ray, T a_t, uint32_t a_leaf, const RayOptions< T > &a_options) noexcept
The crossing at a distance along a ray on one of the composition's leaves: its normal (outward of the...
Definition EBGeometry_CSGRayForms.hpp:626
static HitT< T > firstHit(const Node &a_shape, const RayT< T > &a_ray, T a_tMin, T a_tMax, const RayOptions< T > &a_options) noexcept
The first crossing of the composition along a ray.
Definition EBGeometry_CSGRayForms.hpp:534
How to ray trace a shape directly, instead of marching its signed distance.
Definition EBGeometry_Ray.hpp:347
How a query marches, where a shape has no ray form.
Definition EBGeometry_Ray.hpp:155
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
A ray: the points origin + t * direction.
Definition EBGeometry_Ray.hpp:54