EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_AnalyticDistanceFunctions.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2022 Robert Marskar <robert.marskar@sintef.no>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
28#ifndef EBGEOMETRY_ANALYTICDISTANCEFUNCTIONS_HPP
29#define EBGEOMETRY_ANALYTICDISTANCEFUNCTIONS_HPP
30
31// Std includes
32#include <algorithm>
33#include <cmath>
34#include <cstddef>
35#include <random>
36#include <type_traits>
37
38// Our includes
39#include "EBGeometry_Array.hpp"
43#include "EBGeometry_GPU.hpp"
44#include "EBGeometry_Macros.hpp"
45#include "EBGeometry_Math.hpp"
46#include "EBGeometry_Vec.hpp"
47
48namespace EBGeometry {
49
58template <class T>
60{
61 static_assert(std::is_floating_point_v<T>, "PlaneSDF<T>: T must be a floating-point type");
62
63public:
68
74 PlaneSDF() = default;
75
81 PlaneSDF(const Vec3T<T>& a_point, const Vec3T<T>& a_normal) noexcept
82 {
83 EBGEOMETRY_REQUIRE(std::isfinite(a_point[0]) && std::isfinite(a_point[1]) && std::isfinite(a_point[2]),
84 "PlaneSDF: the point must be finite (%g, %g, %g)",
85 double(a_point[0]),
86 double(a_point[1]),
87 double(a_point[2]));
88 EBGEOMETRY_REQUIRE(std::isfinite(a_normal[0]) && std::isfinite(a_normal[1]) && std::isfinite(a_normal[2]),
89 "PlaneSDF: the normal must be finite (%g, %g, %g)",
90 double(a_normal[0]),
91 double(a_normal[1]),
92 double(a_normal[2]));
93 EBGEOMETRY_REQUIRE(a_normal.length() > T(0),
94 "PlaneSDF: the normal must be nonzero (%g, %g, %g)",
95 double(a_normal[0]),
96 double(a_normal[1]),
97 double(a_normal[2]));
98
99 m_point = a_point;
100 m_normal = a_normal / a_normal.length();
101 }
102
106 PlaneSDF(const PlaneSDF&) = default;
107
111 PlaneSDF(PlaneSDF&&) = default;
112
117 PlaneSDF&
118 operator=(const PlaneSDF&) = default;
119
124 PlaneSDF&
125 operator=(PlaneSDF&&) = default;
126
132 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
133 T
134 signedDistance(const Vec3T<T>& a_point) const noexcept
135 {
136 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
137 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
138 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
139 EBGEOMETRY_EXPECT(std::abs(m_normal.length() - T(1)) < std::sqrt(Math::Limits<T>::epsilon()));
140
141 return dot((a_point - m_point), m_normal);
142 }
143
149 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
151 computeBoundingVolume() const noexcept
152 {
154 }
155
160 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
161 const Vec3T<T>&
162 getPoint() const noexcept
163 {
164 return m_point;
165 }
166
171 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
172 const Vec3T<T>&
173 getNormal() const noexcept
174 {
175 return m_normal;
176 }
177
178protected:
183
187 Vec3T<T> m_normal = Vec3T<T>(T(0), T(1), T(0));
188};
189
197template <class T>
199{
200 static_assert(std::is_floating_point_v<T>, "SphereSDF<T>: T must be a floating-point type");
201
202public:
207
211 SphereSDF() = default;
212
218 SphereSDF(const Vec3T<T>& a_center, const T& a_radius) noexcept
219 {
220 EBGEOMETRY_REQUIRE(std::isfinite(a_center[0]) && std::isfinite(a_center[1]) && std::isfinite(a_center[2]),
221 "SphereSDF: the center must be finite (%g, %g, %g)",
222 double(a_center[0]),
223 double(a_center[1]),
224 double(a_center[2]));
225 EBGEOMETRY_REQUIRE(std::isfinite(a_radius) && a_radius > T(0),
226 "SphereSDF: the radius must be finite and positive (%g)",
227 double(a_radius));
228
229 m_center = a_center;
230 m_radius = a_radius;
231 }
232
236 SphereSDF(const SphereSDF&) = default;
237
241 SphereSDF(SphereSDF&&) = default;
242
247 SphereSDF&
248 operator=(const SphereSDF&) = default;
249
254 SphereSDF&
255 operator=(SphereSDF&&) = default;
256
261 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
262 const Vec3T<T>&
263 getCenter() const noexcept
264 {
265 return m_center;
266 }
267
273 Vec3T<T>&
274 getCenter() noexcept
275 {
276 return m_center;
277 }
278
283 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
284 const T&
285 getRadius() const noexcept
286 {
287 return m_radius;
288 }
289
295 T&
296 getRadius() noexcept
297 {
298 return m_radius;
299 }
300
306 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
307 T
308 signedDistance(const Vec3T<T>& a_point) const noexcept
309 {
310 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
311 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
312 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
313
314 return (a_point - m_center).length() - m_radius;
315 }
316
322 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
328
329protected:
334
338 T m_radius = T(1);
339};
340
349template <class T>
351{
352 static_assert(std::is_floating_point_v<T>, "BoxSDF<T>: T must be a floating-point type");
353
354public:
359
363 BoxSDF() = default;
364
371 BoxSDF(const Vec3T<T>& a_loCorner, const Vec3T<T>& a_hiCorner) noexcept
372 {
373 EBGEOMETRY_REQUIRE(std::isfinite(a_loCorner[0]) && std::isfinite(a_loCorner[1]) && std::isfinite(a_loCorner[2]),
374 "BoxSDF: the low corner must be finite (%g, %g, %g)",
375 double(a_loCorner[0]),
376 double(a_loCorner[1]),
377 double(a_loCorner[2]));
378 EBGEOMETRY_REQUIRE(std::isfinite(a_hiCorner[0]) && std::isfinite(a_hiCorner[1]) && std::isfinite(a_hiCorner[2]),
379 "BoxSDF: the high corner must be finite (%g, %g, %g)",
380 double(a_hiCorner[0]),
381 double(a_hiCorner[1]),
382 double(a_hiCorner[2]));
384 a_loCorner[0] < a_hiCorner[0] && a_loCorner[1] < a_hiCorner[1] && a_loCorner[2] < a_hiCorner[2],
385 "BoxSDF: the low corner (%g, %g, %g) must be below the high corner (%g, %g, %g) in every direction",
386 double(a_loCorner[0]),
387 double(a_loCorner[1]),
388 double(a_loCorner[2]),
389 double(a_hiCorner[0]),
390 double(a_hiCorner[1]),
391 double(a_hiCorner[2]));
392
393 m_loCorner = a_loCorner;
394 m_hiCorner = a_hiCorner;
395 }
396
400 BoxSDF(const BoxSDF&) = default;
401
405 BoxSDF(BoxSDF&&) = default;
406
411 BoxSDF&
412 operator=(const BoxSDF&) = default;
413
418 BoxSDF&
419 operator=(BoxSDF&&) = default;
420
425 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
426 const Vec3T<T>&
427 getLowCorner() const noexcept
428 {
429 return m_loCorner;
430 }
431
437 Vec3T<T>&
438 getLowCorner() noexcept
439 {
440 return m_loCorner;
441 }
442
447 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
448 const Vec3T<T>&
449 getHighCorner() const noexcept
450 {
451 return m_hiCorner;
452 }
453
459 Vec3T<T>&
460 getHighCorner() noexcept
461 {
462 return m_hiCorner;
463 }
464
470 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
471 T
472 signedDistance(const Vec3T<T>& a_point) const noexcept
473 {
474 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
475 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
476 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
477
478 // For each coordinate direction, we have delta[dir] if a_point[dir] falls
479 // between xLo and xHi. In this case delta[dir] will be the signed distance
480 // to the closest box face in the dir-direction. Otherwise, if a_point[dir]
481 // is outside the corner we have delta[dir] > 0.
482 const Vec3T<T> delta(Math::max(m_loCorner[0] - a_point[0], a_point[0] - m_hiCorner[0]),
483 Math::max(m_loCorner[1] - a_point[1], a_point[1] - m_hiCorner[1]),
484 Math::max(m_loCorner[2] - a_point[2], a_point[2] - m_hiCorner[2]));
485
486 // Note: max is max(Vec3T<T>, Vec3T<T>) and not std::max. It returns a
487 // vector with coordinate-wise largest components. Note that the first part
488 // Math::min(...) is the signed distance on the inside of the box (delta will
489 // have negative components). The other part max(Vec3T<T>::zeros(), ...) is
490 // for outside the box.
491 const T d = Math::min(T(0.0), delta[delta.maxDir(false)]) + max(Vec3T<T>::zeros(), delta).length();
492
493 return d;
494 }
495
501 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
503 computeBoundingVolume() const noexcept
504 {
506 }
507
508protected:
512 Vec3T<T> m_loCorner = Vec3T<T>(T(-0.5), T(-0.5), T(-0.5));
513
517 Vec3T<T> m_hiCorner = Vec3T<T>(T(0.5), T(0.5), T(0.5));
518};
519
531template <class T>
533{
534 static_assert(std::is_floating_point_v<T>, "TorusSDF<T>: T must be a floating-point type");
535
536public:
541
545 TorusSDF() = default;
546
553 TorusSDF(const Vec3T<T>& a_center, const T& a_majorRadius, const T& a_minorRadius) noexcept
554 {
555 EBGEOMETRY_REQUIRE(std::isfinite(a_center[0]) && std::isfinite(a_center[1]) && std::isfinite(a_center[2]),
556 "TorusSDF: the center must be finite (%g, %g, %g)",
557 double(a_center[0]),
558 double(a_center[1]),
559 double(a_center[2]));
560 EBGEOMETRY_REQUIRE(std::isfinite(a_majorRadius) && a_majorRadius > T(0),
561 "TorusSDF: the major radius must be finite and positive (%g)",
562 double(a_majorRadius));
563 EBGEOMETRY_REQUIRE(std::isfinite(a_minorRadius) && a_minorRadius > T(0),
564 "TorusSDF: the minor radius must be finite and positive (%g)",
565 double(a_minorRadius));
566 EBGEOMETRY_REQUIRE(a_minorRadius < a_majorRadius,
567 "TorusSDF: the minor radius (%g) must be less than the major radius (%g)",
568 double(a_minorRadius),
569 double(a_majorRadius));
570
571 m_center = a_center;
572 m_majorRadius = a_majorRadius;
573 m_minorRadius = a_minorRadius;
574 }
575
579 TorusSDF(const TorusSDF&) = default;
580
584 TorusSDF(TorusSDF&&) = default;
585
590 TorusSDF&
591 operator=(const TorusSDF&) = default;
592
597 TorusSDF&
598 operator=(TorusSDF&&) = default;
599
604 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
605 const Vec3T<T>&
606 getCenter() const noexcept
607 {
608 return m_center;
609 }
610
616 Vec3T<T>&
617 getCenter() noexcept
618 {
619 return m_center;
620 }
621
626 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
627 const T&
628 getMajorRadius() const noexcept
629 {
630 return m_majorRadius;
631 }
632
638 T&
639 getMajorRadius() noexcept
640 {
641 return m_majorRadius;
642 }
643
648 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
649 const T&
650 getMinorRadius() const noexcept
651 {
652 return m_minorRadius;
653 }
654
660 T&
661 getMinorRadius() noexcept
662 {
663 return m_minorRadius;
664 }
670 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
671 T
672 signedDistance(const Vec3T<T>& a_point) const noexcept
673 {
674 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
675 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
676 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
677
678 const Vec3T<T> p = a_point - m_center;
679 const T rho = std::sqrt(p[0] * p[0] + p[2] * p[2]) - m_majorRadius;
680 const T d = std::sqrt(rho * rho + p[1] * p[1]) - m_minorRadius;
681
682 return d;
683 }
684
690 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
692 computeBoundingVolume() const noexcept
693 {
694 const T outer = m_majorRadius + m_minorRadius;
695 const Vec3T<T> half(outer, m_minorRadius, outer);
696
697 return BoundingVolumes::AABBT<T>(m_center - half, m_center + half);
698 }
699
700protected:
705
710
714 T m_minorRadius = T(0.5);
715};
716
726template <class T>
728{
729 static_assert(std::is_floating_point_v<T>, "CylinderSDF<T>: T must be a floating-point type");
730
731public:
736
741 CylinderSDF() = default;
742
749 CylinderSDF(const Vec3T<T>& a_center1, const Vec3T<T>& a_center2, const T& a_radius) noexcept
750 {
751 EBGEOMETRY_REQUIRE(std::isfinite(a_center1[0]) && std::isfinite(a_center1[1]) && std::isfinite(a_center1[2]),
752 "CylinderSDF: the first center must be finite (%g, %g, %g)",
753 double(a_center1[0]),
754 double(a_center1[1]),
755 double(a_center1[2]));
756 EBGEOMETRY_REQUIRE(std::isfinite(a_center2[0]) && std::isfinite(a_center2[1]) && std::isfinite(a_center2[2]),
757 "CylinderSDF: the second center must be finite (%g, %g, %g)",
758 double(a_center2[0]),
759 double(a_center2[1]),
760 double(a_center2[2]));
761 EBGEOMETRY_REQUIRE(std::isfinite(a_radius) && a_radius > T(0),
762 "CylinderSDF: the radius must be finite and positive (%g)",
763 double(a_radius));
764 EBGEOMETRY_REQUIRE((a_center2 - a_center1).length() > T(0),
765 "CylinderSDF: the two centers must differ, but both are (%g, %g, %g)",
766 double(a_center1[0]),
767 double(a_center1[1]),
768 double(a_center1[2]));
769
770 m_center1 = a_center1;
771 m_center2 = a_center2;
772 m_radius = a_radius;
773
774 m_center = (m_center2 + m_center1) * T(0.5);
777 }
778
782 CylinderSDF(const CylinderSDF&) = default;
783
788
794 operator=(const CylinderSDF&) = default;
795
801 operator=(CylinderSDF&&) = default;
802
807 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
808 const Vec3T<T>&
809 getCenter1() const noexcept
810 {
811 return m_center1;
812 }
813
818 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
819 const Vec3T<T>&
820 getCenter2() const noexcept
821 {
822 return m_center2;
823 }
824
829 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
830 const T&
831 getRadius() const noexcept
832 {
833 return m_radius;
834 }
835
841 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
842 T
843 signedDistance(const Vec3T<T>& a_point) const noexcept
844 {
845 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
846 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
847 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
848
850
851 if (m_length > T(0.0) && m_radius > T(0.0)) {
852 EBGEOMETRY_EXPECT(std::abs(m_axis.length() - T(1)) < std::sqrt(Math::Limits<T>::epsilon()));
853
854 const Vec3T<T> point = a_point - m_center;
855 const T para = dot(point, m_axis);
856 const Vec3T<T> ortho = point - para * m_axis; // Distance from cylinder axis.
857
858 // w: Distance from cylinder wall. < 0 on inside and > 0 on outside.
859 // h: Distance from cylinder top. < 0 on inside and > 0 on outside.
860 const T w = ortho.length() - m_radius;
861 const T h = std::abs(para) - T(0.5) * m_length;
862
863 constexpr T zero = T(0.0);
864
865 if (w <= zero && h <= zero) {
866 // Inside cylinder
867 d = (std::abs(w) < std::abs(h)) ? w : h;
868 }
869 else if (w <= zero && h > zero) {
870 // Above one of the endcaps.
871 d = h;
872 }
873 else if (w > zero && h < zero) {
874 // Outside radius but between the endcaps.
875 d = w;
876 }
877 else {
878 d = std::sqrt(w * w + h * h);
879 }
880 }
881
882 return d;
883 }
884
891 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
893 computeBoundingVolume() const noexcept
894 {
895 Vec3T<T> reach;
896
897 for (size_t dir = 0; dir < 3; dir++) {
898 reach[dir] = m_radius * std::sqrt(Math::max(T(0), T(1) - m_axis[dir] * m_axis[dir]));
899 }
900
902 }
903
904protected:
908 Vec3T<T> m_center1 = Vec3T<T>(T(0), T(-0.5), T(0));
909
913 Vec3T<T> m_center2 = Vec3T<T>(T(0), T(0.5), T(0));
914
919
923 Vec3T<T> m_axis = Vec3T<T>(T(0), T(1), T(0));
924
928 T m_length = T(1);
929
933 T m_radius = T(1);
934};
935
945template <class T>
947{
948 static_assert(std::is_floating_point_v<T>, "InfiniteCylinderSDF<T>: T must be a floating-point type");
949
950public:
955
961
968 InfiniteCylinderSDF(const Vec3T<T>& a_center, const T& a_radius, const size_t a_axis) noexcept
969 {
970 EBGEOMETRY_REQUIRE(std::isfinite(a_center[0]) && std::isfinite(a_center[1]) && std::isfinite(a_center[2]),
971 "InfiniteCylinderSDF: the center must be finite (%g, %g, %g)",
972 double(a_center[0]),
973 double(a_center[1]),
974 double(a_center[2]));
975 EBGEOMETRY_REQUIRE(std::isfinite(a_radius) && a_radius > T(0),
976 "InfiniteCylinderSDF: the radius must be finite and positive (%g)",
977 double(a_radius));
978 EBGEOMETRY_REQUIRE(a_axis < 3U, "InfiniteCylinderSDF: the axis must be 0, 1 or 2 (%zu)", a_axis);
979
980 m_center = a_center;
981 m_radius = a_radius;
982 m_axis = a_axis;
983 }
984
989
994
1001
1008
1014 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1015 T
1016 signedDistance(const Vec3T<T>& a_point) const noexcept
1017 {
1018 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
1019 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
1020 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
1021
1022 Vec3T<T> delta = a_point - m_center;
1023 delta[m_axis] = 0.0;
1024
1025 const T d = delta.length() - m_radius;
1026
1027 return d;
1028 }
1029
1035 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1037 computeBoundingVolume() const noexcept
1038 {
1041
1044
1045 return BoundingVolumes::AABBT<T>(lo, hi);
1046 }
1047
1052 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1053 const Vec3T<T>&
1054 getCenter() const noexcept
1055 {
1056 return m_center;
1057 }
1058
1063 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1064 const T&
1065 getRadius() const noexcept
1066 {
1067 return m_radius;
1068 }
1069
1074 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1075 const size_t&
1076 getAxis() const noexcept
1077 {
1078 return m_axis;
1079 }
1080
1081protected:
1086
1090 T m_radius = T(1);
1091
1095 size_t m_axis = 1U;
1096};
1097
1115template <class T>
1117{
1118 static_assert(std::is_floating_point_v<T>, "CapsuleSDF<T>: T must be a floating-point type");
1119
1120public:
1125
1131 CapsuleSDF() = default;
1132
1144 CapsuleSDF(const Vec3T<T>& a_tip1, const Vec3T<T>& a_tip2, const T& a_radius) noexcept
1145 {
1146 EBGEOMETRY_REQUIRE(std::isfinite(a_tip1[0]) && std::isfinite(a_tip1[1]) && std::isfinite(a_tip1[2]),
1147 "CapsuleSDF: the first tip must be finite (%g, %g, %g)",
1148 double(a_tip1[0]),
1149 double(a_tip1[1]),
1150 double(a_tip1[2]));
1151 EBGEOMETRY_REQUIRE(std::isfinite(a_tip2[0]) && std::isfinite(a_tip2[1]) && std::isfinite(a_tip2[2]),
1152 "CapsuleSDF: the second tip must be finite (%g, %g, %g)",
1153 double(a_tip2[0]),
1154 double(a_tip2[1]),
1155 double(a_tip2[2]));
1156 EBGEOMETRY_REQUIRE(std::isfinite(a_radius) && a_radius > T(0),
1157 "CapsuleSDF: the radius must be finite and positive (%g)",
1158 double(a_radius));
1159 EBGEOMETRY_REQUIRE((a_tip2 - a_tip1).length() >= T(2) * a_radius,
1160 "CapsuleSDF: the tips must be at least two radii apart (distance %g, radius %g)",
1161 double((a_tip2 - a_tip1).length()),
1162 double(a_radius));
1163
1164 const Vec3T<T> axis = (a_tip2 - a_tip1) / length(a_tip2 - a_tip1);
1165
1166 m_center1 = a_tip1 + a_radius * axis;
1167 m_center2 = a_tip2 - a_radius * axis;
1168 m_radius = a_radius;
1169 }
1170
1174 CapsuleSDF(const CapsuleSDF&) = default;
1175
1180
1185 CapsuleSDF&
1186 operator=(const CapsuleSDF&) = default;
1187
1192 CapsuleSDF&
1193 operator=(CapsuleSDF&&) = default;
1194
1200 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1201 T
1202 signedDistance(const Vec3T<T>& a_point) const noexcept
1203 {
1204 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
1205 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
1206 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
1207
1208 const Vec3T<T> v1 = a_point - m_center1;
1209 const Vec3T<T> v2 = m_center2 - m_center1;
1210
1211 // Tips exactly two radii apart put both hemisphere centers at the same point: a sphere. Guard the
1212 // projection, which would otherwise divide zero by zero.
1213 const T len2 = dot(v2, v2);
1214
1215 const T h = (len2 > T(0)) ? Math::clamp(dot(v1, v2) / len2, T(0.0), T(1.0)) : T(0.0);
1216 const T d = length(v1 - h * v2) - m_radius;
1217
1218 return d;
1219 }
1220
1226 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1233
1238 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1239 const Vec3T<T>&
1240 getCenter1() const noexcept
1241 {
1242 return m_center1;
1243 }
1244
1249 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1250 const Vec3T<T>&
1251 getCenter2() const noexcept
1252 {
1253 return m_center2;
1254 }
1255
1260 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1261 const T&
1262 getRadius() const noexcept
1263 {
1264 return m_radius;
1265 }
1266
1267protected:
1271 Vec3T<T> m_center1 = Vec3T<T>(T(0), T(-0.5), T(0));
1272
1276 Vec3T<T> m_center2 = Vec3T<T>(T(0), T(0.5), T(0));
1277
1281 T m_radius = T(0.5);
1282};
1283
1299template <class T>
1301{
1302 static_assert(std::is_floating_point_v<T>, "InfiniteConeSDF<T>: T must be a floating-point type");
1303
1304public:
1309
1314 InfiniteConeSDF() = default;
1315
1322 InfiniteConeSDF(const Vec3T<T>& a_tip, const T& a_angle) noexcept
1323 {
1324 EBGEOMETRY_REQUIRE(std::isfinite(a_tip[0]) && std::isfinite(a_tip[1]) && std::isfinite(a_tip[2]),
1325 "InfiniteConeSDF: the tip must be finite (%g, %g, %g)",
1326 double(a_tip[0]),
1327 double(a_tip[1]),
1328 double(a_tip[2]));
1329 EBGEOMETRY_REQUIRE(a_angle > T(0) && a_angle < T(180),
1330 "InfiniteConeSDF: the angle must be in (0, 180) degrees (%g)",
1331 double(a_angle));
1332
1333 m_tip = a_tip;
1334 m_c[0] = std::sin(T(0.5) * a_angle * pi<T> / T(180));
1335 m_c[1] = std::cos(T(0.5) * a_angle * pi<T> / T(180));
1336 }
1337
1342
1347
1353 operator=(const InfiniteConeSDF&) = default;
1354
1361
1367 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1368 T
1369 signedDistance(const Vec3T<T>& a_point) const noexcept
1370 {
1371 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
1372 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
1373 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
1374 EBGEOMETRY_EXPECT(std::abs(length(m_c) - T(1)) < std::sqrt(Math::Limits<T>::epsilon()));
1375
1376 const Vec3T<T> delta = a_point - m_tip;
1377 const Vec2T<T> q(std::sqrt(delta[0] * delta[0] + delta[2] * delta[2]), -delta[1]);
1378
1379 const T d1 = length(q - m_c * Math::max(dot(q, m_c), T(0.0)));
1380 const T d2 = d1 * ((q[0] * m_c[1] - q[1] * m_c[0] < T(0.0)) ? T(-1.0) : T(1.0));
1381
1382 return d2;
1383 }
1384
1390 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1392 computeBoundingVolume() const noexcept
1393 {
1394 Vec3T<T> hi = Vec3T<T>::max();
1395
1396 hi[1] = m_tip[1];
1397
1399 }
1400
1401protected:
1406
1410 Vec2T<T> m_c = Vec2T<T>(std::sin(pi<T> / T(8)), std::cos(pi<T> / T(8)));
1411};
1412
1425template <class T>
1427{
1428 static_assert(std::is_floating_point_v<T>, "ConeSDF<T>: T must be a floating-point type");
1429
1430public:
1435
1440 ConeSDF() = default;
1441
1448 ConeSDF(const Vec3T<T>& a_tip, const T& a_height, const T& a_angle) noexcept
1449 {
1450 EBGEOMETRY_REQUIRE(std::isfinite(a_tip[0]) && std::isfinite(a_tip[1]) && std::isfinite(a_tip[2]),
1451 "ConeSDF: the tip must be finite (%g, %g, %g)",
1452 double(a_tip[0]),
1453 double(a_tip[1]),
1454 double(a_tip[2]));
1455 EBGEOMETRY_REQUIRE(std::isfinite(a_height) && a_height > T(0),
1456 "ConeSDF: the height must be finite and positive (%g)",
1457 double(a_height));
1459 a_angle > T(0) && a_angle < T(180), "ConeSDF: the angle must be in (0, 180) degrees (%g)", double(a_angle));
1460
1461 m_tip = a_tip;
1462 m_height = a_height;
1463 m_c[0] = std::sin(T(0.5) * a_angle * pi<T> / T(180));
1464 m_c[1] = std::cos(T(0.5) * a_angle * pi<T> / T(180));
1465 }
1466
1470 ConeSDF(const ConeSDF&) = default;
1471
1475 ConeSDF(ConeSDF&&) = default;
1476
1481 ConeSDF&
1482 operator=(const ConeSDF&) = default;
1483
1488 ConeSDF&
1489 operator=(ConeSDF&&) = default;
1490
1496 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1497 T
1498 signedDistance(const Vec3T<T>& a_point) const noexcept
1499 {
1500 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
1501 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
1502 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
1503 EBGEOMETRY_EXPECT(std::abs(length(m_c) - T(1)) < std::sqrt(Math::Limits<T>::epsilon()));
1504 EBGEOMETRY_EXPECT(m_c[1] > T(0));
1505
1506 const Vec3T<T> delta = a_point - m_tip;
1507 const T dr = std::sqrt(delta[0] * delta[0] + delta[2] * delta[2]);
1508 const T dz = delta[1];
1509
1510 constexpr T zero = T(0.0);
1511 constexpr T one = T(1.0);
1512
1513 const Vec2T<T> q = m_height * Vec2T<T>(m_c[0] / m_c[1], -1.0);
1514 const Vec2T<T> w = Vec2T<T>(dr, dz);
1515 const Vec2T<T> a = w - Math::clamp(dot(w, q) / dot(q, q), zero, one) * q;
1516 const Vec2T<T> b = w - Vec2T<T>(q[0] * Math::clamp(w[0] / q[0], zero, one), q[1]);
1517
1518 auto sign = [](const T& x) -> int { return (x > zero) - (x < zero); };
1519
1520 const T k = sign(q[1]);
1521 const T d = Math::min(dot(a, a), dot(b, b));
1522 const T s = Math::max(k * (w[0] * q[1] - w[1] * q[0]), k * (w[1] - q[1]));
1523
1524 return std::sqrt(d) * sign(s);
1525 }
1526
1533 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1535 computeBoundingVolume() const noexcept
1536 {
1537 const T baseRadius = m_height * m_c[0] / m_c[1];
1538
1539 return BoundingVolumes::AABBT<T>(m_tip - Vec3T<T>(baseRadius, m_height, baseRadius),
1540 m_tip + Vec3T<T>(baseRadius, T(0), baseRadius));
1541 }
1542
1543protected:
1548
1552 Vec2T<T> m_c = Vec2T<T>(std::sin(pi<T> / T(8)), std::cos(pi<T> / T(8)));
1553
1557 T m_height = T(1);
1558};
1559
1568template <class T>
1570{
1571 static_assert(std::is_floating_point_v<T>, "RoundedBoxSDF<T>: T must be a floating-point type");
1572
1573public:
1578
1583 RoundedBoxSDF() = default;
1584
1592 RoundedBoxSDF(const Vec3T<T>& a_center, const Vec3T<T>& a_size, const T a_curvature) noexcept
1593 {
1594 EBGEOMETRY_REQUIRE(std::isfinite(a_center[0]) && std::isfinite(a_center[1]) && std::isfinite(a_center[2]),
1595 "RoundedBoxSDF: the center must be finite (%g, %g, %g)",
1596 double(a_center[0]),
1597 double(a_center[1]),
1598 double(a_center[2]));
1599 EBGEOMETRY_REQUIRE(std::isfinite(a_curvature) && a_curvature > T(0),
1600 "RoundedBoxSDF: the curvature must be finite and positive (%g)",
1601 double(a_curvature));
1602 EBGEOMETRY_REQUIRE(std::isfinite(a_size[0]) && std::isfinite(a_size[1]) && std::isfinite(a_size[2]) &&
1603 a_size[0] > T(2) * a_curvature && a_size[1] > T(2) * a_curvature &&
1604 a_size[2] > T(2) * a_curvature,
1605 "RoundedBoxSDF: the size (%g, %g, %g) must be finite and exceed twice the curvature (%g)",
1606 double(a_size[0]),
1607 double(a_size[1]),
1608 double(a_size[2]),
1609 double(a_curvature));
1610
1611 m_center = a_center;
1612 m_dimensions = T(0.5) * a_size - a_curvature * Vec3T<T>::ones();
1613 m_curvature = a_curvature;
1614 }
1615
1619 RoundedBoxSDF(const RoundedBoxSDF&) = default;
1620
1625
1631 operator=(const RoundedBoxSDF&) = default;
1632
1639
1645 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1646 T
1647 signedDistance(const Vec3T<T>& a_point) const noexcept
1648 {
1649 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
1650 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
1651 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
1652
1653 // q is the point's per-axis distance beyond the inner box (negative inside it). Outside, the
1654 // distance to the inner box is the length of q's positive part; inside, it is the distance to
1655 // the nearest face, max(q) <= 0. Either way the rounding moves the surface out by m_curvature.
1656 const Vec3T<T> p = a_point - m_center;
1657 const Vec3T<T> q(
1658 std::abs(p[0]) - m_dimensions[0], std::abs(p[1]) - m_dimensions[1], std::abs(p[2]) - m_dimensions[2]);
1659
1660 const T outside = length(max(q, Vec3T<T>::zeros()));
1661 const T inside = Math::min(Math::max(q[0], Math::max(q[1], q[2])), T(0));
1662
1663 return outside + inside - m_curvature;
1664 }
1665
1671 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1673 computeBoundingVolume() const noexcept
1674 {
1676
1677 return BoundingVolumes::AABBT<T>(m_center - half, m_center + half);
1678 }
1679
1680protected:
1684 T m_curvature = T(0.1);
1685
1690
1694 Vec3T<T> m_dimensions = Vec3T<T>(T(0.4), T(0.4), T(0.4));
1695};
1696
1714template <class T>
1716{
1717 static_assert(std::is_floating_point_v<T>, "PerlinSDF<T>: T must be a floating-point type");
1718
1719public:
1725
1730 PerlinSDF() noexcept : PerlinSDF(T(1), Vec3T<T>::ones(), T(0.5), 1U)
1731 {}
1732
1741 PerlinSDF(const T a_noiseAmplitude,
1742 const Vec3T<T> a_noiseFrequency,
1743 const T a_noisePersistence,
1744 const unsigned int a_noiseOctaves) noexcept
1745 {
1747 std::isfinite(a_noiseAmplitude), "PerlinSDF: the noise amplitude must be finite (%g)", double(a_noiseAmplitude));
1748 EBGEOMETRY_REQUIRE(std::isfinite(a_noiseFrequency[0]) && std::isfinite(a_noiseFrequency[1]) &&
1749 std::isfinite(a_noiseFrequency[2]),
1750 "PerlinSDF: the noise frequency must be finite (%g, %g, %g)",
1751 double(a_noiseFrequency[0]),
1752 double(a_noiseFrequency[1]),
1753 double(a_noiseFrequency[2]));
1754 EBGEOMETRY_REQUIRE(std::isfinite(a_noisePersistence),
1755 "PerlinSDF: the noise persistence must be finite (%g)",
1756 double(a_noisePersistence));
1757
1758 m_noiseAmplitude = a_noiseAmplitude;
1759 m_noiseFrequency = a_noiseFrequency;
1760 m_noisePersistence = Math::min(T(1), a_noisePersistence);
1761 m_noiseOctaves = Math::max(1U, a_noiseOctaves);
1762
1763 // Each octave divides the frequency by the persistence, so zero would give an infinite frequency
1764 // (and NaN noise) for an octave that contributes nothing anyway.
1765 if (!(m_noisePersistence > T(0))) {
1766 m_noisePersistence = T(1);
1767 m_noiseOctaves = 1U;
1768 }
1769
1770 std::mt19937 g(0);
1771 this->shuffle(g);
1772 }
1773
1777 PerlinSDF(const PerlinSDF&) = default;
1778
1782 PerlinSDF(PerlinSDF&&) = default;
1783
1788 PerlinSDF&
1789 operator=(const PerlinSDF&) = default;
1790
1795 PerlinSDF&
1796 operator=(PerlinSDF&&) = default;
1797
1803 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1804 T
1805 signedDistance(const Vec3T<T>& a_point) const noexcept
1806 {
1807 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
1808 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
1809 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
1810
1811 T ret = 0.0;
1812
1813 Vec3T<T> curFreq = m_noiseFrequency;
1814 T curAmp = 1.0;
1815
1816 for (unsigned int curOctave = 0; curOctave < m_noiseOctaves; curOctave++) {
1817 ret += T(0.5) * curAmp * (T(1) + this->noise(a_point * curFreq));
1818
1819 curFreq = curFreq / m_noisePersistence;
1820 curAmp = curAmp * m_noisePersistence;
1821 }
1822
1823 return ret * m_noiseAmplitude;
1824 };
1825
1838 template <class URNG>
1839 void
1840 shuffle(URNG& g) noexcept
1841 {
1842
1843 for (unsigned int i = 0; i < 256; i++) {
1844 m_permutationTable[i] = static_cast<int>(i);
1845 }
1846
1847 std::shuffle(m_permutationTable.begin(), m_permutationTable.begin() + 256, g);
1848
1849 for (int i = 0; i < 256; i++) {
1851 }
1852 }
1853
1860 {
1861 return m_permutationTable;
1862 }
1863
1869 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1871 computeBoundingVolume() const noexcept
1872 {
1874 }
1875
1876protected:
1881
1886
1891
1898
1902 unsigned int m_noiseOctaves = 1U;
1903
1911 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1912 T
1913 lerp(const T t, const T a, const T b) const noexcept
1914 {
1915 return a + t * (b - a);
1916 };
1917
1923 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1924 T
1925 fade(const T t) const noexcept
1926 {
1927 return t * t * t * (t * (t * 6 - 15) + 10);
1928 };
1929
1938 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1939 T
1940 grad(const int hash, const T x, const T y, const T z) const noexcept
1941 {
1942 const int h = hash & 15;
1943 const T u = h < 8 ? x : y;
1944 const T v = h < 4 ? y : h == 12 || h == 14 ? x : z;
1945 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
1946 }
1947
1953 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
1954 T
1955 noise(const Vec3T<T>& a_point) const noexcept
1956 {
1957 // Lower cube corner
1958 const int X = static_cast<int>(std::floor(a_point[0])) & 255;
1959 const int Y = static_cast<int>(std::floor(a_point[1])) & 255;
1960 const int Z = static_cast<int>(std::floor(a_point[2])) & 255;
1961
1962 // Relative distance wrt lower cube corner
1963 const T x = a_point[0] - std::floor(a_point[0]);
1964 const T y = a_point[1] - std::floor(a_point[1]);
1965 const T z = a_point[2] - std::floor(a_point[2]);
1966
1967 // Fade curves
1968 const T u = fade(x);
1969 const T v = fade(y);
1970 const T w = fade(z);
1971
1972 // Hash coordinates of 8 cube corners
1973 const int A = m_permutationTable[X] + Y;
1974 const int AA = m_permutationTable[A] + Z;
1975 const int AB = m_permutationTable[A + 1] + Z;
1976 const int B = m_permutationTable[X + 1] + Y;
1977 const int BA = m_permutationTable[B] + Z;
1978 const int BB = m_permutationTable[B + 1] + Z;
1979
1980 // Add blended results from 8 corners of cube
1981 return lerp(
1982 w,
1983 lerp(v,
1984 lerp(u, grad(m_permutationTable[AA], x, y, z), grad(m_permutationTable[BA], x - 1, y, z)),
1985 lerp(u, grad(m_permutationTable[AB], x, y - 1, z), grad(m_permutationTable[BB], x - 1, y - 1, z))),
1986 lerp(v,
1987 lerp(u, grad(m_permutationTable[AA + 1], x, y, z - 1), grad(m_permutationTable[BA + 1], x - 1, y, z - 1)),
1988 lerp(u,
1989 grad(m_permutationTable[AB + 1], x, y - 1, z - 1),
1990 grad(m_permutationTable[BB + 1], x - 1, y - 1, z - 1))));
1991 };
1992};
1993
2016template <class T>
2018{
2019 static_assert(std::is_floating_point_v<T>, "RoundedCylinderSDF<T>: T must be a floating-point type");
2020
2021public:
2026
2032
2041 RoundedCylinderSDF(const Vec3T<T>& a_center, const T a_radius, const T a_curvature, const T a_height) noexcept
2042 {
2043 EBGEOMETRY_REQUIRE(std::isfinite(a_center[0]) && std::isfinite(a_center[1]) && std::isfinite(a_center[2]),
2044 "RoundedCylinderSDF: the center must be finite (%g, %g, %g)",
2045 double(a_center[0]),
2046 double(a_center[1]),
2047 double(a_center[2]));
2048 EBGEOMETRY_REQUIRE(std::isfinite(a_radius) && a_radius > T(0),
2049 "RoundedCylinderSDF: the radius must be finite and positive (%g)",
2050 double(a_radius));
2051 EBGEOMETRY_REQUIRE(std::isfinite(a_curvature) && a_curvature > T(0),
2052 "RoundedCylinderSDF: the curvature must be finite and positive (%g)",
2053 double(a_curvature));
2054 EBGEOMETRY_REQUIRE(std::isfinite(a_height) && a_height > T(0),
2055 "RoundedCylinderSDF: the height must be finite and positive (%g)",
2056 double(a_height));
2057 EBGEOMETRY_REQUIRE(a_curvature < a_radius,
2058 "RoundedCylinderSDF: the curvature (%g) must be less than the radius (%g)",
2059 double(a_curvature),
2060 double(a_radius));
2061 EBGEOMETRY_REQUIRE(T(2) * a_curvature < a_height,
2062 "RoundedCylinderSDF: twice the curvature (%g) must be less than the height (%g)",
2063 double(a_curvature),
2064 double(a_height));
2065
2066 m_center = a_center;
2067 m_majorRadius = a_radius - a_curvature;
2068 m_minorRadius = a_curvature;
2069 m_height = T(0.5) * a_height - a_curvature;
2070 }
2071
2076
2081
2088
2095
2101 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
2102 T
2103 signedDistance(const Vec3T<T>& a_point) const noexcept
2104 {
2105 EBGEOMETRY_EXPECT(std::isfinite(a_point[0]));
2106 EBGEOMETRY_EXPECT(std::isfinite(a_point[1]));
2107 EBGEOMETRY_EXPECT(std::isfinite(a_point[2]));
2108
2109 const Vec3T<T> p = a_point - m_center;
2110 const T xz = std::sqrt(p[2] * p[2] + p[0] * p[0]);
2111 const auto d1 = Vec2T<T>(xz - m_majorRadius, std::abs(p[1]) - m_height);
2112 const auto d2 = Vec2T<T>(Math::max(d1[0], T(0)), Math::max(d1[1], T(0)));
2113
2114 return Math::min(Math::max(d1[0], d1[1]), T(0)) + std::sqrt(d2[0] * d2[0] + d2[1] * d2[1]) - m_minorRadius;
2115 }
2116
2122 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
2124 computeBoundingVolume() const noexcept
2125 {
2126 const T radius = m_majorRadius + m_minorRadius;
2127 const Vec3T<T> half(radius, m_height + m_minorRadius, radius);
2128
2129 return BoundingVolumes::AABBT<T>(m_center - half, m_center + half);
2130 }
2131
2132protected:
2137
2141 T m_majorRadius = T(0.9);
2142
2146 T m_minorRadius = T(0.1);
2147
2151 T m_height = T(0.4);
2152};
2153
2158static_assert(std::is_trivially_copyable_v<PlaneSDF<float>>, "PlaneSDF<float> must be trivially copyable");
2159static_assert(std::is_trivially_copyable_v<PlaneSDF<double>>, "PlaneSDF<double> must be trivially copyable");
2160static_assert(std::is_trivially_copyable_v<SphereSDF<float>>, "SphereSDF<float> must be trivially copyable");
2161static_assert(std::is_trivially_copyable_v<SphereSDF<double>>, "SphereSDF<double> must be trivially copyable");
2162static_assert(std::is_trivially_copyable_v<BoxSDF<float>>, "BoxSDF<float> must be trivially copyable");
2163static_assert(std::is_trivially_copyable_v<BoxSDF<double>>, "BoxSDF<double> must be trivially copyable");
2164static_assert(std::is_trivially_copyable_v<TorusSDF<float>>, "TorusSDF<float> must be trivially copyable");
2165static_assert(std::is_trivially_copyable_v<TorusSDF<double>>, "TorusSDF<double> must be trivially copyable");
2166static_assert(std::is_trivially_copyable_v<CylinderSDF<float>>, "CylinderSDF<float> must be trivially copyable");
2167static_assert(std::is_trivially_copyable_v<CylinderSDF<double>>, "CylinderSDF<double> must be trivially copyable");
2168static_assert(std::is_trivially_copyable_v<InfiniteCylinderSDF<float>>,
2169 "InfiniteCylinderSDF<float> must be trivially copyable");
2170static_assert(std::is_trivially_copyable_v<InfiniteCylinderSDF<double>>,
2171 "InfiniteCylinderSDF<double> must be trivially copyable");
2172static_assert(std::is_trivially_copyable_v<CapsuleSDF<float>>, "CapsuleSDF<float> must be trivially copyable");
2173static_assert(std::is_trivially_copyable_v<CapsuleSDF<double>>, "CapsuleSDF<double> must be trivially copyable");
2174static_assert(std::is_trivially_copyable_v<InfiniteConeSDF<float>>,
2175 "InfiniteConeSDF<float> must be trivially copyable");
2176static_assert(std::is_trivially_copyable_v<InfiniteConeSDF<double>>,
2177 "InfiniteConeSDF<double> must be trivially copyable");
2178static_assert(std::is_trivially_copyable_v<ConeSDF<float>>, "ConeSDF<float> must be trivially copyable");
2179static_assert(std::is_trivially_copyable_v<ConeSDF<double>>, "ConeSDF<double> must be trivially copyable");
2180static_assert(std::is_trivially_copyable_v<RoundedBoxSDF<float>>, "RoundedBoxSDF<float> must be trivially copyable");
2181static_assert(std::is_trivially_copyable_v<RoundedBoxSDF<double>>, "RoundedBoxSDF<double> must be trivially copyable");
2182static_assert(std::is_trivially_copyable_v<PerlinSDF<float>>, "PerlinSDF<float> must be trivially copyable");
2183static_assert(std::is_trivially_copyable_v<PerlinSDF<double>>, "PerlinSDF<double> must be trivially copyable");
2184static_assert(std::is_trivially_copyable_v<RoundedCylinderSDF<float>>,
2185 "RoundedCylinderSDF<float> must be trivially copyable");
2186static_assert(std::is_trivially_copyable_v<RoundedCylinderSDF<double>>,
2187 "RoundedCylinderSDF<double> must be trivially copyable");
2188
2189} // namespace EBGeometry
2190
2191// Every translation unit that sees these shapes sees their ray forms too, so firstHit() on one of them
2192// is the same function everywhere.
2194
2195#endif
Ray forms (see RayForm) for the analytic shapes that have a closed-form crossing: PlaneSDF,...
A fixed-size array that compiles for both host and device.
Declarations of bounding volume types used in bounding volume hierarchies.
Mathematical constants for EBGeometry.
How far a function's value can be trusted as a distance: DistanceQuality, and the distanceQualityOf t...
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
Utility macros for EBGeometry.
#define EBGEOMETRY_REQUIRE(cond,...)
Always-on check of user input and one-time host setup.
Definition EBGeometry_Macros.hpp:84
#define EBGEOMETRY_EXPECT(cond)
Runtime precondition assertion for EBGeometry.
Definition EBGeometry_Macros.hpp:155
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.
Axis-aligned bounding box (AABB) enclosing a set of 3D points.
Definition EBGeometry_BoundingVolumes.hpp:37
Signed distance field for an axis-aligned box (AABB).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:351
BoxSDF & operator=(const BoxSDF &)=default
Copy assignment.
BoxSDF()=default
Default constructor. Constructs a unit cube centered at the origin: [-0.5, 0.5]^3.
BoxSDF(const BoxSDF &)=default
Copy constructor.
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:503
Vec3T< T > m_loCorner
Low box corner.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:512
Vec3T< T > & getHighCorner() noexcept
Get upper-right corner.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:460
Vec3T< T > & getLowCorner() noexcept
Get lower-left corner.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:438
BoxSDF & operator=(BoxSDF &&)=default
Move assignment.
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the axis-aligned box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:472
const Vec3T< T > & getHighCorner() const noexcept
Get upper-right corner.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:449
const Vec3T< T > & getLowCorner() const noexcept
Get lower-left corner.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:427
Vec3T< T > m_hiCorner
High box corner.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:517
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:358
BoxSDF(BoxSDF &&)=default
Move constructor.
BoxSDF(const Vec3T< T > &a_loCorner, const Vec3T< T > &a_hiCorner) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:371
Signed distance field for a capsule (pill shape): a cylinder capped with hemispheres.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1117
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1124
const Vec3T< T > & getCenter2() const noexcept
Get the center of the second hemispherical cap.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1251
CapsuleSDF & operator=(const CapsuleSDF &)=default
Copy assignment.
Vec3T< T > m_center2
Center of the other hemispherical cap.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1276
CapsuleSDF()=default
Default constructor. Constructs a capsule with tips at (0,-1,0) and (0,1,0), radius 0....
const T & getRadius() const noexcept
Get the radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1262
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1228
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the capsule.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1202
CapsuleSDF(const CapsuleSDF &)=default
Copy constructor.
CapsuleSDF & operator=(CapsuleSDF &&)=default
Move assignment.
T m_radius
Capsule radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1281
CapsuleSDF(const Vec3T< T > &a_tip1, const Vec3T< T > &a_tip2, const T &a_radius) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1144
const Vec3T< T > & getCenter1() const noexcept
Get the center of the first hemispherical cap.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1240
CapsuleSDF(CapsuleSDF &&)=default
Move constructor.
Vec3T< T > m_center1
Center of one hemispherical cap.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1271
Signed distance field for a finite cone.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1427
ConeSDF()=default
Default constructor. Constructs a finite cone with its tip at the origin, height 1,...
Vec3T< T > m_tip
Tip position.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1547
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1535
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the finite cone.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1498
ConeSDF & operator=(ConeSDF &&)=default
Move assignment.
ConeSDF & operator=(const ConeSDF &)=default
Copy assignment.
ConeSDF(ConeSDF &&)=default
Move constructor.
T m_height
Cone height (tip to base).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1557
ConeSDF(const Vec3T< T > &a_tip, const T &a_height, const T &a_angle) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1448
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1434
ConeSDF(const ConeSDF &)=default
Copy constructor.
Vec2T< T > m_c
(sin, cos) of the half opening-angle. Default: 45° full angle → half-angle 22.5°.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1552
Signed distance field for a finite, flat-capped cylinder.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:728
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:893
T m_length
Distance between the two endpoints.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:928
Vec3T< T > m_center1
One endpoint (cap center).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:908
const Vec3T< T > & getCenter2() const noexcept
Get the other endpoint.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:820
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the cylinder.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:843
Vec3T< T > m_center2
Other endpoint (cap center).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:913
CylinderSDF(const Vec3T< T > &a_center1, const Vec3T< T > &a_center2, const T &a_radius) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:749
CylinderSDF()=default
Default constructor. Constructs a unit cylinder of radius 1 and height 1, centered at the origin with...
CylinderSDF(const CylinderSDF &)=default
Copy constructor.
Vec3T< T > m_center
Midpoint of m_center1 and m_center2.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:918
const T & getRadius() const noexcept
Get radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:831
Vec3T< T > m_axis
Unit axis pointing from m_center1 to m_center2.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:923
const Vec3T< T > & getCenter1() const noexcept
Get one endpoint.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:809
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:735
T m_radius
Cylinder radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:933
CylinderSDF(CylinderSDF &&)=default
Move constructor.
CylinderSDF & operator=(CylinderSDF &&)=default
Move assignment.
CylinderSDF & operator=(const CylinderSDF &)=default
Copy assignment.
Signed distance field for an infinite cone.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1301
InfiniteConeSDF(const InfiniteConeSDF &)=default
Copy constructor.
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1392
InfiniteConeSDF()=default
Default constructor. Constructs an infinite cone with tip at the origin, 45° full opening angle,...
Vec3T< T > m_tip
Tip position.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1405
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1308
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the infinite cone.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1369
Vec2T< T > m_c
(sin, cos) of the half opening-angle. Default: 45° full angle → half-angle 22.5°.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1410
InfiniteConeSDF(const Vec3T< T > &a_tip, const T &a_angle) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1322
InfiniteConeSDF(InfiniteConeSDF &&)=default
Move constructor.
InfiniteConeSDF & operator=(InfiniteConeSDF &&)=default
Move assignment.
InfiniteConeSDF & operator=(const InfiniteConeSDF &)=default
Copy assignment.
Signed distance field for an infinitely long cylinder.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:947
T m_radius
Cylinder radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1090
InfiniteCylinderSDF & operator=(const InfiniteCylinderSDF &)=default
Copy assignment.
const size_t & getAxis() const noexcept
Get the coordinate axis the cylinder runs along.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1076
InfiniteCylinderSDF(const Vec3T< T > &a_center, const T &a_radius, const size_t a_axis) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:968
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the infinite cylinder.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1016
InfiniteCylinderSDF(const InfiniteCylinderSDF &)=default
Copy constructor.
Vec3T< T > m_center
Center point on the cylinder axis.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1085
InfiniteCylinderSDF(InfiniteCylinderSDF &&)=default
Move constructor.
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1037
const Vec3T< T > & getCenter() const noexcept
Get the point on the axis.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1054
InfiniteCylinderSDF()=default
Default constructor. Constructs an infinite cylinder of radius 1 centered at the origin with its axis...
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:954
size_t m_axis
Coordinate axis index (0 = x, 1 = y, 2 = z).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1095
const T & getRadius() const noexcept
Get the radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1065
InfiniteCylinderSDF & operator=(InfiniteCylinderSDF &&)=default
Move assignment.
Ken Perlin's gradient-noise implicit function.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1716
PerlinSDF(const T a_noiseAmplitude, const Vec3T< T > a_noiseFrequency, const T a_noisePersistence, const unsigned int a_noiseOctaves) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1741
Array< int, 512 > m_permutationTable
Integer hash permutation table (512 entries: [0..255] mirrored).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1897
unsigned int m_noiseOctaves
Number of noise octaves.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1902
Vec3T< T > m_noiseFrequency
Spatial noise frequency along each Cartesian axis.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1880
PerlinSDF & operator=(const PerlinSDF &)=default
Copy assignment.
PerlinSDF(const PerlinSDF &)=default
Copy constructor.
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: not at all. The value is noise,...
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1724
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function. Generates a noise value on [0, m_noiseAmplitude] for one octave.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1805
T noise(const Vec3T< T > &a_point) const noexcept
Single-octave Perlin noise evaluation.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1955
T grad(const int hash, const T x, const T y, const T z) const noexcept
Ken Perlin's gradient hash function.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1940
T lerp(const T t, const T a, const T b) const noexcept
Ken Perlin's linear interpolation helper.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1913
Array< int, 512 > & getPermutationTable() noexcept
Get the internal permutation table.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1859
PerlinSDF(PerlinSDF &&)=default
Move constructor.
T fade(const T t) const noexcept
Ken Perlin's fade (smoothstep) function: 6t^5 - 15t^4 + 10t^3.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1925
PerlinSDF & operator=(PerlinSDF &&)=default
Move assignment.
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1871
T m_noiseAmplitude
Noise amplitude (output scale).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1885
PerlinSDF() noexcept
Default constructor. Constructs a single-octave Perlin noise field with unit amplitude,...
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1730
T m_noisePersistence
Per-octave amplitude decay factor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1890
void shuffle(URNG &g) noexcept
Shuffle the permutation table with the provided uniform random number generator.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1840
Signed distance function for a plane.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:60
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:67
const Vec3T< T > & getPoint() const noexcept
Get the point on the plane.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:162
PlaneSDF()=default
Default constructor. Constructs the y = 0 plane with outward normal (0, 1, 0).
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:151
PlaneSDF(const Vec3T< T > &a_point, const Vec3T< T > &a_normal) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:81
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the plane.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:134
PlaneSDF(const PlaneSDF &)=default
Copy constructor.
const Vec3T< T > & getNormal() const noexcept
Get the unit normal of the plane.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:173
PlaneSDF & operator=(PlaneSDF &&)=default
Move assignment.
PlaneSDF(PlaneSDF &&)=default
Move constructor.
Vec3T< T > m_point
Point on plane.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:182
Vec3T< T > m_normal
Plane normal vector (unit length).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:187
PlaneSDF & operator=(const PlaneSDF &)=default
Copy assignment.
Signed distance field for an axis-aligned box with rounded edges and corners.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1570
RoundedBoxSDF()=default
Default constructor. Constructs a rounded unit cube, [-0.5, 0.5]^3, centered at the origin,...
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1673
T m_curvature
Corner rounding radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1684
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1577
RoundedBoxSDF & operator=(RoundedBoxSDF &&)=default
Move assignment.
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the rounded box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1647
RoundedBoxSDF(const Vec3T< T > &a_center, const Vec3T< T > &a_size, const T a_curvature) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1592
RoundedBoxSDF(const RoundedBoxSDF &)=default
Copy constructor.
Vec3T< T > m_dimensions
Half-extents of the inner box (= 0.5 * outer size - curvature).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1694
Vec3T< T > m_center
Box center.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:1689
RoundedBoxSDF(RoundedBoxSDF &&)=default
Move constructor.
RoundedBoxSDF & operator=(const RoundedBoxSDF &)=default
Copy assignment.
Signed distance field for a cylinder with rounded (toroidal) edges.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2018
RoundedCylinderSDF(RoundedCylinderSDF &&)=default
Move constructor.
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2124
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2025
RoundedCylinderSDF & operator=(RoundedCylinderSDF &&)=default
Move assignment.
RoundedCylinderSDF(const RoundedCylinderSDF &)=default
Copy constructor.
T m_height
Inner half-height (= 0.5*height - curvature).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2151
RoundedCylinderSDF & operator=(const RoundedCylinderSDF &)=default
Copy assignment.
Vec3T< T > m_center
Cylinder center.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2136
T m_majorRadius
Inner cylinder radius (= outer radius - curvature).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2141
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the rounded cylinder.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2103
RoundedCylinderSDF(const Vec3T< T > &a_center, const T a_radius, const T a_curvature, const T a_height) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2041
T m_minorRadius
Edge rounding radius (= curvature).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:2146
RoundedCylinderSDF()=default
Default constructor. Constructs a rounded cylinder centered at the origin, axis along y,...
Signed distance field for a sphere.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:199
Vec3T< T > & getCenter() noexcept
Get sphere center (mutable).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:274
SphereSDF()=default
Default constructor. Constructs a unit sphere centered at the origin.
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the sphere.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:308
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:324
SphereSDF & operator=(SphereSDF &&)=default
Move assignment.
SphereSDF & operator=(const SphereSDF &)=default
Copy assignment.
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:206
const Vec3T< T > & getCenter() const noexcept
Get sphere center (const).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:263
Vec3T< T > m_center
Sphere center.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:333
T m_radius
Sphere radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:338
const T & getRadius() const noexcept
Get sphere radius (const).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:285
SphereSDF(SphereSDF &&)=default
Move constructor.
SphereSDF(const SphereSDF &)=default
Copy constructor.
T & getRadius() noexcept
Get sphere radius (mutable).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:296
SphereSDF(const Vec3T< T > &a_center, const T &a_radius) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:218
Signed distance field for a torus.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:533
TorusSDF & operator=(const TorusSDF &)=default
Copy assignment.
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance function for the torus.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:672
T m_minorRadius
Minor (tube) radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:714
Vec3T< T > & getCenter() noexcept
Get torus center.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:617
T m_majorRadius
Major (ring) radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:709
TorusSDF(const Vec3T< T > &a_center, const T &a_majorRadius, const T &a_minorRadius) noexcept
Full constructor.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:553
static constexpr DistanceQuality distanceQuality
How far signedDistance() can be trusted as a distance: the Euclidean distance to the surface.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:540
const T & getMinorRadius() const noexcept
Get minor radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:650
TorusSDF(TorusSDF &&)=default
Move constructor.
TorusSDF(const TorusSDF &)=default
Copy constructor.
const T & getMajorRadius() const noexcept
Get major radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:628
T & getMajorRadius() noexcept
Get major radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:639
Vec3T< T > m_center
Torus center.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:704
TorusSDF & operator=(TorusSDF &&)=default
Move assignment.
T & getMinorRadius() noexcept
Get minor radius.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:661
TorusSDF()=default
Default constructor. Constructs a torus centered at the origin with major radius 1 and minor radius 0...
const Vec3T< T > & getCenter() const noexcept
Get torus center.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:606
BoundingVolumes::AABBT< T > computeBoundingVolume() const noexcept
The shape's axis-aligned bounding box.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:692
Two-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:37
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:258
static constexpr Vec3T< T > max() noexcept
Return the most-positive representable vector.
size_t maxDir(const bool a_doAbs) const noexcept
Return the direction which has the largest component (can be absolute)
T length() const noexcept
Compute vector length.
static constexpr Vec3T< T > ones() noexcept
Return a vector with x = y = z = 1.
static constexpr Vec3T< T > zeros() noexcept
Return a vector with x = y = z = 0.
constexpr T clamp(const T &a_value, const T &a_lo, const T &a_hi) noexcept
A value limited to [lo, hi].
Definition EBGeometry_Math.hpp:78
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
Vec2T< T > min(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Component-wise minimum of two vectors.
T length(const Vec2T< T > &v) noexcept
Euclidean length of a 2D vector.
T dot(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Dot product of two 2D vectors.
DistanceQuality
How far the value of a signed distance function can be trusted, from strongest to weakest.
Definition EBGeometry_DistanceQuality.hpp:25
@ Exact
The value's magnitude is the Euclidean distance to the surface.
@ NotADistance
Only the sign is meaningful, so the function describes a surface (its zero level set) but says nothin...
Vec2T< T > max(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Component-wise maximum of two vectors.
Fixed-size array with host- and device-callable members.
Definition EBGeometry_Array.hpp:33
constexpr T * begin() noexcept
Iterator to the first element.
Definition EBGeometry_Array.hpp:104
Numeric limits, with the meanings of the std::numeric_limits members of the same names.
Definition EBGeometry_Math.hpp:91