18#ifndef EBGEOMETRY_CSGRAYFORMS_HPP
19#define EBGEOMETRY_CSGRAYFORMS_HPP
55template <
bool IsUnion>
98template <
class Op,
class... Cs>
115 static constexpr uint32_t
value = 1;
123template <
class Op,
class... Cs>
139template <
size_t I,
class... Cs>
147template <
class C,
class... Cs>
153 static constexpr uint32_t value = 0;
162template <
size_t I,
class C,
class... Cs>
178template <
class C,
class =
void>
193template <
class C,
class T>
207template <
class D,
class T>
223template <
class T,
class... Cs>
229 static constexpr bool found =
false;
243template <
class T,
class C,
class... Cs>
267template <
size_t I,
class Op,
class... Cs>
274 return CSGDetail::fromStored<C>(Fused::Detail::get<I>(a_node.layout().m_operands), a_node.location());
292template <
size_t I,
class T,
class Op,
class... Cs>
300 const bool a_firstOnly,
305 RayDetail::shapeSpans(RayDetail::fusedOperand<I>(a_node), a_ray, a_t0, a_t1, a_options, a_firstOnly, a_spans);
331template <
size_t I,
class T,
class Op,
class... Cs>
338 const bool a_firstOnly,
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);
347 RayDetail::keepFirst(a_spans);
350 RayDetail::fusedUnite<I + 1>(a_node, a_ray, a_t0, a_options, a_firstOnly, a_spans, a_operand);
375template <
size_t I,
bool Marched,
size_t Skip,
class T,
class Op,
class... Cs>
382 const bool a_firstOnly,
387 if constexpr (I <
sizeof...(Cs)) {
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);
397 RayDetail::intersectInto(a_spans, a_operand, a_scratch);
399 else if constexpr (kind == 2) {
402 RayDetail::spansWithin(RayDetail::fusedOperand<0>(RayDetail::fusedOperand<I>(a_node)),
410 RayDetail::complement(a_operand, a_t0, a_scratch);
411 RayDetail::intersectInto(a_spans, a_scratch, a_operand);
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);
419 RayDetail::fusedIntersect<I + 1, Marched, Skip>(
420 a_node, a_ray, a_t0, a_options, a_firstOnly, a_spans, a_operand, a_scratch);
438template <
size_t I,
class T,
class Op,
class... Cs>
444 const uint32_t a_leaf,
454 return RayDetail::leafHit(RayDetail::fusedOperand<I>(a_node), a_ray, a_t, a_options);
473template <
class T,
class Op,
class... Cs,
size_t... Is>
479 const uint32_t a_leaf,
481 std::index_sequence<Is...>)
noexcept
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;
490 ? (hit = RayDetail::fusedOperandLeafHit<Is>(a_node, a_ray, a_t, a_leaf, a_options),
true)
510template <
class Op,
class... Cs>
511struct RayForm<Fused::
Node<Op, Cs...>, std::enable_if_t<Fused::Detail::TracedExactly<Op>::value>>
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);
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);
545 HitT<T> hit = RayDetail::traceSpans(trace, resolve, a_ray, a_tMin, a_tMax);
573 if constexpr (std::is_same_v<Op, Fused::UnionOp>) {
576 RayDetail::fusedOperandSpans<0>(a_shape, a_ray, a_tMin, a_tMax, a_options, a_firstOnly, a_spans);
579 RayDetail::keepFirst(a_spans);
582 RayDetail::fusedUnite<1>(a_shape, a_ray, a_tMin, a_options, a_firstOnly, a_spans, operand);
584 else if constexpr (std::is_same_v<Op, Fused::IntersectionOp>) {
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);
599 else if constexpr (std::is_same_v<Op, Fused::ComplementOp>) {
602 RayDetail::fusedOperandSpans<0>(a_shape, a_ray, a_tMin, a_tMax, a_options,
false, operand);
603 RayDetail::complement(operand, a_tMin, a_spans);
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);
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...>{});
636 HitT<T> hit = RayDetail::fusedLeafHit(
637 a_shape, mapped.
m_ray, mapped.
m_t0, a_leaf, a_options, std::index_sequence_for<Cs...>{});
659template <
class T,
class P,
size_t K>
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);
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);
685 return RayDetail::traceSpans(trace, resolve, a_ray, a_tMin, a_tMax);
711 a_spans.reset(a_tMax);
716 const Root bvh = a_shape.getBVH();
717 const auto unbounded = a_shape.getUnboundedPrimitives();
718 const auto primitives = bvh.getPrimitives();
722 const auto add = [&a_ray, a_tMin, &a_options, a_firstOnly, &location, &operand](
724 RayDetail::shapeSpans(CSGDetail::fromStored<P>(a_primitive, location),
731 RayDetail::nameLeaf(a_leaf, operand);
732 RayDetail::uniteInto(a_union, operand);
735 RayDetail::keepFirst(a_union);
739 for (uint32_t i = 0; i < unbounded.size(); i++) {
740 add(a_spans, unbounded[i], i);
743 const uint32_t numUnbounded = unbounded.size();
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));
753 const auto bound = [](
const RaySpansT<T>& a_union)
noexcept -> T {
return a_union.m_horizon; };
755 bvh.traverse(
BVH::RayQuery<T>(a_ray.m_origin, a_ray.m_direction, a_tMin), a_spans, leaf, bound);
776 const auto unbounded = a_shape.getUnboundedPrimitives();
778 const auto primitives = a_shape.getBVH().getPrimitives();
781 (a_leaf < unbounded.size()) ? unbounded[a_leaf] : primitives[a_leaf - unbounded.size()];
785 HitT<T> hit = RayDetail::leafHit(CSGDetail::fromStored<P>(stored, location), a_ray, a_t, a_options);
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.
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
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
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