EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_Fused.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
27#ifndef EBGEOMETRY_FUSED_HPP
28#define EBGEOMETRY_FUSED_HPP
29
30// Std includes
31#include <cstddef>
32#include <cstdint>
33#include <type_traits>
34#include <utility>
35
36// Our includes
37#include "EBGeometry_Affine.hpp"
40#include "EBGeometry_CSGOps.hpp"
42#include "EBGeometry_Expr.hpp"
43#include "EBGeometry_GPU.hpp"
44#include "EBGeometry_Macros.hpp"
45#include "EBGeometry_Pool.hpp"
46#include "EBGeometry_Vec.hpp"
47
48namespace EBGeometry {
49
53namespace Fused {
54
59namespace Detail {
60
66template <class... Ss>
67struct Pack;
68
72template <>
73struct Pack<>
74{
75};
76
82template <class S, class... Rest>
83struct Pack<S, Rest...>
84{
89
93 Pack<Rest...> m_tail;
94};
95
104template <size_t I, class S, class... Rest>
105[[nodiscard]] EBGEOMETRY_HOST_DEVICE
106inline const auto&
107get(const Pack<S, Rest...>& a_pack) noexcept
108{
109 if constexpr (I == 0) {
110 return a_pack.m_head;
111 }
112 else {
113 return get<I - 1>(a_pack.m_tail);
114 }
115}
116
125template <size_t I, class S, class... Rest>
126[[nodiscard]] EBGEOMETRY_HOST_DEVICE
127inline auto&
128get(Pack<S, Rest...>& a_pack) noexcept
129{
130 if constexpr (I == 0) {
131 return a_pack.m_head;
132 }
133 else {
134 return get<I - 1>(a_pack.m_tail);
135 }
136}
137
143template <size_t I, class... Cs>
144struct TypeAt;
145
151template <class C, class... Rest>
152struct TypeAt<0, C, Rest...>
153{
157 using type = C;
158};
159
166template <size_t I, class C, class... Rest>
167struct TypeAt<I, C, Rest...>
168{
172 using type = typename TypeAt<I - 1, Rest...>::type;
173};
174
179template <class... Cs>
180inline constexpr bool anyPoolHandle = (isPoolHandle<Cs> || ...);
181
187template <class... Cs>
188[[nodiscard]] constexpr DistanceQuality
190{
191 const DistanceQuality qualities[] = {distanceQualityOf<Cs>...};
192
194
195 for (const DistanceQuality c : qualities) {
196 q = (static_cast<int>(c) > static_cast<int>(q)) ? c : q;
197 }
198
199 return q;
200}
201
206template <bool Handle>
207struct Base
208{
213 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
214 inline PoolLocation
215 location() const noexcept
216 {
217 return PoolLocation{};
218 }
219};
220
224template <>
225struct Base<true> : PoolHandle
226{
230 Base() noexcept = default;
231
237 explicit Base(const PoolLocation& a_location) noexcept : PoolHandle(a_location)
238 {}
239};
240
245template <class... Cs>
247{
252
257
261 static constexpr size_t count = sizeof...(Cs);
262
270 template <size_t I, class T>
271 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
272 inline T
273 value(const Vec3T<T>& a_point) const noexcept
274 {
275 using C = typename TypeAt<I, Cs...>::type;
276
277 if constexpr (isPoolHandle<C>) {
278 return C(get<I>(m_pack), m_location).signedDistance(a_point);
279 }
280 else {
281 return get<I>(m_pack).signedDistance(a_point);
282 }
283 }
284
290 template <size_t I>
291 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
292 inline auto
293 box() const
294 {
295 using C = typename TypeAt<I, Cs...>::type;
296
297 return CSGDetail::fromStored<C>(get<I>(m_pack), m_location).computeBoundingVolume();
298 }
299};
300
301} // namespace Detail
302
311template <class Op, class... Cs>
312class Node : public Detail::Base<Detail::anyPoolHandle<Cs...>>
313{
314public:
315 static_assert(sizeof...(Cs) > 0, "Fused::Node needs an operand");
316 static_assert((isShape<Cs> && ...), "Fused::Node: every operand must be a shape (see isShape)");
317
321 using T = ShapePrecision<typename Detail::TypeAt<0, Cs...>::type>;
322
323 static_assert((std::is_same_v<ShapePrecision<Cs>, T> && ...), "Fused::Node: the operands' precisions differ");
324
328 static constexpr bool isHandle = Detail::anyPoolHandle<Cs...>;
329
333 static constexpr DistanceQuality distanceQuality = Op::template quality<Cs...>();
334
351
355 Node() = delete;
356
361 template <bool H = isHandle, std::enable_if_t<!H, int> = 0>
363 explicit Node(const Layout& a_layout) noexcept : m_layout(a_layout)
364 {}
365
371 template <bool H = isHandle, std::enable_if_t<H, int> = 0>
373 Node(const Layout& a_layout, const PoolLocation& a_location) noexcept
374 : Detail::Base<true>(a_location), m_layout(a_layout)
375 {}
376
381 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
382 inline const Layout&
383 layout() const noexcept
384 {
385 return m_layout;
386 }
387
393 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
394 inline T
395 signedDistance(const Vec3T<T>& a_point) const noexcept
396 {
397 return m_layout.m_op.evaluate(this->operands(), a_point);
398 }
399
404 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
407 {
408 return m_layout.m_op.box(this->operands());
409 }
410
417 [[nodiscard]] EBGEOMETRY_HOST
418 inline Node
419 rebasedView(const Pool& a_pool) const noexcept;
420
427 [[nodiscard]] EBGEOMETRY_HOST
428 inline Node
429 deepCopy(Pool& a_dstPool) const;
430
431private:
435 Layout m_layout;
436
441 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
442 inline Detail::Operands<Cs...>
443 operands() const noexcept
444 {
445 return Detail::Operands<Cs...>{m_layout.m_operands, this->location()};
446 }
447};
448
453template <bool IsUnion>
455{
461 template <class... Cs>
462 [[nodiscard]] static constexpr DistanceQuality
463 quality() noexcept
464 {
465 return Detail::worstAndBound<Cs...>();
466 }
467
476 template <class O, class T>
477 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
478 inline T
479 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
480 {
481 return this->fold(a_operands, a_point, std::make_index_sequence<O::count - 1>{});
482 }
483
490 template <class O>
491 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
492 inline auto
493 box(const O& a_operands) const
494 {
495 return this->boxes(a_operands, std::make_index_sequence<O::count>{});
496 }
497
498private:
508 template <class O, class T, size_t... Is>
509 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
510 inline T
511 fold(const O& a_operands, const Vec3T<T>& a_point, std::index_sequence<Is...>) const noexcept
512 {
513 T value = a_operands.template value<0>(a_point);
514
515 if constexpr (IsUnion) {
516 ((value = Math::min(value, a_operands.template value<Is + 1>(a_point))), ...);
517 }
518 else {
519 ((value = Math::max(value, a_operands.template value<Is + 1>(a_point))), ...);
520 }
521
522 return value;
523 }
524
532 template <class O, size_t... Is>
533 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
534 inline auto
535 boxes(const O& a_operands, std::index_sequence<Is...>) const
536 {
537 using Box = decltype(a_operands.template box<0>());
538 using T = std::decay_t<decltype(a_operands.template box<0>().getLowCorner()[0])>;
539
540 Box box = IsUnion ? Box() : ExprDetail::everywhere<T>();
541
542 if constexpr (IsUnion) {
543 ((box = box.merged(a_operands.template box<Is>())), ...);
544 }
545 else {
546 ((box = ExprDetail::intersected(box, a_operands.template box<Is>())), ...);
547 }
548
549 return box;
550 }
551};
552
557
562
568template <class T, bool IsUnion>
570{
575
580
586 template <class... Cs>
587 [[nodiscard]] static constexpr DistanceQuality
588 quality() noexcept
589 {
590 return Detail::worstAndBound<Cs...>();
591 }
592
600 template <class O>
601 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
602 inline T
603 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
604 {
605 return this->blend(a_operands, a_point, std::make_index_sequence<O::count>{});
606 }
607
615 template <class O>
616 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
618 box(const O& a_operands) const
619 {
621
622 if constexpr (IsUnion) {
623 return ExprDetail::grown(box, m_exponential ? m_smooth * std::log(T(2)) : T(0.25) * m_smooth);
624 }
625 else {
626 return box;
627 }
628 }
629
630private:
639 template <class O, size_t... Is>
640 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
641 inline T
642 blend(const O& a_operands, const Vec3T<T>& a_point, std::index_sequence<Is...>) const noexcept
643 {
644 CSGOps::Pair<T> pair = CSGOps::pairInit<T>(!IsUnion);
645
646 (CSGOps::pairInsert(pair, a_operands.template value<Is>(a_point), !IsUnion), ...);
647
648 return CSGOps::pairBlend(pair, m_smooth, !IsUnion, m_exponential);
649 }
650};
651
656{
662 template <class C>
663 [[nodiscard]] static constexpr DistanceQuality
664 quality() noexcept
665 {
666 return distanceQualityOf<C>;
667 }
668
677 template <class O, class T>
678 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
679 inline T
680 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
681 {
682 return -a_operands.template value<0>(a_point);
683 }
684
691 template <class O>
692 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
693 inline auto
694 box(const O& a_operands) const
695 {
696 using T = std::decay_t<decltype(a_operands.template box<0>().getLowCorner()[0])>;
697
698 return ExprDetail::everywhere<T>();
699 }
700};
701
707template <class T>
709{
714
719
724
730 template <class C>
731 [[nodiscard]] static constexpr DistanceQuality
732 quality() noexcept
733 {
734 return distanceQualityOf<C>;
735 }
736
744 template <class O>
745 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
746 inline T
747 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
748 {
749 const T value = a_operands.template value<0>(CSGOps::affinePoint(m_map, a_point));
750
751 return (m_valueScale != T(1)) ? value * m_valueScale : value;
752 }
753
760 template <class O>
761 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
763 box(const O& a_operands) const
764 {
765 return m_inverse.transform(a_operands.template box<0>());
766 }
767};
768
773template <class T>
775{
780
786 template <class C>
787 [[nodiscard]] static constexpr DistanceQuality
788 quality() noexcept
789 {
790 return Detail::worstAndBound<C>();
791 }
792
800 template <class O>
801 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
802 inline T
803 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
804 {
805 return a_operands.template value<0>(CSGOps::elongatePoint(m_halfLengths, a_point));
806 }
807
814 template <class O>
815 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
817 box(const O& a_operands) const
818 {
819 return ExprDetail::grown(a_operands.template box<0>(), m_halfLengths);
820 }
821};
822
828template <class T, bool IsAnnulus>
830{
835
842 template <class C>
843 [[nodiscard]] static constexpr DistanceQuality
844 quality() noexcept
845 {
846 return IsAnnulus ? distanceQualityOf<C> : Detail::worstAndBound<C>();
847 }
848
856 template <class O>
857 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
858 inline T
859 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
860 {
861 const T value = a_operands.template value<0>(a_point);
862
863 if constexpr (IsAnnulus) {
864 return CSGOps::annular(value, m_amount);
865 }
866 else {
867 return CSGOps::offset(value, m_amount);
868 }
869 }
870
877 template <class O>
878 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
880 box(const O& a_operands) const
881 {
882 return ExprDetail::grown(a_operands.template box<0>(), Math::max(m_amount, T(0)));
883 }
884};
885
891template <class T>
893{
898
904 template <class C>
905 [[nodiscard]] static constexpr DistanceQuality
906 quality() noexcept
907 {
908 return Detail::worstAndBound<C>();
909 }
910
918 template <class O>
919 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
920 inline T
921 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
922 {
923 const auto f = [&a_operands](const Vec3T<T>& a_x) noexcept -> T { return a_operands.template value<0>(a_x); };
924
925 return CSGOps::repetition<T>(m_repetition, a_point, f);
926 }
927
934 template <class O>
935 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
937 box(const O& a_operands) const;
938};
939
944template <class T>
945struct BlurOp
946{
951
957 template <class C>
958 [[nodiscard]] static constexpr DistanceQuality
959 quality() noexcept
960 {
961 return Detail::worstAndBound<C>();
962 }
963
971 template <class O>
972 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
973 inline T
974 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
975 {
976 const auto f = [&a_operands](const Vec3T<T>& a_x) noexcept -> T { return a_operands.template value<0>(a_x); };
977
978 return CSGOps::blur(m_weights.m_values, a_point, f);
979 }
980
987 template <class O>
988 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
990 box(const O& a_operands) const
991 {
992 return ExprDetail::grown(a_operands.template box<0>(), std::sqrt(T(3)) * m_weights.m_values[0]);
993 }
994};
995
1002template <class T>
1004{
1009
1014
1020 template <class C>
1021 [[nodiscard]] static constexpr DistanceQuality
1022 quality() noexcept
1023 {
1024 return Detail::worstAndBound<C>();
1025 }
1026
1034 template <class O>
1035 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1036 inline T
1037 evaluate(const O& a_operands, const Vec3T<T>& a_point) const noexcept
1038 {
1039 if (m_identity) {
1040 return a_operands.template value<0>(a_point);
1041 }
1042
1043 const auto f = [&a_operands](const Vec3T<T>& a_x) noexcept -> T { return a_operands.template value<0>(a_x); };
1044
1045 return CSGOps::mollify(m_grid, a_point, f);
1046 }
1047
1054 template <class O>
1055 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1057 box(const O& a_operands) const
1058 {
1059 const BoundingVolumes::AABBT<T> box = a_operands.template box<0>();
1060
1061 return m_identity ? box : ExprDetail::grown(box, std::sqrt(T(3)) * m_grid.m_radius);
1062 }
1063};
1064
1070template <class... Cs>
1072{
1077};
1078
1085template <class... Cs>
1086[[nodiscard]] EBGEOMETRY_HOST
1087inline OperandList<Cs...>
1088operands(const Cs&... a_operands);
1089
1095template <class Op, class... Cs>
1096using NodeOf = Node<Op, Cs...>;
1097
1106template <class C, class... Cs>
1107[[nodiscard]] EBGEOMETRY_HOST
1108inline auto
1109Union(const C& a_first, const Cs&... a_others);
1110
1119template <class C, class... Cs>
1120[[nodiscard]] EBGEOMETRY_HOST
1121inline auto
1122Intersection(const C& a_first, const Cs&... a_others);
1123
1134template <class A, class B, class... Bs>
1135[[nodiscard]] EBGEOMETRY_HOST
1136inline auto
1137Difference(const A& a_first, const B& a_second, const Bs&... a_others);
1138
1145template <class C>
1146[[nodiscard]] EBGEOMETRY_HOST
1148Complement(const C& a_operand);
1149
1160template <class A, class B>
1161[[nodiscard]] EBGEOMETRY_HOST
1162inline Node<SmoothCombineOp<ShapePrecision<A>, true>, A, B>
1163SmoothUnion(const A& a_first,
1164 const B& a_second,
1165 const ShapePrecision<A> a_smooth,
1166 const BlendKind a_blend = BlendKind::Polynomial);
1167
1177template <class... Cs>
1178[[nodiscard]] EBGEOMETRY_HOST
1179inline auto
1181 const ShapePrecision<typename Detail::TypeAt<0, Cs...>::type> a_smooth,
1182 const BlendKind a_blend = BlendKind::Polynomial);
1183
1194template <class A, class B>
1195[[nodiscard]] EBGEOMETRY_HOST
1196inline Node<SmoothCombineOp<ShapePrecision<A>, false>, A, B>
1197SmoothIntersection(const A& a_first,
1198 const B& a_second,
1199 const ShapePrecision<A> a_smooth,
1200 const BlendKind a_blend = BlendKind::Polynomial);
1201
1210template <class... Cs>
1211[[nodiscard]] EBGEOMETRY_HOST
1212inline auto
1214 const ShapePrecision<typename Detail::TypeAt<0, Cs...>::type> a_smooth,
1215 const BlendKind a_blend = BlendKind::Polynomial);
1216
1227template <class A, class B>
1228[[nodiscard]] EBGEOMETRY_HOST
1229inline auto
1230SmoothDifference(const A& a_first,
1231 const B& a_second,
1232 const ShapePrecision<A> a_smooth,
1233 const BlendKind a_blend = BlendKind::Polynomial);
1234
1245template <class A, class... Bs>
1246[[nodiscard]] EBGEOMETRY_HOST
1247inline auto
1248SmoothDifference(const A& a_first,
1249 const OperandList<Bs...>& a_others,
1250 const ShapePrecision<A> a_smooth,
1251 const BlendKind a_blend = BlendKind::Polynomial);
1252
1260template <class C>
1261[[nodiscard]] EBGEOMETRY_HOST
1262inline auto
1263Translate(const C& a_operand, const Vec3T<ShapePrecision<C>>& a_shift);
1264
1273template <class C>
1274[[nodiscard]] EBGEOMETRY_HOST
1275inline auto
1276Rotate(const C& a_operand, const ShapePrecision<C> a_degrees, const size_t a_axis);
1277
1286template <class C>
1287[[nodiscard]] EBGEOMETRY_HOST
1288inline auto
1289Rotate(const C& a_operand, const ShapePrecision<C> a_degrees, const Vec3T<ShapePrecision<C>>& a_axis);
1290
1299template <class C>
1300[[nodiscard]] EBGEOMETRY_HOST
1301inline auto
1302Scale(const C& a_operand, const ShapePrecision<C> a_factor);
1303
1311template <class C>
1312[[nodiscard]] EBGEOMETRY_HOST
1313inline auto
1314Reflect(const C& a_operand, const size_t a_axis);
1315
1325template <class C>
1326[[nodiscard]] EBGEOMETRY_HOST
1327inline Node<ShiftOp<ShapePrecision<C>, false>, C>
1328Offset(const C& a_operand, const ShapePrecision<C> a_offset);
1329
1337template <class C>
1338[[nodiscard]] EBGEOMETRY_HOST
1339inline Node<ShiftOp<ShapePrecision<C>, true>, C>
1340Annular(const C& a_operand, const ShapePrecision<C> a_delta);
1341
1349template <class C>
1350[[nodiscard]] EBGEOMETRY_HOST
1352Elongate(const C& a_operand, const Vec3T<ShapePrecision<C>>& a_elongation);
1353
1364template <class C>
1365[[nodiscard]] EBGEOMETRY_HOST
1367FiniteRepetition(const C& a_operand,
1368 const Vec3T<ShapePrecision<C>>& a_period,
1369 const Vec3T<ShapePrecision<C>>& a_repeatLo,
1370 const Vec3T<ShapePrecision<C>>& a_repeatHi);
1371
1381template <class C>
1382[[nodiscard]] EBGEOMETRY_HOST
1384Blur(const C& a_operand, const ShapePrecision<C> a_blur, const ShapePrecision<C> a_alpha = ShapePrecision<C>(0.5));
1385
1395template <class C>
1396[[nodiscard]] EBGEOMETRY_HOST
1398Mollify(const C& a_operand, const ShapePrecision<C> a_dist, const size_t a_samples);
1399
1400} // namespace Fused
1401
1402} // namespace EBGeometry
1403
1404#include "EBGeometry_FusedImplem.hpp"
1405
1406// The ray forms of the fused operations and the BVH unions (and, through it, of the offsets): firstHit() is a
1407// template, and a file that included this header without them would march a composition that another file
1408// traces exactly, two definitions of one function. Included last, since that header includes this one.
1410
1411#endif
Declaration of Affine3T, an affine map of 3D space (a 3x3 matrix and a shift).
BVH-accelerated unions of many primitives of one type: BVHUnion and BVHSmoothUnion.
Declarations of bounding volume types used in bounding volume hierarchies.
The arithmetic of each CSG operation, shared by the Tape's evaluator and the fused operations.
The ray forms (see RayForm) of compositions: the fused union, intersection, difference,...
How far a function's value can be trusted as a distance: DistanceQuality, and the distanceQualityOf t...
The tape's front end: Expr, a host-side value that describes a composed object, and the free function...
GPU portability layer: host/device decoration macros and backend detection.
#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
#define EBGEOMETRY_HOST
Mark a function as callable from host code only (no-op on host compilers).
Definition EBGeometry_GPU.hpp:83
Utility macros for EBGeometry.
Growable bump arena for the GPU memory foundation.
Declaration of 2D and 3D point/vector classes with templated precision, and free functions on them.
Axis-aligned bounding box (AABB) enclosing a set of 3D points.
Definition EBGeometry_BoundingVolumes.hpp:37
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
Node(const Layout &a_layout) noexcept
A node from its layout, for a node with no pool-resident operand.
Definition EBGeometry_Fused.hpp:363
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance (see DistanceQuality).
Definition EBGeometry_Fused.hpp:333
static constexpr bool isHandle
Whether the node lives in a pool: whether one of its operands does.
Definition EBGeometry_Fused.hpp:328
Node(const Layout &a_layout, const PoolLocation &a_location) noexcept
A node from its layout and the location its pool-resident operands resolve against.
Definition EBGeometry_Fused.hpp:373
BoundingVolumes::AABBT< T > computeBoundingVolume() const
The composition's bounding box, by the rules of the expression builder.
Definition EBGeometry_Fused.hpp:406
Node rebasedView(const Pool &a_pool) const noexcept
The same node resolving against a mirror of its pool (see Pool::mirror()); a node with no pool-reside...
const Layout & layout() const noexcept
The node's layout.
Definition EBGeometry_Fused.hpp:383
T signedDistance(const Vec3T< T > &a_point) const noexcept
The composition's value at a point.
Definition EBGeometry_Fused.hpp:395
Node()=delete
Disallowed: build a node with a Fused:: function.
Node deepCopy(Pool &a_dstPool) const
A copy of the node whose pool-resident operands are copied into another pool; a node with no pool-res...
Base of every pool-resident handle: the one PoolLocation its arrays resolve against.
Definition EBGeometry_Pool.hpp:499
Growable bump arena over a MemoryResource.
Definition EBGeometry_Pool.hpp:183
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:258
Vec3T< T > elongatePoint(const Vec3T< T > &a_halfLengths, const Vec3T< T > &a_point) noexcept
The point an elongation evaluates its operand at: p - clamp(p, -h, h).
Definition EBGeometry_CSGOps.hpp:451
T offset(const T a_value, const T a_offset) noexcept
An offset's value: v - r, computed as v + (-r).
Definition EBGeometry_CSGOps.hpp:468
T annular(const T a_value, const T a_delta) noexcept
An annulus's value: |v| - delta, computed as |v| + (-delta).
Definition EBGeometry_CSGOps.hpp:483
auto mollify(const MollifyGrid< T > &a_grid, const Vec3T< T > &a_point, const F &a_operand) noexcept
A mollification's value: sum_k w_k f(p - o_k) over the grid's taps, each weight divided by the sum of...
Definition EBGeometry_CSGOps.hpp:836
T pairBlend(const Pair< T > &a_pair, const T a_smooth, const bool a_largest, const bool a_exponential) noexcept
The smooth minimum (or maximum) of a pair's two values.
Definition EBGeometry_CSGOps.hpp:603
void pairInsert(Pair< T > &a_pair, const T a_value, const bool a_largest) noexcept
Insert a value into a pair of extreme values.
Definition EBGeometry_CSGOps.hpp:547
Vec3T< T > affinePoint(const T *a_coefficients, const Vec3T< T > &a_point) noexcept
The point an affine map sends a query point to: the point the mapped object's operand sees.
Definition EBGeometry_CSGOps.hpp:415
auto blur(const T *a_weights, const Vec3T< T > &a_point, const F &a_operand) noexcept
A blur's value: the weighted sum of its operand's values at the 27 points p + d (i,...
Definition EBGeometry_CSGOps.hpp:682
constexpr DistanceQuality worstAndBound() noexcept
The worst distance quality among some operand types, and Bound (Exact < Bound < NotADistance).
Definition EBGeometry_Fused.hpp:189
const auto & get(const Pack< S, Rest... > &a_pack) noexcept
Operand I of a pack.
Definition EBGeometry_Fused.hpp:107
constexpr bool anyPoolHandle
Whether any of the operand types lives in a pool.
Definition EBGeometry_Fused.hpp:180
Node< ShiftOp< ShapePrecision< C >, false >, C > Offset(const C &a_operand, const ShapePrecision< C > a_offset)
Offset a shape's surface outward by a distance, v - r.
auto SmoothDifference(const A &a_first, const B &a_second, const ShapePrecision< A > a_smooth, const BlendKind a_blend=BlendKind::Polynomial)
Smooth difference A \ B: the smooth intersection of A and the complement of B.
auto Intersection(const C &a_first, const Cs &... a_others)
Intersection of shapes: the maximum of their values. One shape is returned as is.
Node< SmoothCombineOp< ShapePrecision< A >, false >, A, B > SmoothIntersection(const A &a_first, const B &a_second, const ShapePrecision< A > a_smooth, const BlendKind a_blend=BlendKind::Polynomial)
Smooth intersection of two shapes: a smooth maximum of their values.
auto Reflect(const C &a_operand, const size_t a_axis)
Reflect a shape in a coordinate plane through the origin.
OperandList< Cs... > operands(const Cs &... a_operands)
A list of operands for an n-ary smooth operation.
Node< BlurOp< ShapePrecision< C > >, C > Blur(const C &a_operand, const ShapePrecision< C > a_blur, const ShapePrecision< C > a_alpha=ShapePrecision< C >(0.5))
Blur a shape: a weighted average of its values at the 27 points p + d (i, j, k), i,...
Node< MollifyOp< ShapePrecision< C > >, C > Mollify(const C &a_operand, const ShapePrecision< C > a_dist, const size_t a_samples)
Mollify a shape: convolve it with a smooth bump kernel sampled on an n x n x n grid over [-r,...
Node< RepetitionOp< ShapePrecision< C > >, C > FiniteRepetition(const C &a_operand, const Vec3T< ShapePrecision< C > > &a_period, const Vec3T< ShapePrecision< C > > &a_repeatLo, const Vec3T< ShapePrecision< C > > &a_repeatHi)
Finite repetition: copies of a shape on a grid of tiles, the minimum over all of them (see EBGeometry...
Node< ElongateOp< ShapePrecision< C > >, C > Elongate(const C &a_operand, const Vec3T< ShapePrecision< C > > &a_elongation)
Elongate a shape: stretch it by inserting a box of half-lengths h at the origin.
Node< ComplementOp, C > Complement(const C &a_operand)
Complement: inside and outside swapped, -v.
auto Scale(const C &a_operand, const ShapePrecision< C > a_factor)
Scale a shape uniformly about the origin: |s| times its value at p / s.
Node< SmoothCombineOp< ShapePrecision< A >, true >, A, B > SmoothUnion(const A &a_first, const B &a_second, const ShapePrecision< A > a_smooth, const BlendKind a_blend=BlendKind::Polynomial)
Smooth union of two shapes: a smooth minimum of their values.
auto Translate(const C &a_operand, const Vec3T< ShapePrecision< C > > &a_shift)
Translate a shape by a shift.
auto Difference(const A &a_first, const B &a_second, const Bs &... a_others)
Difference A \ (B1 u B2 u ...): max(A, -min_i Bi).
auto Union(const C &a_first, const Cs &... a_others)
Union of shapes: the minimum of their values. One shape is returned as is.
Node< ShiftOp< ShapePrecision< C >, true >, C > Annular(const C &a_operand, const ShapePrecision< C > a_delta)
A shell around a shape's surface, |v| - delta.
auto Rotate(const C &a_operand, const ShapePrecision< C > a_degrees, const size_t a_axis)
Rotate a shape about a coordinate axis through the origin.
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
BlendKind
How a smooth union, intersection or difference blends the two extreme values.
Definition EBGeometry_Expr.hpp:42
@ Polynomial
SmoothMinOp/SmoothMaxOp: quadratic blend over a band of width s; deepens by at most s/4.
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
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,...
An affine map of 3D space, x -> A x + b, with A stored by rows.
Definition EBGeometry_Affine.hpp:37
A blur's distance and weights.
Definition EBGeometry_CSGOps.hpp:640
A mollification's tap grid: n taps per axis over [-r, r]^3, and the sum of their weights.
Definition EBGeometry_CSGOps.hpp:776
The two most extreme values seen so far, for an n-ary smooth union or intersection.
Definition EBGeometry_CSGOps.hpp:496
A finite repetition: copies of an object on a grid of tiles.
Definition EBGeometry_CSGOps.hpp:888
An affine map (translation, rotation, scaling, reflection, or a composition of them): the operand's v...
Definition EBGeometry_Fused.hpp:709
Affine3T< T > m_map
The map from a query point to the point the operand sees.
Definition EBGeometry_Fused.hpp:713
BoundingVolumes::AABBT< T > box(const O &a_operands) const
The box: the operand's, mapped by the inverse.
Definition EBGeometry_Fused.hpp:763
Affine3T< T > m_inverse
Its inverse, which maps the operand's box.
Definition EBGeometry_Fused.hpp:718
T m_valueScale
Value scale: |s| for a scaling by s, which keeps a distance a distance.
Definition EBGeometry_Fused.hpp:723
static constexpr DistanceQuality quality() noexcept
Distance quality: the operand's.
Definition EBGeometry_Fused.hpp:732
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:747
Blur: a weighted average of the operand's values at 27 points (CSGOps::blur()).
Definition EBGeometry_Fused.hpp:946
BoundingVolumes::AABBT< T > box(const O &a_operands) const
The box: the operand's, grown by sqrt(3) d.
Definition EBGeometry_Fused.hpp:990
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:974
static constexpr DistanceQuality quality() noexcept
Distance quality: a bound, unless the operand is not a distance.
Definition EBGeometry_Fused.hpp:959
CSGOps::BlurWeights< T > m_weights
Blur distance and weights.
Definition EBGeometry_Fused.hpp:950
Union or intersection: the minimum or the maximum of the operands' values, in order.
Definition EBGeometry_Fused.hpp:455
auto box(const O &a_operands) const
The box: the union, or the intersection, of the operands' boxes.
Definition EBGeometry_Fused.hpp:493
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:479
static constexpr DistanceQuality quality() noexcept
Distance quality: a bound at best.
Definition EBGeometry_Fused.hpp:463
Complement: -v, inside and outside swapped.
Definition EBGeometry_Fused.hpp:656
auto box(const O &a_operands) const
The box: everywhere.
Definition EBGeometry_Fused.hpp:694
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:680
static constexpr DistanceQuality quality() noexcept
Distance quality: the operand's.
Definition EBGeometry_Fused.hpp:664
Base() noexcept=default
An unset location.
A value node's base: no pool, and an unset location for the code that asks for one.
Definition EBGeometry_Fused.hpp:208
PoolLocation location() const noexcept
An unset location: a value node resolves nothing against a pool.
Definition EBGeometry_Fused.hpp:215
The operands of a node, with the location their pool-resident ones resolve against.
Definition EBGeometry_Fused.hpp:247
static constexpr size_t count
Number of operands.
Definition EBGeometry_Fused.hpp:261
const Pack< CSGDetail::Stored< Cs >... > & m_pack
The operands, as stored.
Definition EBGeometry_Fused.hpp:251
auto box() const
Operand I's bounding box.
Definition EBGeometry_Fused.hpp:293
T value(const Vec3T< T > &a_point) const noexcept
Operand I's value at a point.
Definition EBGeometry_Fused.hpp:273
PoolLocation m_location
The node's location.
Definition EBGeometry_Fused.hpp:256
S m_head
First operand.
Definition EBGeometry_Fused.hpp:88
Pack< Rest... > m_tail
The others.
Definition EBGeometry_Fused.hpp:93
The operands of a fused node, as stored: a recursive aggregate, so that it stays trivially copyable a...
Definition EBGeometry_Fused.hpp:67
C type
The type.
Definition EBGeometry_Fused.hpp:157
typename TypeAt< I - 1, Rest... >::type type
The type.
Definition EBGeometry_Fused.hpp:172
Type I of a list of types.
Definition EBGeometry_Fused.hpp:144
Elongation: the operand's value at p - clamp(p, -h, h).
Definition EBGeometry_Fused.hpp:775
BoundingVolumes::AABBT< T > box(const O &a_operands) const
The box: the operand's, grown by h.
Definition EBGeometry_Fused.hpp:817
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:803
Vec3T< T > m_halfLengths
Half-lengths h of the inserted box.
Definition EBGeometry_Fused.hpp:779
static constexpr DistanceQuality quality() noexcept
Distance quality: a bound at best.
Definition EBGeometry_Fused.hpp:788
Mollification: the operand convolved with a bump kernel sampled on a grid (CSGOps::mollify()).
Definition EBGeometry_Fused.hpp:1004
BoundingVolumes::AABBT< T > box(const O &a_operands) const
The box: the operand's, grown by sqrt(3) r (the operand's own if there is nothing to average).
Definition EBGeometry_Fused.hpp:1057
CSGOps::MollifyGrid< T > m_grid
The tap grid.
Definition EBGeometry_Fused.hpp:1008
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:1037
bool m_identity
Whether there is nothing to average over (one sample per axis, or a zero distance).
Definition EBGeometry_Fused.hpp:1013
static constexpr DistanceQuality quality() noexcept
Distance quality: a bound, unless the operand is not a distance.
Definition EBGeometry_Fused.hpp:1022
Everything the node holds: the operation's parameters and its operands (their layouts for pool-reside...
Definition EBGeometry_Fused.hpp:340
Detail::Pack< CSGDetail::Stored< Cs >... > m_operands
The operands, as stored.
Definition EBGeometry_Fused.hpp:349
Op m_op
The operation.
Definition EBGeometry_Fused.hpp:344
A list of operands, for the n-ary smooth operations (whose smoothing parameters follow the operands):...
Definition EBGeometry_Fused.hpp:1072
Detail::Pack< Cs... > m_items
The operands.
Definition EBGeometry_Fused.hpp:1076
Finite repetition: the minimum of the operand's value over all its copies (CSGOps::repetition()).
Definition EBGeometry_Fused.hpp:893
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:921
BoundingVolumes::AABBT< T > box(const O &a_operands) const
The box: the operand's, swept over the tiles.
CSGOps::Repetition< T > m_repetition
The repetition: period, tile counts and the operand's box.
Definition EBGeometry_Fused.hpp:897
static constexpr DistanceQuality quality() noexcept
Distance quality: a bound at best.
Definition EBGeometry_Fused.hpp:906
Offset (v - r) or annulus (|v| - delta).
Definition EBGeometry_Fused.hpp:830
T m_amount
The offset r, or the half-thickness delta.
Definition EBGeometry_Fused.hpp:834
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:859
BoundingVolumes::AABBT< T > box(const O &a_operands) const
The box: the operand's, grown by max(0, r) or max(0, delta).
Definition EBGeometry_Fused.hpp:880
static constexpr DistanceQuality quality() noexcept
Distance quality. An annulus keeps the operand's; an offset is a bound at best, since a negative offs...
Definition EBGeometry_Fused.hpp:844
Smooth union or intersection: a smooth minimum (maximum) of the two smallest (largest) values.
Definition EBGeometry_Fused.hpp:570
static constexpr DistanceQuality quality() noexcept
Distance quality: a bound at best.
Definition EBGeometry_Fused.hpp:588
bool m_exponential
Whether the blend is exponential (BlendKind::Exponential) rather than polynomial.
Definition EBGeometry_Fused.hpp:579
T m_smooth
Smoothing length.
Definition EBGeometry_Fused.hpp:574
T evaluate(const O &a_operands, const Vec3T< T > &a_point) const noexcept
The value.
Definition EBGeometry_Fused.hpp:603
BoundingVolumes::AABBT< T > box(const O &a_operands) const
The box: as a union or intersection's, a union's grown by how far the blend can move its surface out ...
Definition EBGeometry_Fused.hpp:618
Where a pool-resident descriptor resolves its offsets, and the rules for moving it.
Definition EBGeometry_Pool.hpp:99