18#ifndef EBGEOMETRY_CSGOPS_HPP
19#define EBGEOMETRY_CSGOPS_HPP
46inline constexpr uint32_t
NoTag = 0xFFFFFFFFU;
90inline constexpr bool isTagged<Tagged<T>> =
true;
98template <
class T, std::enable_if_t<std::is_
floating_po
int_v<T>,
int> = 0>
119 return a_value.m_value;
128template <
class T, std::enable_if_t<std::is_
floating_po
int_v<T>,
int> = 0>
162template <
class V,
class T>
166leafValue(
const T a_value, [[maybe_unused]]
const uint32_t a_tag, [[maybe_unused]]
const Vec3T<T>& a_point)
noexcept
168 if constexpr (isTagged<V>) {
169 return V{a_value, a_tag, a_point};
188 if constexpr (isTagged<V>) {
189 return withValue(a_value, -a_value.m_value);
208 if constexpr (isTagged<V>) {
209 return withValue(a_value, std::abs(a_value.m_value));
212 return std::abs(a_value);
224template <
class V,
class T>
228plus(
const V& a_value,
const T a_constant)
noexcept
230 if constexpr (isTagged<V>) {
231 return withValue(a_value, a_value.m_value + a_constant);
234 return a_value + a_constant;
246template <
class V,
class T>
250times(
const V& a_value,
const T a_constant)
noexcept
252 if constexpr (isTagged<V>) {
253 return withValue(a_value, a_value.m_value * a_constant);
256 return a_value * a_constant;
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])};
293 if constexpr (isTagged<V>) {
294 using T =
decltype(V::m_value);
310template <
class T, std::enable_if_t<std::is_
floating_po
int_v<T>,
int> = 0>
314smaller(
const T a_first,
const T a_second)
noexcept
332 return select(a_second.m_value < a_first.m_value, a_first, a_second);
342template <
class T, std::enable_if_t<std::is_
floating_po
int_v<T>,
int> = 0>
346larger(
const T a_first,
const T a_second)
noexcept
364 return select(a_first.m_value < a_second.m_value, a_first, a_second);
417 const T* m = a_coefficients;
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]);
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]));
468offset(
const T a_value,
const T a_offset)
noexcept
470 return a_value + (-a_offset);
483annular(
const T a_value,
const T a_delta)
noexcept
485 return std::abs(a_value) + (-a_delta);
519 if constexpr (isTagged<V>) {
520 using T =
decltype(V::m_value);
525 return Pair<V>{tagged, tagged};
544template <
class T, std::enable_if_t<std::is_
floating_po
int_v<T>,
int> = 0>
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);
553 a_pair.m_second = a_pair.m_first;
554 a_pair.m_first = a_value;
556 else if (beyondSecond) {
557 a_pair.m_second = a_value;
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;
577 const bool beyondFirst = a_largest ? (value > first) : (value < first);
578 const bool beyondSecond = a_largest ? (value > second) : (value < second);
581 a_pair.m_second = a_pair.m_first;
582 a_pair.m_first = a_value;
584 else if (beyondSecond) {
585 a_pair.m_second = a_value;
600template <
class T, std::enable_if_t<std::is_
floating_po
int_v<T>,
int> = 0>
603pairBlend(
const Pair<T>& a_pair,
const T a_smooth,
const bool a_largest,
const bool a_exponential)
noexcept
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);
610 return a_largest ?
SmoothMaxOp<T>{}(a_pair.m_first, a_pair.m_second, a_smooth)
629 const Pair<T> values{a_pair.
m_first.m_value, a_pair.m_second.m_value};
631 return withValue(a_pair.m_first,
pairBlend(values, a_smooth, a_largest, a_exponential));
660 const T beta = (T(1) - a_alpha) / T(2);
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))}};
679template <
class T,
class F>
682blur(
const T* a_weights,
const Vec3T<T>& a_point,
const F& a_operand)
noexcept
684 using V =
decltype(a_operand(a_point));
686 const T d = a_weights[0];
687 const T* w = a_weights;
694 if constexpr (isTagged<V>) {
696 V center = noLeaf<V>();
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;
704 const V tapValue = a_operand(a_point +
Vec3T<T>(T(i) * d, T(j) * d, T(k) * d));
706 value += w[1 + m] * tapValue.m_value;
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;
726 value += w[1 + m] * a_operand(tap);
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
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);
765 const T t =
Math::max(T(0), T(1) - a_offset.length2() / (T(4) * a_radius * a_radius));
810 MollifyGrid<T> grid{a_radius, T(2) * a_radius / T(a_samples - 1), T(0), a_samples};
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++) {
833template <
class T,
class F>
838 using V =
decltype(a_operand(a_point));
842 if constexpr (isTagged<V>) {
844 V heaviest = noLeaf<V>();
845 T heaviestWeight = -T(1);
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++) {
851 const V f = a_operand(a_point - o);
852 const T w =
mollifyWeight(o, a_grid.m_radius) / a_grid.m_sum;
854 value += f.m_value * w;
856 if (w > heaviestWeight) {
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++) {
873 value += a_operand(a_point - o) * (
mollifyWeight(o, a_grid.m_radius) / a_grid.m_sum);
921 period(
const size_t a_dir)
const noexcept
933 low(
const size_t a_dir)
const noexcept
945 high(
const size_t a_dir)
const noexcept
957 boxLow(
const size_t a_dir)
const noexcept
998 period(
const size_t a_dir)
const noexcept
1010 low(
const size_t a_dir)
const noexcept
1022 high(
const size_t a_dir)
const noexcept
1068template <
class T,
class R,
class F>
1073 using V =
decltype(a_object(a_point));
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))));
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])));
1091 for (
size_t dir = 0; dir < 3; dir++) {
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));
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)));
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;
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);
1113 if (i == home[0] && j == home[1] && k == home[2]) {
1117 const int tile[3] = {i, j, k};
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);
1131 if (dist2 <= bound * bound) {
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))));
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