diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/collection.h | 263 | ||||
-rw-r--r-- | lib/enumDetails.h | 102 | ||||
-rw-r--r-- | lib/glArrays.h | 26 | ||||
-rw-r--r-- | lib/manyPtr.h | 86 | ||||
-rw-r--r-- | lib/maths.cpp | 4 | ||||
-rw-r--r-- | lib/maths.h | 6 | ||||
-rw-r--r-- | lib/persistence.h | 3 | ||||
-rw-r--r-- | lib/ray.h | 47 | ||||
-rw-r--r-- | lib/stream_support.h | 2 |
9 files changed, 422 insertions, 117 deletions
diff --git a/lib/collection.h b/lib/collection.h index 6802bcb..1c77e1c 100644 --- a/lib/collection.h +++ b/lib/collection.h @@ -3,29 +3,62 @@ #include <algorithm> #include <functional> #include <memory> +#include <special_members.h> #include <type_traits> #include <vector> -template<typename Object, bool shared = true> class Collection { +template<typename Ptr, typename... Others> class Collection { public: + Collection() = default; virtual ~Collection() = default; - using Ptr = std::conditional_t<shared, std::shared_ptr<Object>, std::unique_ptr<Object>>; + DEFAULT_MOVE_NO_COPY(Collection); + + using Object = Ptr::element_type; using Objects = std::vector<Ptr>; - Objects objects; + template<typename T> using OtherObjects = std::vector<T *>; + + Collection & + operator=(Objects && other) + { + objects = std::move(other); + ((std::get<OtherObjects<Others>>(otherObjects).clear()), ...); + for (const auto & other : objects) { + addOthersPtr(other.get()); + } + return *this; + } + + const Ptr & + operator[](size_t idx) const + { + return objects[idx]; + } + + template<typename T = Object> + requires(std::is_same_v<T, Object> || (std::is_base_of_v<Others, T> || ...)) + [[nodiscard]] auto + size() const noexcept + { + return containerFor<T>().size(); + } template<typename T = Object, typename... Params> auto create(Params &&... params) requires std::is_base_of_v<Object, T> { - if constexpr (shared) { + if constexpr (requires(Ptr ptr) { ptr = std::make_shared<T>(std::forward<Params>(params)...); }) { auto obj = std::make_shared<T>(std::forward<Params>(params)...); objects.emplace_back(obj); + addOthersType<T>(obj.get()); return obj; } else { - return static_cast<T *>(objects.emplace_back(std::make_unique<T>(std::forward<Params>(params)...)).get()); + auto obj = static_cast<T *>( + objects.emplace_back(std::make_unique<T>(std::forward<Params>(params)...)).get()); + addOthersType<T>(obj); + return obj; } } @@ -33,12 +66,19 @@ public: T * find() { - if (auto i = std::find_if(objects.begin(), objects.end(), - [](auto && o) { - return (dynamic_cast<T *>(o.get())); - }); - i != objects.end()) { - return static_cast<T *>(i->get()); + const auto & srcObjects = containerFor<T>(); + if constexpr (std::is_convertible_v<typename std::remove_reference_t<decltype(srcObjects)>::value_type, T *>) { + if (srcObjects.empty()) { + return nullptr; + } + return srcObjects.front(); + } + else if (auto i = std::find_if(srcObjects.begin(), srcObjects.end(), + [](auto && o) { + return dynamic_cast<T *>(std::to_address(o)) != nullptr; + }); + i != srcObjects.end()) { + return static_cast<T *>(std::to_address(*i)); } return nullptr; } @@ -58,74 +98,229 @@ public: auto apply(const auto & m, Params &&... params) const { - return apply_internal<T>(objects.begin(), objects.end(), m, std::forward<Params>(params)...); + const auto & srcObjects = containerFor<T>(); + return apply_internal<T>(srcObjects.begin(), srcObjects.end(), m, std::forward<Params>(params)...); } template<typename T = Object, typename... Params> auto rapply(const auto & m, Params &&... params) const { - return apply_internal<T>(objects.rbegin(), objects.rend(), m, std::forward<Params>(params)...); + const auto & srcObjects = containerFor<T>(); + return apply_internal<T>(srcObjects.rbegin(), srcObjects.rend(), m, std::forward<Params>(params)...); } template<typename T = Object, typename... Params> auto applyOne(const auto & m, Params &&... params) const { - return applyOne_internal<T>(objects.begin(), objects.end(), m, std::forward<Params>(params)...); + const auto & srcObjects = containerFor<T>(); + return applyOne_internal<T>(srcObjects.begin(), srcObjects.end(), m, std::forward<Params>(params)...); } template<typename T = Object, typename... Params> auto rapplyOne(const auto & m, Params &&... params) const { - return applyOne_internal<T>(objects.rbegin(), objects.rend(), m, std::forward<Params>(params)...); + const auto & srcObjects = containerFor<T>(); + return applyOne_internal<T>(srcObjects.rbegin(), srcObjects.rend(), m, std::forward<Params>(params)...); } - template<typename T = Object> + template<typename T> + requires std::is_base_of_v<Object, T> auto removeAll() { - return std::erase_if(objects, [](auto && op) { - return dynamic_cast<T *>(op.get()); - }); + auto removeAllFrom = [](auto & container) { + if constexpr (std::is_base_of_v<T, std::decay_t<decltype(*container.front())>>) { + const auto size = container.size(); + container.clear(); + return size; + } + else { + return std::erase_if(container, [](auto && objPtr) -> bool { + return dynamic_cast<const T *>(std::to_address(objPtr)); + }); + } + }; + (removeAllFrom(std::get<OtherObjects<Others>>(otherObjects)), ...); + return removeAllFrom(objects); + } + + void + clear() + { + ((std::get<OtherObjects<Others>>(otherObjects).clear()), ...); + objects.clear(); } - auto + [[nodiscard]] auto + begin() const + { + return objects.begin(); + } + + [[nodiscard]] auto end() const { return objects.end(); } - auto + [[nodiscard]] auto + rbegin() const + { + return objects.rbegin(); + } + + [[nodiscard]] auto rend() const { return objects.rend(); } + [[nodiscard]] bool + empty() const + { + return objects.empty(); + } + + decltype(auto) + emplace(Ptr && ptr) + { + const auto & object = objects.emplace_back(std::move(ptr)); + addOthersPtr(object.get()); + return object; + } + protected: + Objects objects; + std::tuple<OtherObjects<Others>...> otherObjects; + + template<typename T> + void + addOthersType(T * obj) + { + applyToOthersType<T>( + [](auto & others, auto ptr) { + others.emplace_back(ptr); + }, + obj); + } + + void + addOthersPtr(Object * obj) + { + applyToOthersPtr( + [](auto & others, auto ptr) { + others.emplace_back(ptr); + }, + obj); + } + + template<typename T, typename... Params> + requires(sizeof...(Others) == 0) + void + applyToOthersType(const auto &, Params...) + { + } + + void + applyToOthersPtr(const auto &, Object *) + requires(sizeof...(Others) == 0) + { + } + + template<typename T, typename... Params> + requires(sizeof...(Others) > 0) + void + applyToOthersType(const auto & func, Params &&... params) + { + ( + [&]() { + if constexpr (std::is_convertible_v<T *, Others *>) { + std::invoke( + func, std::get<OtherObjects<Others>>(otherObjects), std::forward<Params>(params)...); + } + }(), + ...); + } + + void + applyToOthersPtr(const auto & func, Object * obj) + requires(sizeof...(Others) > 0) + { + ( + [&]() { + if (auto ptr = dynamic_cast<Others *>(obj)) { + std::invoke(func, std::get<OtherObjects<Others>>(otherObjects), ptr); + } + }(), + ...); + } + + template<typename T> + requires((std::is_base_of_v<Others, T> || ...)) + [[nodiscard]] consteval static size_t + idx() + { + size_t typeIdx = 0; + auto found = ((++typeIdx && std::is_base_of_v<Others, T>) || ...); + return typeIdx - found; + } + + template<typename T> + [[nodiscard]] + constexpr const auto & + containerFor() const + { + if constexpr ((std::is_base_of_v<Others, T> || ...)) { + return std::get<idx<T>()>(otherObjects); + } + else { + return objects; + } + } + template<typename T = Object, typename... Params> auto apply_internal(const auto begin, const auto end, const auto & m, Params &&... params) const { - return std::count_if(begin, end, [&m, ¶ms...](auto && op) { - if (auto o = dynamic_cast<T *>(op.get())) { - std::invoke(m, o, std::forward<Params>(params)...); - return true; - } - return false; - }); + if constexpr (std::is_convertible_v<decltype(std::to_address(*begin)), T *>) { + std::for_each(begin, end, [&m, ¶ms...](auto && op) { + std::invoke(m, op, std::forward<Params>(params)...); + }); + return std::distance(begin, end); + } + else { + return std::count_if(begin, end, [&m, ¶ms...](auto && op) { + if (auto o = dynamic_cast<T *>(std::to_address(op))) { + std::invoke(m, o, std::forward<Params>(params)...); + return true; + } + return false; + }); + } } template<typename T = Object, typename... Params> auto applyOne_internal(const auto begin, const auto end, const auto & m, Params &&... params) const { - return std::find_if(begin, end, [&m, ¶ms...](auto && op) { - if (auto o = dynamic_cast<T *>(op.get())) { - return std::invoke(m, o, std::forward<Params>(params)...); - } - return false; - }); + if constexpr (std::is_convertible_v<decltype(std::to_address(*begin)), T *>) { + return std::find_if(begin, end, [&m, ¶ms...](auto && op) { + return std::invoke(m, op, std::forward<Params>(params)...); + }); + } + else { + return std::find_if(begin, end, [&m, ¶ms...](auto && op) { + if (auto o = dynamic_cast<T *>(std::to_address(op))) { + return std::invoke(m, o, std::forward<Params>(params)...); + } + return false; + }); + } } }; + +template<typename T, typename... Others> using SharedCollection = Collection<std::shared_ptr<T>, Others...>; +template<typename T, typename... Others> using UniqueCollection = Collection<std::unique_ptr<T>, Others...>; diff --git a/lib/enumDetails.h b/lib/enumDetails.h index dfae082..49906d4 100644 --- a/lib/enumDetails.h +++ b/lib/enumDetails.h @@ -9,11 +9,11 @@ /// EnumDetailsBase // Shared helpers struct EnumDetailsBase { - template<size_t len> + template<size_t Len> constexpr static auto strArr(auto input, auto start, auto end) { - std::array<char, len> out; + std::array<char, Len> out; input.copy(out.begin(), end - start, start); return out; } @@ -33,22 +33,22 @@ protected: return std::string_view {__PRETTY_FUNCTION__}; }; - constexpr static auto typeNameStart {typeraw().find(SEARCH_TYPE) + SEARCH_TYPE.length()}; - constexpr static auto typeNameEnd {typeraw().find_first_of("];", typeNameStart)}; - constexpr static auto typeNameLen {typeNameEnd - typeNameStart}; - constexpr static auto typeNameArr {strArr<typeNameLen>(typeraw(), typeNameStart, typeNameEnd)}; + constexpr static auto TYPE_NAME_START {typeraw().find(SEARCH_TYPE) + SEARCH_TYPE.length()}; + constexpr static auto TYPE_NAME_END {typeraw().find_first_of("];", TYPE_NAME_START)}; + constexpr static auto TYPE_NAME_LEN {TYPE_NAME_END - TYPE_NAME_START}; + constexpr static auto TYPE_NAME_ARR {strArr<TYPE_NAME_LEN>(typeraw(), TYPE_NAME_START, TYPE_NAME_END)}; public: - constexpr static std::string_view typeName {typeNameArr.data(), typeNameArr.size()}; + constexpr static std::string_view TYPE_NAME {TYPE_NAME_ARR.data(), TYPE_NAME_ARR.size()}; }; /// EnumValueDetails // Extracts the value name and constructs string_views of the parts -template<auto value> struct EnumValueDetails : public EnumTypeDetails<decltype(value)> { +template<auto Value> struct EnumValueDetails : public EnumTypeDetails<decltype(Value)> { #ifndef ENUM_PROBE private: #endif - using T = EnumTypeDetails<decltype(value)>; + using T = EnumTypeDetails<decltype(Value)>; constexpr static auto raw() @@ -56,26 +56,23 @@ private: return std::string_view {__PRETTY_FUNCTION__}; }; - constexpr static auto nameStart {raw().find_last_of(": ") + 1}; - constexpr static auto nameEnd {raw().find_first_of("];", nameStart)}; - constexpr static auto nameLen {nameEnd - nameStart}; - constexpr static auto nameArr {EnumValueDetails::template strArr<nameLen>(raw(), nameStart, nameEnd)}; + constexpr static auto NAME_START {raw().find_last_of(": ") + 1}; + constexpr static auto NAME_END {raw().find_first_of("];", NAME_START)}; + constexpr static auto NAME_LEN {NAME_END - NAME_START}; + constexpr static auto NAME_ARR {EnumValueDetails::template strArr<NAME_LEN>(raw(), NAME_START, NAME_END)}; public: - constexpr static std::string_view valueName {nameArr.data(), nameArr.size()}; - constexpr static auto valid {valueName.back() < '0' || valueName.back() > '9'}; -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wenum-constexpr-conversion" -#endif - constexpr static auto raw_value {value}; -#pragma GCC diagnostic pop + constexpr static std::string_view VALUE_NAME {NAME_ARR.data(), NAME_ARR.size()}; + constexpr static auto VALID {VALUE_NAME.back() < '0' || VALUE_NAME.back() > '9'}; + constexpr static auto RAW_VALUE {Value}; }; /// EnumValueCollection // Customisation point for specifying the range of underlying values your enum can have template<typename E> struct EnumValueCollection { - using Vs = std::make_integer_sequence<int, 256>; + using Underlying = std::underlying_type_t<E>; + static constexpr Underlying UPPER = std::numeric_limits<Underlying>::max(); + using Vs = std::make_integer_sequence<Underlying, UPPER>; }; /// EnumDetails @@ -84,45 +81,36 @@ template<typename E> struct EnumDetails { #ifndef ENUM_PROBE private: #endif - template<auto... n> + using Underlying = std::underlying_type_t<E>; + + template<auto... N> constexpr static auto - get_valids(std::integer_sequence<int, n...>) + getValids(std::integer_sequence<Underlying, N...>) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wenum-constexpr-conversion" -#endif - return std::array {EnumValueDetails<static_cast<E>(n)>::valid...}; -#pragma GCC diagnostic pop + return std::array {EnumValueDetails<static_cast<E>(N)>::VALID...}; } - template<auto... n> + template<auto... N> constexpr static auto - get_values(std::integer_sequence<int, n...>) + getValues(std::integer_sequence<Underlying, N...>) { -#pragma GCC diagnostic push -#ifdef __clang__ -# pragma GCC diagnostic ignored "-Wenum-constexpr-conversion" -#endif - return std::array {EnumValueDetails<static_cast<E>(n)>::raw_value...}; -#pragma GCC diagnostic pop + return std::array {EnumValueDetails<static_cast<E>(N)>::RAW_VALUE...}; } - template<auto... n> + template<auto... N> constexpr static auto - get_valueNames(std::integer_sequence<int, n...>) + getValueNames(std::integer_sequence<int, N...>) { - return std::array {EnumValueDetails<values[n]>::valueName...}; + return std::array {EnumValueDetails<VALUES[N]>::VALUE_NAME...}; } using EVC = EnumValueCollection<E>; - constexpr static auto valid_flags {get_valids(typename EVC::Vs {})}; - constexpr static auto valid_count {std::count_if(valid_flags.begin(), valid_flags.end(), std::identity {})}; + constexpr static auto VALID_FLAGS {getValids(typename EVC::Vs {})}; + constexpr static auto VALID_COUNT {std::count_if(VALID_FLAGS.begin(), VALID_FLAGS.end(), std::identity {})}; constexpr static auto - lookup(const auto key, const auto & search, - const auto & out) -> std::optional<typename std::decay_t<decltype(out)>::value_type> + lookup(const auto key, const auto & search, const auto & out) + -> std::optional<typename std::decay_t<decltype(out)>::value_type> { if (const auto itr = std::find(search.begin(), search.end(), key); itr != search.end()) { return out[static_cast<std::size_t>(std::distance(search.begin(), itr))]; @@ -131,32 +119,32 @@ private: } public: - constexpr static auto values {[]() { - constexpr auto values {get_values(typename EVC::Vs {})}; - static_assert(std::is_sorted(values.begin(), values.end()), "Candidate values must be sorted"); - std::array<E, valid_count> out; - std::copy_if(values.begin(), values.end(), out.begin(), [valid = valid_flags.begin()](auto) mutable { + constexpr static auto VALUES {[]() { + constexpr auto VALUES {getValues(typename EVC::Vs {})}; + static_assert(std::ranges::is_sorted(VALUES), "Candidate values must be sorted"); + std::array<E, VALID_COUNT> out; + std::copy_if(VALUES.begin(), VALUES.end(), out.begin(), [valid = VALID_FLAGS.begin()](auto) mutable { return *valid++; }); return out; }()}; - constexpr static auto names {get_valueNames(std::make_integer_sequence<int, valid_count> {})}; + constexpr static auto NAMES {getValueNames(std::make_integer_sequence<int, VALID_COUNT> {})}; constexpr static bool - is_valid(E value) noexcept + isValid(E value) noexcept { - return std::binary_search(values.begin(), values.end(), value); + return std::binary_search(VALUES.begin(), VALUES.end(), value); } constexpr static std::optional<E> parse(std::string_view name) noexcept { - return lookup(name, names, values); + return lookup(name, NAMES, VALUES); } constexpr static std::optional<std::string_view> - to_string(E value) noexcept + toString(E value) noexcept { - return lookup(value, values, names); + return lookup(value, VALUES, NAMES); } }; diff --git a/lib/glArrays.h b/lib/glArrays.h index 787ea17..842a593 100644 --- a/lib/glArrays.h +++ b/lib/glArrays.h @@ -6,6 +6,7 @@ #include <glad/gl.h> #include <special_members.h> +// NOLINTNEXTLINE(readability-identifier-naming) template<size_t N> class glArraysBase { static_assert(N > 0); @@ -15,20 +16,30 @@ public: CUSTOM_MOVE(glArraysBase); // NOLINTNEXTLINE(hicpp-explicit-conversions) - inline operator GLuint() const + requires(N == 1) { - static_assert(N == 1, "Implicit cast only if N == 1"); return ids.front(); } - inline auto + GLuint + operator*() const + requires(N == 1) + { + return ids.front(); + } + + const auto & operator[](size_t n) const { return ids[n]; } - constexpr static auto size {N}; + constexpr static auto + size() + { + return N; + } protected: glArraysBase() noexcept = default; @@ -49,6 +60,7 @@ glArraysBase<N>::operator=(glArraysBase<N> && src) noexcept return *this; } +// NOLINTNEXTLINE(readability-identifier-naming) template<size_t N, auto Gen, auto Del> class glArrays : public glArraysBase<N> { public: using glArraysBase<N>::glArraysBase; @@ -56,12 +68,12 @@ public: DEFAULT_MOVE_COPY(glArrays); - inline glArrays() noexcept + glArrays() noexcept { (*Gen)(N, this->ids.data()); } - inline ~glArrays() noexcept + ~glArrays() noexcept { if (this->ids.front()) { (*Del)(N, this->ids.data()); @@ -69,6 +81,7 @@ public: } }; +// NOLINTBEGIN(readability-identifier-naming) template<size_t N> using glVertexArrays = glArrays<N, &glGenVertexArrays, &glDeleteVertexArrays>; using glVertexArray = glVertexArrays<1>; template<size_t N> using glBuffers = glArrays<N, &glGenBuffers, &glDeleteBuffers>; @@ -79,3 +92,4 @@ template<size_t N> using glFrameBuffers = glArrays<N, &glGenFramebuffers, &glDel using glFrameBuffer = glFrameBuffers<1>; template<size_t N> using glRenderBuffers = glArrays<N, &glGenRenderbuffers, &glDeleteRenderbuffers>; using glRenderBuffer = glRenderBuffers<1>; +// NOLINTEND(readability-identifier-naming) diff --git a/lib/manyPtr.h b/lib/manyPtr.h new file mode 100644 index 0000000..9e08452 --- /dev/null +++ b/lib/manyPtr.h @@ -0,0 +1,86 @@ +#pragma once + +#include <memory> +#include <tuple> + +template<typename Primary, typename... Others> class ManyPtr : Primary { +public: + using element_type = typename Primary::element_type; + + template<typename... Params> ManyPtr(Params &&... params) : Primary {std::forward<Params>(params)...} + { + updatePtrs(); + } + + using Primary::operator->; + using Primary::operator*; + using Primary::operator bool; + using Primary::get; + + template<typename... Params> + void + reset(Params &&... params) + { + Primary::reset(std::forward<Params>(params)...); + updatePtrs(); + } + + template<typename Other> + [[nodiscard]] consteval static bool + couldBe() + { + return (std::is_convertible_v<Others *, Other *> || ...); + } + + template<typename Other> + requires(couldBe<Other>()) + [[nodiscard]] auto + getAs() const + { + return std::get<idx<Other>()>(others); + } + + template<typename Other> + requires(!couldBe<Other>() && requires { std::dynamic_pointer_cast<Other>(std::declval<Primary>()); }) + [[nodiscard]] auto + dynamicCast() const + { + return std::dynamic_pointer_cast<Other>(*this); + } + + template<typename Other> + requires(!couldBe<Other>() && !requires { std::dynamic_pointer_cast<Other>(std::declval<Primary>()); }) + [[nodiscard]] auto + dynamicCast() const + { + return dynamic_cast<Other *>(get()); + } + +private: + using OtherPtrs = std::tuple<Others *...>; + + template<typename Other> + requires(couldBe<Other>()) + [[nodiscard]] consteval static bool + idx() + { + size_t typeIdx = 0; + return ((typeIdx++ && std::is_convertible_v<Others *, Other *>) || ...); + } + + void + updatePtrs() + { + if (*this) { + others = {dynamic_cast<Others *>(get())...}; + } + else { + others = {}; + } + } + + OtherPtrs others; +}; + +template<typename Primary, typename... Others> using ManySharedPtr = ManyPtr<std::shared_ptr<Primary>, Others...>; +template<typename Primary, typename... Others> using ManyUniquePtr = ManyPtr<std::unique_ptr<Primary>, Others...>; diff --git a/lib/maths.cpp b/lib/maths.cpp index 3a9bf9b..12e0681 100644 --- a/lib/maths.cpp +++ b/lib/maths.cpp @@ -32,13 +32,13 @@ static_assert(pow(3, 2) == 9); static_assert(pow(pi, 3) == 31.006278991699219F); float -operator"" _mph(const long double v) +operator""_mph(const long double v) { return static_cast<float>(mph_to_ms(v)); } float -operator"" _kph(const long double v) +operator""_kph(const long double v) { return static_cast<float>(kph_to_ms(v)); } diff --git a/lib/maths.h b/lib/maths.h index 0afce98..43d6dcd 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -504,11 +504,11 @@ kph_to_ms(T v) } // ... literals are handy for now, probably go away when we load stuff externally -float operator"" _mph(const long double v); -float operator"" _kph(const long double v); +float operator""_mph(const long double v); +float operator""_kph(const long double v); constexpr float -operator"" _degrees(long double degrees) +operator""_degrees(long double degrees) { return static_cast<float>(degrees) * degreesToRads; } diff --git a/lib/persistence.h b/lib/persistence.h index e385b20..75bcea6 100644 --- a/lib/persistence.h +++ b/lib/persistence.h @@ -1,5 +1,6 @@ #pragma once +#include "manyPtr.h" #include <charconv> #include <format> #include <functional> @@ -200,7 +201,7 @@ namespace Persistence { } [[nodiscard]] virtual NameActionSelection setName(const std::string_view key, SelectionFactory &&) = 0; - virtual void selHandler() {}; + virtual void selHandler() { }; virtual void setType(const std::string_view, const Persistable *) = 0; SelectionPtr sel {}; @@ -53,34 +53,55 @@ public: } } - bool - intersectTriangle(const PositionType t0, const PositionType t1, const PositionType t2, BaryPosition & bary, - RelativeDistance & distance) const + struct IntersectTriangleResult { + BaryPosition bary; + RelativeDistance distance; + }; + + std::optional<IntersectTriangleResult> + intersectTriangle(const PositionType t0, const PositionType t1, const PositionType t2) const { + IntersectTriangleResult out; if constexpr (std::is_floating_point_v<typename PositionType::value_type>) { - return glm::intersectRayTriangle(start, direction, t0, t1, t2, bary, distance) && distance >= 0.F; + if (glm::intersectRayTriangle(start, direction, t0, t1, t2, out.bary, out.distance) + && out.distance >= 0.F) { + return out; + } } else { const RelativePosition3D t0r = t0 - start, t1r = t1 - start, t2r = t2 - start; - return glm::intersectRayTriangle({}, direction, t0r, t1r, t2r, bary, distance) && distance >= 0.F; + if (glm::intersectRayTriangle({}, direction, t0r, t1r, t2r, out.bary, out.distance) + && out.distance >= 0.F) { + return out; + } } + return std::nullopt; } - bool - intersectSphere(const PositionType centre, const PositionType::value_type size, PositionType & position, - Normal3D & normal) const + struct IntersectSphereResult { + PositionType position; + Normal3D normal; + }; + + std::optional<IntersectSphereResult> + intersectSphere(const PositionType centre, const PositionType::value_type size) const { + IntersectSphereResult out; if constexpr (std::is_floating_point_v<typename PositionType::value_type>) { - return glm::intersectRaySphere(start, direction, centre, size, position, normal); + if (glm::intersectRaySphere(start, direction, centre, size, out.position, out.normal)) { + return out; + } } else { const RelativePosition3D cr = centre - start; RelativePosition3D positionF {}; - const auto r = glm::intersectRaySphere( - {}, direction, cr, static_cast<RelativeDistance>(size), positionF, normal); - position = GlobalPosition3D(positionF) + start; - return r; + if (glm::intersectRaySphere( + {}, direction, cr, static_cast<RelativeDistance>(size), positionF, out.normal)) { + out.position = GlobalPosition3D(positionF) + start; + return out; + } } + return std::nullopt; } }; diff --git a/lib/stream_support.h b/lib/stream_support.h index 5f276fd..7f1df96 100644 --- a/lib/stream_support.h +++ b/lib/stream_support.h @@ -81,7 +81,7 @@ namespace std { inline std::ostream & operator<<(std::ostream & s, const E & e) { - return s << EnumTypeDetails<E>::typeName << "::" << EnumDetails<E>::to_string(e).value(); + return s << EnumTypeDetails<E>::TYPE_NAME << "::" << EnumDetails<E>::toString(e).value(); } template<typename T> |