EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_CSGOps.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_CSGOPS_HPP
19#define EBGEOMETRY_CSGOPS_HPP
20
21// Std includes
22#include <cmath>
23#include <cstdint>
24#include <type_traits>
25
26// Our includes
27#include "EBGeometry_Affine.hpp"
28#include "EBGeometry_Blend.hpp"
30#include "EBGeometry_GPU.hpp"
31#include "EBGeometry_Macros.hpp"
32#include "EBGeometry_Math.hpp"
33#include "EBGeometry_Vec.hpp"
34
35namespace EBGeometry {
36
41namespace CSGOps {
42
46inline constexpr uint32_t NoTag = 0xFFFFFFFFU;
47
56template <class T>
57struct Tagged
58{
63
70 uint32_t m_tag;
71
76};
77
82template <class V>
83inline constexpr bool isTagged = false;
84
89template <class T>
90inline constexpr bool isTagged<Tagged<T>> = true;
91
98template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
99[[nodiscard]] EBGEOMETRY_HOST_DEVICE
101inline T
102valueOf(const T a_value) noexcept
103{
104 return a_value;
105}
106
113template <class T>
114[[nodiscard]] EBGEOMETRY_HOST_DEVICE
116inline T
117valueOf(const Tagged<T>& a_value) noexcept
118{
119 return a_value.m_value;
120}
121
128template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
129[[nodiscard]] EBGEOMETRY_HOST_DEVICE
131inline T
132withValue(const T /*a_like*/, const T a_value) noexcept
133{
134 return a_value;
135}
136
144template <class T>
145[[nodiscard]] EBGEOMETRY_HOST_DEVICE
147inline Tagged<T>
148withValue(const Tagged<T>& a_like, const T a_value) noexcept
149{
150 return Tagged<T>{a_value, a_like.m_tag, a_like.m_point};
151}
152
162template <class V, class T>
163[[nodiscard]] EBGEOMETRY_HOST_DEVICE
165inline V
166leafValue(const T a_value, [[maybe_unused]] const uint32_t a_tag, [[maybe_unused]] const Vec3T<T>& a_point) noexcept
167{
168 if constexpr (isTagged<V>) {
169 return V{a_value, a_tag, a_point};
170 }
171 else {
172 return a_value;
173 }
174}
175
182template <class V>
183[[nodiscard]] EBGEOMETRY_HOST_DEVICE
185inline V
186negated(const V& a_value) noexcept
187{
188 if constexpr (isTagged<V>) {
189 return withValue(a_value, -a_value.m_value);
190 }
191 else {
192 return -a_value;
193 }
194}
195
202template <class V>
203[[nodiscard]] EBGEOMETRY_HOST_DEVICE
205inline V
206magnitude(const V& a_value) noexcept
207{
208 if constexpr (isTagged<V>) {
209 return withValue(a_value, std::abs(a_value.m_value));
210 }
211 else {
212 return std::abs(a_value);
213 }
214}
215
224template <class V, class T>
225[[nodiscard]] EBGEOMETRY_HOST_DEVICE
227inline V
228plus(const V& a_value, const T a_constant) noexcept
229{
230 if constexpr (isTagged<V>) {
231 return withValue(a_value, a_value.m_value + a_constant);
232 }
233 else {
234 return a_value + a_constant;
235 }
236}
237
246template <class V, class T>
247[[nodiscard]] EBGEOMETRY_HOST_DEVICE
249inline V
250times(const V& a_value, const T a_constant) noexcept
251{
252 if constexpr (isTagged<V>) {
253 return withValue(a_value, a_value.m_value * a_constant);
254 }
255 else {
256 return a_value * a_constant;
257 }
258}
259
269template <class T>
270[[nodiscard]] EBGEOMETRY_HOST_DEVICE
272inline Tagged<T>
273select(const bool a_second, const Tagged<T>& a_first, const Tagged<T>& a_other) noexcept
274{
275 return Tagged<T>{a_second ? a_other.m_value : a_first.m_value,
276 a_second ? a_other.m_tag : a_first.m_tag,
277 Vec3T<T>(a_second ? a_other.m_point[0] : a_first.m_point[0],
278 a_second ? a_other.m_point[1] : a_first.m_point[1],
279 a_second ? a_other.m_point[2] : a_first.m_point[2])};
280}
281
287template <class V>
288[[nodiscard]] EBGEOMETRY_HOST_DEVICE
290inline V
291noLeaf() noexcept
292{
293 if constexpr (isTagged<V>) {
294 using T = decltype(V::m_value);
295
296 return V{T(0), NoTag, Vec3T<T>::zeros()};
297 }
298 else {
299 return V(0);
300 }
301}
302
310template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
311[[nodiscard]] EBGEOMETRY_HOST_DEVICE
313inline T
314smaller(const T a_first, const T a_second) noexcept
315{
316 return Math::min(a_first, a_second);
317}
318
326template <class T>
327[[nodiscard]] EBGEOMETRY_HOST_DEVICE
329inline Tagged<T>
330smaller(const Tagged<T>& a_first, const Tagged<T>& a_second) noexcept
331{
332 return select(a_second.m_value < a_first.m_value, a_first, a_second);
333}
334
342template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
343[[nodiscard]] EBGEOMETRY_HOST_DEVICE
345inline T
346larger(const T a_first, const T a_second) noexcept
347{
348 return Math::max(a_first, a_second);
349}
350
358template <class T>
359[[nodiscard]] EBGEOMETRY_HOST_DEVICE
361inline Tagged<T>
362larger(const Tagged<T>& a_first, const Tagged<T>& a_second) noexcept
363{
364 return select(a_first.m_value < a_second.m_value, a_first, a_second);
365}
366
371template <class T>
373{
377 T m_values[12];
378};
379
386template <class T>
387[[nodiscard]] EBGEOMETRY_HOST_DEVICE
389affineCoefficients(const Affine3T<T>& a_map) noexcept
390{
391 return AffineCoefficients<T>{{a_map.m_row0[0],
392 a_map.m_row0[1],
393 a_map.m_row0[2],
394 a_map.m_row1[0],
395 a_map.m_row1[1],
396 a_map.m_row1[2],
397 a_map.m_row2[0],
398 a_map.m_row2[1],
399 a_map.m_row2[2],
400 a_map.m_shift[0],
401 a_map.m_shift[1],
402 a_map.m_shift[2]}};
403}
404
412template <class T>
413[[nodiscard]] EBGEOMETRY_HOST_DEVICE
414inline Vec3T<T>
415affinePoint(const T* a_coefficients, const Vec3T<T>& a_point) noexcept
416{
417 const T* m = a_coefficients;
418
419 return Vec3T<T>(m[0] * a_point[0] + m[1] * a_point[1] + m[2] * a_point[2] + m[9],
420 m[3] * a_point[0] + m[4] * a_point[1] + m[5] * a_point[2] + m[10],
421 m[6] * a_point[0] + m[7] * a_point[1] + m[8] * a_point[2] + m[11]);
422}
423
431template <class T>
432[[nodiscard]] EBGEOMETRY_HOST_DEVICE
433inline Vec3T<T>
434affinePoint(const Affine3T<T>& a_map, const Vec3T<T>& a_point) noexcept
435{
436 const AffineCoefficients<T> coefficients = affineCoefficients(a_map);
437
438 return affinePoint(coefficients.m_values, a_point);
439}
440
448template <class T>
449[[nodiscard]] EBGEOMETRY_HOST_DEVICE
450inline Vec3T<T>
451elongatePoint(const Vec3T<T>& a_halfLengths, const Vec3T<T>& a_point) noexcept
452{
453 return a_point - clamp(a_point,
454 Vec3T<T>(-a_halfLengths[0], -a_halfLengths[1], -a_halfLengths[2]),
455 Vec3T<T>(a_halfLengths[0], a_halfLengths[1], a_halfLengths[2]));
456}
457
465template <class T>
466[[nodiscard]] EBGEOMETRY_HOST_DEVICE
467inline T
468offset(const T a_value, const T a_offset) noexcept
469{
470 return a_value + (-a_offset);
471}
472
480template <class T>
481[[nodiscard]] EBGEOMETRY_HOST_DEVICE
482inline T
483annular(const T a_value, const T a_delta) noexcept
484{
485 return std::abs(a_value) + (-a_delta);
486}
487
494template <class V>
495struct Pair
496{
501
506};
507
514template <class V>
515[[nodiscard]] EBGEOMETRY_HOST_DEVICE
516inline Pair<V>
517pairInit(const bool a_largest) noexcept
518{
519 if constexpr (isTagged<V>) {
520 using T = decltype(V::m_value);
521
522 const T empty = a_largest ? -Math::Limits<T>::infinity() : Math::Limits<T>::infinity();
523 const V tagged{empty, NoTag, Vec3T<T>::zeros()};
524
525 return Pair<V>{tagged, tagged};
526 }
527 else {
528 const V empty = a_largest ? -Math::Limits<V>::infinity() : Math::Limits<V>::infinity();
529
530 return Pair<V>{empty, empty};
531 }
532}
533
544template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
546inline void
547pairInsert(Pair<T>& a_pair, const T a_value, const bool a_largest) noexcept
548{
549 const bool beyondFirst = a_largest ? (a_value > a_pair.m_first) : (a_value < a_pair.m_first);
550 const bool beyondSecond = a_largest ? (a_value > a_pair.m_second) : (a_value < a_pair.m_second);
551
552 if (beyondFirst) {
553 a_pair.m_second = a_pair.m_first;
554 a_pair.m_first = a_value;
555 }
556 else if (beyondSecond) {
557 a_pair.m_second = a_value;
558 }
559}
560
568template <class T>
570inline void
571pairInsert(Pair<Tagged<T>>& a_pair, const Tagged<T>& a_value, const bool a_largest) noexcept
572{
573 const T value = a_value.m_value;
574 const T first = a_pair.m_first.m_value;
575 const T second = a_pair.m_second.m_value;
576
577 const bool beyondFirst = a_largest ? (value > first) : (value < first);
578 const bool beyondSecond = a_largest ? (value > second) : (value < second);
579
580 if (beyondFirst) {
581 a_pair.m_second = a_pair.m_first;
582 a_pair.m_first = a_value;
583 }
584 else if (beyondSecond) {
585 a_pair.m_second = a_value;
586 }
587}
588
600template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
601[[nodiscard]] EBGEOMETRY_HOST_DEVICE
602inline T
603pairBlend(const Pair<T>& a_pair, const T a_smooth, const bool a_largest, const bool a_exponential) noexcept
604{
605 if (a_exponential) {
606 return a_largest ? ExpMaxOp<T>{}(a_pair.m_first, a_pair.m_second, a_smooth)
607 : ExpMinOp<T>{}(a_pair.m_first, a_pair.m_second, a_smooth);
608 }
609
610 return a_largest ? SmoothMaxOp<T>{}(a_pair.m_first, a_pair.m_second, a_smooth)
611 : SmoothMinOp<T>{}(a_pair.m_first, a_pair.m_second, a_smooth);
612}
613
624template <class T>
625[[nodiscard]] EBGEOMETRY_HOST_DEVICE
626inline Tagged<T>
627pairBlend(const Pair<Tagged<T>>& a_pair, const T a_smooth, const bool a_largest, const bool a_exponential) noexcept
628{
629 const Pair<T> values{a_pair.m_first.m_value, a_pair.m_second.m_value};
630
631 return withValue(a_pair.m_first, pairBlend(values, a_smooth, a_largest, a_exponential));
632}
633
638template <class T>
640{
645};
646
655template <class T>
656[[nodiscard]] EBGEOMETRY_HOST
657inline BlurWeights<T>
658blurWeights(const T a_distance, const T a_alpha)
659{
660 const T beta = (T(1) - a_alpha) / T(2);
661
662 return BlurWeights<T>{{a_distance,
663 std::pow(a_alpha, T(3)) * std::pow(beta, T(0)),
664 std::pow(a_alpha, T(2)) * std::pow(beta, T(1)),
665 std::pow(a_alpha, T(1)) * std::pow(beta, T(2)),
666 std::pow(a_alpha, T(0)) * std::pow(beta, T(3))}};
667}
668
679template <class T, class F>
680[[nodiscard]] EBGEOMETRY_HOST_DEVICE
681inline auto
682blur(const T* a_weights, const Vec3T<T>& a_point, const F& a_operand) noexcept
683{
684 using V = decltype(a_operand(a_point));
685
686 const T d = a_weights[0];
687 const T* w = a_weights;
688
689 // The 27 taps p + d (i, j, k), in this order; a tap m = |i| + |j| + |k| steps from the center has weight
690 // w[1 + m]. One loop that computes each tap's point itself: with the point computed in a callable
691 // called once per tap, nvcc 12.5 placed some taps at the wrong points.
692 T value = T(0);
693
694 if constexpr (isTagged<V>) {
695 // The same sum, carrying the center tap's tag (the heaviest tap only for alpha >= 1/3).
696 V center = noLeaf<V>();
697
698 for (int t = 0; t < 27; t++) {
699 const int i = t / 9 - 1;
700 const int j = (t / 3) % 3 - 1;
701 const int k = t % 3 - 1;
702 const int m = i * i + j * j + k * k;
703
704 const V tapValue = a_operand(a_point + Vec3T<T>(T(i) * d, T(j) * d, T(k) * d));
705
706 value += w[1 + m] * tapValue.m_value;
707
708 if (m == 0) {
709 center = tapValue;
710 }
711 }
712
713 return withValue(center, value);
714 }
715 else {
716 // Kept exactly as written for the plain value: holding each tap's value in a variable first made the
717 // device compiler give a kernel that evaluates a tape in a loop 255 registers instead of 168.
718 for (int t = 0; t < 27; t++) {
719 const int i = t / 9 - 1;
720 const int j = (t / 3) % 3 - 1;
721 const int k = t % 3 - 1;
722 const int m = i * i + j * j + k * k;
723
724 const Vec3T<T> tap = a_point + Vec3T<T>(T(i) * d, T(j) * d, T(k) * d);
725
726 value += w[1 + m] * a_operand(tap);
727 }
728
729 return value;
730 }
731}
732
743template <class T>
744[[nodiscard]] EBGEOMETRY_HOST_DEVICE
745inline Vec3T<T>
746mollifyOffset(const T a_radius, const T a_spacing, const uint32_t a_i, const uint32_t a_j, const uint32_t a_k) noexcept
747{
748 return Vec3T<T>(-a_radius + T(a_i) * a_spacing, -a_radius + T(a_j) * a_spacing, -a_radius + T(a_k) * a_spacing);
749}
750
760template <class T>
761[[nodiscard]] EBGEOMETRY_HOST_DEVICE
762inline T
763mollifyWeight(const Vec3T<T>& a_offset, const T a_radius) noexcept
764{
765 const T t = Math::max(T(0), T(1) - a_offset.length2() / (T(4) * a_radius * a_radius));
766
767 return t * t;
768}
769
774template <class T>
776{
781
786
791
795 uint32_t m_samples;
796};
797
805template <class T>
806[[nodiscard]] EBGEOMETRY_HOST
807inline MollifyGrid<T>
808mollifyGrid(const T a_radius, const uint32_t a_samples)
809{
810 MollifyGrid<T> grid{a_radius, T(2) * a_radius / T(a_samples - 1), T(0), a_samples};
811
812 for (uint32_t i = 0; i < a_samples; i++) {
813 for (uint32_t j = 0; j < a_samples; j++) {
814 for (uint32_t k = 0; k < a_samples; k++) {
815 grid.m_sum += mollifyWeight(mollifyOffset(a_radius, grid.m_spacing, i, j, k), a_radius);
816 }
817 }
818 }
819
820 return grid;
821}
822
833template <class T, class F>
834[[nodiscard]] EBGEOMETRY_HOST_DEVICE
835inline auto
836mollify(const MollifyGrid<T>& a_grid, const Vec3T<T>& a_point, const F& a_operand) noexcept
837{
838 using V = decltype(a_operand(a_point));
839
840 T value = T(0);
841
842 if constexpr (isTagged<V>) {
843 // The same sum, carrying the tag of the tap with the largest weight (the first, if several have it).
844 V heaviest = noLeaf<V>();
845 T heaviestWeight = -T(1);
846
847 for (uint32_t i = 0; i < a_grid.m_samples; i++) {
848 for (uint32_t j = 0; j < a_grid.m_samples; j++) {
849 for (uint32_t k = 0; k < a_grid.m_samples; k++) {
850 const Vec3T<T> o = mollifyOffset(a_grid.m_radius, a_grid.m_spacing, i, j, k);
851 const V f = a_operand(a_point - o);
852 const T w = mollifyWeight(o, a_grid.m_radius) / a_grid.m_sum;
853
854 value += f.m_value * w;
855
856 if (w > heaviestWeight) {
857 heaviest = f;
858 heaviestWeight = w;
859 }
860 }
861 }
862 }
863
864 return withValue(heaviest, value);
865 }
866 else {
867 // Kept exactly as written for the plain value (see blur()).
868 for (uint32_t i = 0; i < a_grid.m_samples; i++) {
869 for (uint32_t j = 0; j < a_grid.m_samples; j++) {
870 for (uint32_t k = 0; k < a_grid.m_samples; k++) {
871 const Vec3T<T> o = mollifyOffset(a_grid.m_radius, a_grid.m_spacing, i, j, k);
872
873 value += a_operand(a_point - o) * (mollifyWeight(o, a_grid.m_radius) / a_grid.m_sum);
874 }
875 }
876 }
877
878 return value;
879 }
880}
881
886template <class T>
888{
893
898
903
908
913
919 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
920 inline T
921 period(const size_t a_dir) const noexcept
922 {
923 return m_period[a_dir];
924 }
925
931 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
932 inline T
933 low(const size_t a_dir) const noexcept
934 {
935 return m_low[a_dir];
936 }
937
943 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
944 inline T
945 high(const size_t a_dir) const noexcept
946 {
947 return m_high[a_dir];
948 }
949
955 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
956 inline T
957 boxLow(const size_t a_dir) const noexcept
958 {
959 return m_boxLow[a_dir];
960 }
961
967 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
968 inline T
969 boxHigh(const size_t a_dir) const noexcept
970 {
971 return m_boxHigh[a_dir];
972 }
973};
974
983template <class T>
985{
989 const T* m_params;
990
996 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
997 inline T
998 period(const size_t a_dir) const noexcept
999 {
1000 return m_params[a_dir];
1001 }
1002
1008 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1009 inline T
1010 low(const size_t a_dir) const noexcept
1011 {
1012 return m_params[3 + a_dir];
1013 }
1014
1020 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1021 inline T
1022 high(const size_t a_dir) const noexcept
1023 {
1024 return m_params[6 + a_dir];
1025 }
1026
1032 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1033 inline T
1034 boxLow(const size_t a_dir) const noexcept
1035 {
1036 return m_params[9 + a_dir];
1037 }
1038
1044 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1045 inline T
1046 boxHigh(const size_t a_dir) const noexcept
1047 {
1048 return m_params[12 + a_dir];
1049 }
1050};
1051
1068template <class T, class R, class F>
1069[[nodiscard]] EBGEOMETRY_HOST_DEVICE
1070inline auto
1071repetition(const R& a_repetition, const Vec3T<T>& a_point, const F& a_object) noexcept
1072{
1073 using V = decltype(a_object(a_point));
1074
1075 // The tile the point folds into.
1076 int home[3];
1077
1078 for (size_t dir = 0; dir < 3; dir++) {
1079 home[dir] = static_cast<int>(std::round(
1080 Math::min(Math::max(a_point[dir] / a_repetition.period(dir), -a_repetition.low(dir)), a_repetition.high(dir))));
1081 }
1082
1083 V best = a_object(Vec3T<T>(a_point[0] - a_repetition.period(0) * T(home[0]),
1084 a_point[1] - a_repetition.period(1) * T(home[1]),
1085 a_point[2] - a_repetition.period(2) * T(home[2])));
1086
1087 // The tiles whose copy's box comes within max(0, best) of the point, along each axis.
1088 int first[3];
1089 int last[3];
1090
1091 for (size_t dir = 0; dir < 3; dir++) {
1092 const T reach = Math::max(valueOf(best), T(0));
1093 const T lo = std::ceil((a_point[dir] - reach - a_repetition.boxHigh(dir)) / a_repetition.period(dir));
1094 const T hi = std::floor((a_point[dir] + reach - a_repetition.boxLow(dir)) / a_repetition.period(dir));
1095
1096 first[dir] = static_cast<int>(Math::max(lo, -a_repetition.low(dir)));
1097 last[dir] = static_cast<int>(Math::min(hi, a_repetition.high(dir)));
1098 }
1099
1100 // Nested loops over i, j and k kept their counters alive across the calls into the object, which in a
1101 // Tape's sub-program raised every function of a device kernel to 255 registers (from 168); one counter,
1102 // in the same order (k fastest), keeps the kernel's.
1103 const int64_t ni = last[0] - first[0] + 1;
1104 const int64_t nj = last[1] - first[1] + 1;
1105 const int64_t nk = last[2] - first[2] + 1;
1106 const int64_t count = (ni > 0 && nj > 0 && nk > 0) ? ni * nj * nk : 0;
1107
1108 for (int64_t n = 0; n < count; n++) {
1109 const int i = first[0] + static_cast<int>(n / (nj * nk));
1110 const int j = first[1] + static_cast<int>((n / nk) % nj);
1111 const int k = first[2] + static_cast<int>(n % nk);
1112
1113 if (i == home[0] && j == home[1] && k == home[2]) {
1114 continue;
1115 }
1116
1117 const int tile[3] = {i, j, k};
1118 const T bound = Math::max(valueOf(best), T(0));
1119
1120 T dist2 = T(0);
1121
1122 for (size_t dir = 0; dir < 3; dir++) {
1123 const T shift = a_repetition.period(dir) * T(tile[dir]);
1124 const T below = (a_repetition.boxLow(dir) + shift) - a_point[dir];
1125 const T above = a_point[dir] - (a_repetition.boxHigh(dir) + shift);
1126 const T d = Math::max(Math::max(below, above), T(0));
1127
1128 dist2 += d * d;
1129 }
1130
1131 if (dist2 <= bound * bound) {
1132 best = smaller(best,
1133 a_object(Vec3T<T>(a_point[0] - a_repetition.period(0) * T(i),
1134 a_point[1] - a_repetition.period(1) * T(j),
1135 a_point[2] - a_repetition.period(2) * T(k))));
1136 }
1137 }
1138
1139 return best;
1140}
1141
1142} // namespace CSGOps
1143
1144} // namespace EBGeometry
1145
1146#endif
Declaration of Affine3T, an affine map of 3D space (a 3x3 matrix and a shift).
The blend operators that smooth unions, intersections and differences use: ExpMinOp,...
Declarations of bounding volume types used in bounding volume hierarchies.
GPU portability layer: host/device decoration macros and backend detection.
#define EBGEOMETRY_HOST_ALWAYS_INLINE
Always inline a function in a host pass (GCC and Clang); nothing in a device pass.
Definition EBGeometry_GPU.hpp:123
#define EBGEOMETRY_HOST_DEVICE
Mark a function as callable from both host and device code (no-op on host compilers).
Definition EBGeometry_GPU.hpp:80
#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.
Scalar helpers and numeric limits that compile for both host and device.
Declaration of 2D and 3D point/vector classes with templated precision, and free functions on them.
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:258
static constexpr Vec3T< T > zeros() noexcept
Return a vector with x = y = z = 0.
Pair< V > pairInit(const bool a_largest) noexcept
The empty pair: both values +inf (for the smallest) or -inf (for the largest).
Definition EBGeometry_CSGOps.hpp:517
T mollifyWeight(const Vec3T< T > &a_offset, const T a_radius) noexcept
The unnormalized weight of a mollification tap: the bump kernel max(0, 1 - |o|^2 / (2r)^2)^2.
Definition EBGeometry_CSGOps.hpp:763
EBGEOMETRY_HOST_ALWAYS_INLINE T smaller(const T a_first, const T a_second) noexcept
The smaller of two plain values (Math::min()).
Definition EBGeometry_CSGOps.hpp:314
EBGEOMETRY_HOST_ALWAYS_INLINE V magnitude(const V &a_value) noexcept
A value's magnitude, its tag kept.
Definition EBGeometry_CSGOps.hpp:206
auto repetition(const R &a_repetition, const Vec3T< T > &a_point, const F &a_object) noexcept
A finite repetition's value: the minimum of the object's value over all its copies.
Definition EBGeometry_CSGOps.hpp:1071
EBGEOMETRY_HOST_ALWAYS_INLINE T withValue(const T, const T a_value) noexcept
A plain value replaced by another: the other.
Definition EBGeometry_CSGOps.hpp:132
EBGEOMETRY_HOST_ALWAYS_INLINE T valueOf(const T a_value) noexcept
A plain value's value: itself.
Definition EBGeometry_CSGOps.hpp:102
EBGEOMETRY_HOST_ALWAYS_INLINE V negated(const V &a_value) noexcept
A value negated, its tag kept.
Definition EBGeometry_CSGOps.hpp:186
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
EBGEOMETRY_HOST_ALWAYS_INLINE V plus(const V &a_value, const T a_constant) noexcept
A value plus a constant, its tag kept.
Definition EBGeometry_CSGOps.hpp:228
MollifyGrid< T > mollifyGrid(const T a_radius, const uint32_t a_samples)
Set up a mollification's tap grid.
Definition EBGeometry_CSGOps.hpp:808
EBGEOMETRY_HOST_ALWAYS_INLINE V noLeaf() noexcept
A value that comes from no leaf: zero, tagged with NoTag.
Definition EBGeometry_CSGOps.hpp:291
Vec3T< T > mollifyOffset(const T a_radius, const T a_spacing, const uint32_t a_i, const uint32_t a_j, const uint32_t a_k) noexcept
The offset of mollification tap (i, j, k): -r + (i, j, k) dX, dX = 2r / (n - 1).
Definition EBGeometry_CSGOps.hpp:746
BlurWeights< T > blurWeights(const T a_distance, const T a_alpha)
A blur's distance and weights: the weight of a tap m steps from the center is alpha^(3-m) beta^m with...
Definition EBGeometry_CSGOps.hpp:658
EBGEOMETRY_HOST_ALWAYS_INLINE V times(const V &a_value, const T a_constant) noexcept
A value times a constant, its tag kept.
Definition EBGeometry_CSGOps.hpp:250
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
constexpr bool isTagged
Whether V is a tagged value.
Definition EBGeometry_CSGOps.hpp:83
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
EBGEOMETRY_HOST_ALWAYS_INLINE Tagged< T > select(const bool a_second, const Tagged< T > &a_first, const Tagged< T > &a_other) noexcept
One of two tagged values, chosen field by field, so that the compiler selects without a branch: a who...
Definition EBGeometry_CSGOps.hpp:273
EBGEOMETRY_HOST_ALWAYS_INLINE T larger(const T a_first, const T a_second) noexcept
The larger of two plain values (Math::max()).
Definition EBGeometry_CSGOps.hpp:346
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
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
EBGEOMETRY_HOST_ALWAYS_INLINE V leafValue(const T a_value, const uint32_t a_tag, const Vec3T< T > &a_point) noexcept
A leaf's value: the value itself, or the value tagged with the leaf and the point.
Definition EBGeometry_CSGOps.hpp:166
constexpr uint32_t NoTag
The tag of a value that comes from no leaf.
Definition EBGeometry_CSGOps.hpp:46
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
constexpr Vec3T< T > clamp(const Vec3T< T > &v, const Vec3T< T > &lo, const Vec3T< T > &hi) noexcept
Component-wise clamp of a 3D vector.
An affine map of 3D space, x -> A x + b, with A stored by rows.
Definition EBGeometry_Affine.hpp:37
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
A blur's distance and weights.
Definition EBGeometry_CSGOps.hpp:640
T m_values[5]
The blur distance d, followed by the weight of a tap 0, 1, 2 and 3 steps from the center.
Definition EBGeometry_CSGOps.hpp:644
A mollification's tap grid: n taps per axis over [-r, r]^3, and the sum of their weights.
Definition EBGeometry_CSGOps.hpp:776
T m_radius
Mollification distance r.
Definition EBGeometry_CSGOps.hpp:780
T m_sum
Sum of the unnormalized weights, which every weight is divided by.
Definition EBGeometry_CSGOps.hpp:790
uint32_t m_samples
Taps per axis n (at least 2).
Definition EBGeometry_CSGOps.hpp:795
T m_spacing
Tap spacing dX = 2r / (n - 1).
Definition EBGeometry_CSGOps.hpp:785
The two most extreme values seen so far, for an n-ary smooth union or intersection.
Definition EBGeometry_CSGOps.hpp:496
V m_first
The most extreme value.
Definition EBGeometry_CSGOps.hpp:500
V m_second
The next.
Definition EBGeometry_CSGOps.hpp:505
A finite repetition read from an array of 15 parameters (period, low and high counts,...
Definition EBGeometry_CSGOps.hpp:985
T period(const size_t a_dir) const noexcept
Period along an axis.
Definition EBGeometry_CSGOps.hpp:998
T boxHigh(const size_t a_dir) const noexcept
High corner of the object's box along an axis.
Definition EBGeometry_CSGOps.hpp:1046
const T * m_params
The parameters.
Definition EBGeometry_CSGOps.hpp:989
T low(const size_t a_dir) const noexcept
Tiles in the decreasing direction of an axis.
Definition EBGeometry_CSGOps.hpp:1010
T high(const size_t a_dir) const noexcept
Tiles in the increasing direction of an axis.
Definition EBGeometry_CSGOps.hpp:1022
T boxLow(const size_t a_dir) const noexcept
Low corner of the object's box along an axis.
Definition EBGeometry_CSGOps.hpp:1034
A finite repetition: copies of an object on a grid of tiles.
Definition EBGeometry_CSGOps.hpp:888
T boxHigh(const size_t a_dir) const noexcept
High corner of the object's box along an axis.
Definition EBGeometry_CSGOps.hpp:969
Vec3T< T > m_boxHigh
High corner of the repeated object's box.
Definition EBGeometry_CSGOps.hpp:912
T high(const size_t a_dir) const noexcept
Tiles in the increasing direction of an axis.
Definition EBGeometry_CSGOps.hpp:945
T boxLow(const size_t a_dir) const noexcept
Low corner of the object's box along an axis.
Definition EBGeometry_CSGOps.hpp:957
Vec3T< T > m_low
Whole tiles in the decreasing direction of each axis.
Definition EBGeometry_CSGOps.hpp:897
T low(const size_t a_dir) const noexcept
Tiles in the decreasing direction of an axis.
Definition EBGeometry_CSGOps.hpp:933
Vec3T< T > m_period
Tile period along each axis.
Definition EBGeometry_CSGOps.hpp:892
Vec3T< T > m_boxLow
Low corner of the repeated object's box (its home copy's).
Definition EBGeometry_CSGOps.hpp:907
T period(const size_t a_dir) const noexcept
Period along an axis.
Definition EBGeometry_CSGOps.hpp:921
Vec3T< T > m_high
Whole tiles in the increasing direction of each axis.
Definition EBGeometry_CSGOps.hpp:902
A value with the deciding leaf it comes from: the leaf whose surface the composed value is taken from...
Definition EBGeometry_CSGOps.hpp:58
uint32_t m_tag
The deciding leaf, as the structure numbers it (NoTag for none).
Definition EBGeometry_CSGOps.hpp:70
Vec3T< T > m_point
The point the leaf was evaluated at.
Definition EBGeometry_CSGOps.hpp:75
T m_value
The value.
Definition EBGeometry_CSGOps.hpp:62
Exponential smooth maximum for blending two signed-distance values.
Definition EBGeometry_Blend.hpp:69
Exponential smooth minimum for blending two signed-distance values.
Definition EBGeometry_Blend.hpp:39
Numeric limits, with the meanings of the std::numeric_limits members of the same names.
Definition EBGeometry_Math.hpp:91
Quadratic polynomial smooth maximum for blending two signed-distance values.
Definition EBGeometry_Blend.hpp:130
Quadratic polynomial smooth minimum for blending two signed-distance values.
Definition EBGeometry_Blend.hpp:99