summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/collections.h6
-rw-r--r--lib/embed-glsl.cpp.m46
-rw-r--r--lib/enumDetails.h102
-rw-r--r--lib/glAllocator.cpp28
-rw-r--r--lib/glAllocator.h163
-rw-r--r--lib/glArrays.cpp21
-rw-r--r--lib/glArrays.h135
-rw-r--r--lib/glContainer.h497
-rw-r--r--lib/glMappedBufferSpan.h51
-rw-r--r--lib/glMappedBufferWriter.cpp4
-rw-r--r--lib/glMappedBufferWriter.h78
-rw-r--r--lib/gl_traits.h110
-rw-r--r--lib/jsonParse.ll9
-rw-r--r--lib/maths.cpp4
-rw-r--r--lib/maths.h18
-rw-r--r--lib/ray.h47
-rw-r--r--lib/stream_support.h2
17 files changed, 492 insertions, 789 deletions
diff --git a/lib/collections.h b/lib/collections.h
index e182af5..3c80125 100644
--- a/lib/collections.h
+++ b/lib/collections.h
@@ -10,10 +10,8 @@
#include <vector>
template<typename T, typename E>
-concept SequentialCollection = requires(T c) {
- { c.size() } -> std::integral;
- { c.data() } -> std::same_as<const E *>;
-};
+concept SequentialCollection
+ = std::ranges::contiguous_range<T> && std::is_same_v<const E, const typename T::value_type>;
template<typename T>
concept IterableCollection = std::is_same_v<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>;
diff --git a/lib/embed-glsl.cpp.m4 b/lib/embed-glsl.cpp.m4
index ecae004..e8d285c 100644
--- a/lib/embed-glsl.cpp.m4
+++ b/lib/embed-glsl.cpp.m4
@@ -1,9 +1,9 @@
changecom() dnl
// NAME
#include "gfx/gl/shader.h"
-#include "substr(TYPE,1)-NAME.h"
+#include "NAME-substr(TYPE,1).h"
#include <glad/gl.h>
constexpr Shader NAME`_'substr(TYPE,1) {
- R"GLSL-EMBED(// OUTPUT
- include(SOURCE))GLSL-EMBED", GLTYPE };
+ R"GLSL-EMBED(// SOURCE
+include(SOURCE))GLSL-EMBED", GLTYPE };
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/glAllocator.cpp b/lib/glAllocator.cpp
new file mode 100644
index 0000000..633f7ab
--- /dev/null
+++ b/lib/glAllocator.cpp
@@ -0,0 +1,28 @@
+#include "glAllocator.h"
+
+namespace Detail {
+ std::pair<void *, GLuint>
+ allocateBuffer(size_t count, size_t objSize)
+ {
+ constexpr static GLbitfield MAPPING_FLAGS
+ = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
+ constexpr static GLbitfield STORAGE_FLAGS = GL_DYNAMIC_STORAGE_BIT | MAPPING_FLAGS;
+ GLuint name = 0;
+ glCreateBuffers(1, &name);
+ const auto size = static_cast<GLsizeiptr>(count * objSize);
+ glNamedBufferStorage(name, size, nullptr, STORAGE_FLAGS);
+ const auto data = (glMapNamedBufferRange(name, 0, size, MAPPING_FLAGS));
+ if (!data) {
+ glDeleteBuffers(1, &name);
+ throw std::bad_alloc();
+ }
+ return {data, name};
+ }
+
+ void
+ deallocateBuffer(GLuint name)
+ {
+ glUnmapNamedBuffer(name);
+ glDeleteBuffers(1, &name);
+ }
+}
diff --git a/lib/glAllocator.h b/lib/glAllocator.h
new file mode 100644
index 0000000..02690c3
--- /dev/null
+++ b/lib/glAllocator.h
@@ -0,0 +1,163 @@
+#include "special_members.h"
+#include <glad/gl.h>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+namespace Detail {
+ template<typename T> class glPointer {
+ public:
+ constexpr glPointer(const glPointer<std::remove_const_t<T>> & other)
+ requires(std::is_const_v<T>)
+ : ptr {other.get()}, name {other.bufferName()}
+ {
+ }
+
+ DEFAULT_MOVE_COPY(glPointer);
+
+ constexpr glPointer() : ptr {nullptr}, name {0} { }
+
+ constexpr glPointer(T * ptr, GLuint name) : ptr {ptr}, name {name} { }
+
+ auto operator<=>(const glPointer &) const noexcept = default;
+
+ operator T *() const noexcept
+ {
+ return ptr;
+ }
+
+ operator bool() const noexcept
+ {
+ return ptr;
+ }
+
+ std::ptrdiff_t
+ operator-(const glPointer & other) const noexcept
+ {
+ return ptr - other.ptr;
+ }
+
+ T *
+ get() const noexcept
+ {
+ return ptr;
+ }
+
+ T &
+ operator*() const noexcept
+ {
+ return *ptr;
+ }
+
+ [[nodiscard]]
+ T &
+ operator[](std::unsigned_integral auto index) const noexcept
+ {
+ return ptr[index];
+ }
+
+ T *
+ operator->() const noexcept
+ {
+ return ptr;
+ }
+
+ glPointer<T> &
+ operator++() noexcept
+ {
+ ++ptr;
+ return *this;
+ }
+
+ glPointer<T> &
+ operator--() noexcept
+ {
+ --ptr;
+ return *this;
+ }
+
+ [[nodiscard]] glPointer<T>
+ operator+(std::integral auto offset) const noexcept
+ {
+ return {ptr + offset, name};
+ }
+
+ [[nodiscard]] glPointer<T>
+ operator-(std::integral auto offset) const noexcept
+ {
+ return {ptr - offset, name};
+ }
+
+ [[nodiscard]] glPointer<T>
+ operator+=(std::integral auto offset) const noexcept
+ {
+ return {ptr += offset, name};
+ }
+
+ [[nodiscard]] glPointer<T>
+ operator-=(std::integral auto offset) const noexcept
+ {
+ return {ptr -= offset, name};
+ }
+
+ [[nodiscard]] GLuint
+ bufferName() const noexcept
+ {
+ return name;
+ }
+
+ private:
+ T * ptr;
+ GLuint name;
+ };
+
+ std::pair<void *, GLuint> allocateBuffer(size_t count, size_t objSize);
+ void deallocateBuffer(GLuint name);
+
+ template<typename T> class glAllocator {
+ public:
+ // NOLINTBEGIN(readability-identifier-naming) - STL like
+ using pointer = glPointer<T>;
+ using const_pointer = glPointer<const T>;
+ using value_type = T;
+
+ // NOLINTEND(readability-identifier-naming)
+
+ pointer
+ allocate(size_t count)
+ {
+ auto allocated = allocateBuffer(count, sizeof(T));
+ return {static_cast<T *>(allocated.first), allocated.second};
+ }
+
+#if (__cpp_lib_allocate_at_least >= 202302L)
+ std::allocation_result<pointer>
+ allocate_at_least(size_t count)
+ {
+ count = std::min(count, 32ZU);
+ return {allocate(count), count};
+ }
+#endif
+
+ void
+ deallocate(pointer ptr, size_t)
+ {
+ deallocateBuffer(ptr.bufferName());
+ }
+
+ using is_always_equal = std::true_type;
+ };
+}
+
+template<typename T> struct std::iterator_traits<Detail::glPointer<T>> {
+ using iterator_category = std::random_access_iterator_tag;
+ using iterator_concept = std::contiguous_iterator_tag;
+ using value_type = T;
+ using difference_type = std::ptrdiff_t;
+ using reference = T &;
+ using pointer = T *;
+};
+
+template<typename T>
+// NOLINTNEXTLINE(readability-identifier-naming) - OpenGL like
+using glVector = std::vector<T, typename std::allocator_traits<Detail::glAllocator<T>>::allocator_type>;
diff --git a/lib/glArrays.cpp b/lib/glArrays.cpp
deleted file mode 100644
index 7c5b2ea..0000000
--- a/lib/glArrays.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "glArrays.h"
-#include <type_traits>
-
-// Base
-static_assert(!std::is_default_constructible_v<glArraysBase<1>>);
-static_assert(!std::is_copy_constructible_v<glArraysBase<1>>);
-static_assert(!std::is_copy_assignable_v<glArraysBase<1>>);
-static_assert(std::is_nothrow_move_constructible_v<glArraysBase<1>>);
-static_assert(std::is_nothrow_move_assignable_v<glArraysBase<1>>);
-
-// Specialisations (glBuffer is an example of the typedef)
-static_assert(std::is_nothrow_default_constructible_v<glBuffer>);
-static_assert(!std::is_trivially_default_constructible_v<glBuffer>);
-static_assert(std::is_nothrow_destructible_v<glBuffer>);
-static_assert(!std::is_trivially_destructible_v<glBuffer>);
-static_assert(std::is_default_constructible_v<glBuffer>);
-static_assert(!std::is_copy_constructible_v<glBuffer>);
-static_assert(!std::is_copy_assignable_v<glBuffer>);
-static_assert(std::is_nothrow_move_constructible_v<glBuffer>);
-static_assert(std::is_nothrow_move_assignable_v<glBuffer>);
-static_assert(sizeof(glBuffer) == sizeof(GLuint));
diff --git a/lib/glArrays.h b/lib/glArrays.h
index 787ea17..7f5a10b 100644
--- a/lib/glArrays.h
+++ b/lib/glArrays.h
@@ -5,77 +5,108 @@
#include <cstddef>
#include <glad/gl.h>
#include <special_members.h>
+#include <utility>
-template<size_t N> class glArraysBase {
- static_assert(N > 0);
+namespace Detail {
+ class glNamed;
-public:
- ~glArraysBase() = default;
- NO_COPY(glArraysBase);
- CUSTOM_MOVE(glArraysBase);
+ template<typename Named>
+ concept IsglNamed = sizeof(Named) == sizeof(GLuint) && std::is_base_of_v<Detail::glNamed, Named>;
+}
+
+template<Detail::IsglNamed, size_t, auto, auto> struct glManagedArray;
+
+namespace Detail {
+ class glNamed {
+ public:
+ glNamed() = default;
+ ~glNamed() = default;
+ DEFAULT_MOVE_NO_COPY(glNamed);
+
+ GLuint
+ operator*() const noexcept
+ {
+ return name;
+ }
+
+ // NOLINTNEXTLINE(hicpp-explicit-conversions)
+ operator GLuint() const noexcept
+ {
+ return name;
+ }
- // NOLINTNEXTLINE(hicpp-explicit-conversions)
- inline
- operator GLuint() const
+ protected:
+ GLuint name {};
+ template<Detail::IsglNamed, size_t, auto, auto> friend struct ::glManagedArray;
+ };
+}
+
+template<Detail::IsglNamed Named, auto Gen, auto Del> struct glManagedSingle : public Named {
+ glManagedSingle() noexcept
{
- static_assert(N == 1, "Implicit cast only if N == 1");
- return ids.front();
+ (*Gen)(1, &this->name);
}
- inline auto
- operator[](size_t n) const
+ glManagedSingle(glManagedSingle && src) noexcept
{
- return ids[n];
+ this->name = std::exchange(src.name, 0);
}
- constexpr static auto size {N};
+ ~glManagedSingle() noexcept
+ {
+ if (this->name) {
+ (*Del)(1, &this->name);
+ }
+ }
-protected:
- glArraysBase() noexcept = default;
- std::array<GLuint, N> ids {};
-};
+ NO_COPY(glManagedSingle);
-template<size_t N> inline glArraysBase<N>::glArraysBase(glArraysBase<N> && src) noexcept : ids {src.ids}
-{
- std::fill(src.ids.begin(), src.ids.end(), 0);
-}
+ glManagedSingle &
+ operator=(glManagedSingle && src) noexcept
+ {
+ if (this->name) {
+ (*Del)(1, &this->name);
+ }
+ this->name = std::exchange(src.name, 0);
+ return *this;
+ }
+};
-template<size_t N>
-inline glArraysBase<N> &
-glArraysBase<N>::operator=(glArraysBase<N> && src) noexcept
-{
- ids = src.ids;
- std::fill(src.ids.begin(), src.ids.end(), 0);
- return *this;
-}
+template<Detail::IsglNamed Named, size_t N, auto Gen, auto Del> struct glManagedArray : public std::array<Named, N> {
+ using Arr = std::array<Named, N>;
-template<size_t N, auto Gen, auto Del> class glArrays : public glArraysBase<N> {
-public:
- using glArraysBase<N>::glArraysBase;
- using glArraysBase<N>::operator=;
+ glManagedArray() noexcept
+ {
+ (*Gen)(N, &Arr::front().name);
+ }
- DEFAULT_MOVE_COPY(glArrays);
+ glManagedArray(glManagedArray && src) noexcept
+ {
+ Arr::operator=(std::exchange(static_cast<Arr &>(src), {}));
+ }
- inline glArrays() noexcept
+ ~glManagedArray() noexcept
{
- (*Gen)(N, this->ids.data());
+ if (Arr::front().name) {
+ (*Del)(N, &Arr::front().name);
+ }
}
- inline ~glArrays() noexcept
+ NO_COPY(glManagedArray);
+
+ glManagedArray &
+ operator=(glManagedArray && src) noexcept
{
- if (this->ids.front()) {
- (*Del)(N, this->ids.data());
+ if (Arr::front().name) {
+ (*Del)(N, &Arr::front().name);
}
+ Arr::operator=(std::exchange(static_cast<Arr &>(src), {}));
+ return *this;
}
-};
-template<size_t N> using glVertexArrays = glArrays<N, &glGenVertexArrays, &glDeleteVertexArrays>;
-using glVertexArray = glVertexArrays<1>;
-template<size_t N> using glBuffers = glArrays<N, &glGenBuffers, &glDeleteBuffers>;
-using glBuffer = glBuffers<1>;
-template<size_t N> using glTextures = glArrays<N, &glGenTextures, &glDeleteTextures>;
-using glTexture = glTextures<1>;
-template<size_t N> using glFrameBuffers = glArrays<N, &glGenFramebuffers, &glDeleteFramebuffers>;
-using glFrameBuffer = glFrameBuffers<1>;
-template<size_t N> using glRenderBuffers = glArrays<N, &glGenRenderbuffers, &glDeleteRenderbuffers>;
-using glRenderBuffer = glRenderBuffers<1>;
+ [[nodiscard]] static constexpr size_t
+ size() noexcept
+ {
+ return N;
+ }
+};
diff --git a/lib/glContainer.h b/lib/glContainer.h
deleted file mode 100644
index 5cbb038..0000000
--- a/lib/glContainer.h
+++ /dev/null
@@ -1,497 +0,0 @@
-#pragma once
-
-#include "glArrays.h"
-#include <cassert>
-#include <span>
-#include <stdexcept>
-#include <utility>
-#include <vector>
-
-static_assert(GL_READ_ONLY < GL_READ_WRITE);
-static_assert(GL_WRITE_ONLY < GL_READ_WRITE);
-
-template<typename T> class glContainer {
-public:
- using span = std::span<T>;
- using const_span = std::span<const T>;
- using value_type = T;
- using reference_type = T &;
- using const_reference_type = const T &;
- using pointer_type = T *;
- using const_pointer_type = const T *;
- using size_type = std::size_t;
- using iterator = span::iterator;
- using const_iterator = const_span::iterator;
- using reverse_iterator = span::reverse_iterator;
- using const_reverse_iterator = const_span::reverse_iterator;
- static constexpr bool is_trivial_dest = std::is_trivially_destructible_v<T>;
-
- explicit glContainer(GLenum target = GL_ARRAY_BUFFER) : target_ {target}
- {
- allocBuffer(1);
- }
-
- ~glContainer()
- requires(is_trivial_dest)
- = default;
-
- ~glContainer()
- requires(!is_trivial_dest)
- {
- clear();
- }
-
- template<template<typename, typename...> typename C>
- explicit glContainer(const C<T> & src, GLenum target = GL_ARRAY_BUFFER) : target_ {target}
- {
- reserve(src.size());
- std::copy(src.begin(), src.end(), std::back_inserter(*this));
- }
-
- DEFAULT_MOVE_NO_COPY(glContainer);
-
- [[nodiscard]] iterator
- begin()
- {
- map(GL_READ_WRITE);
- return mkspan().begin();
- }
-
- [[nodiscard]] iterator
- end()
- {
- map(GL_READ_WRITE);
- return mkspan().end();
- }
-
- [[nodiscard]] const_iterator
- begin() const
- {
- map(GL_READ_ONLY);
- return mkcspan().begin();
- }
-
- [[nodiscard]] const_iterator
- end() const
- {
- map(GL_READ_ONLY);
- return mkcspan().end();
- }
-
- [[nodiscard]] const_iterator
- cbegin() const
- {
- map(GL_READ_ONLY);
- return mkcspan().begin();
- }
-
- [[nodiscard]] const_iterator
- cend() const
- {
- map(GL_READ_ONLY);
- return mkcspan().end();
- }
-
- [[nodiscard]] reverse_iterator
- rbegin()
- {
- map(GL_READ_WRITE);
- return mkspan().rbegin();
- }
-
- [[nodiscard]] reverse_iterator
- rend()
- {
- map(GL_READ_WRITE);
- return mkspan().rend();
- }
-
- [[nodiscard]] const_reverse_iterator
- rbegin() const
- {
- map(GL_READ_ONLY);
- return mkcspan().rbegin();
- }
-
- [[nodiscard]] const_reverse_iterator
- rend() const
- {
- map(GL_READ_ONLY);
- return mkcspan().rend();
- }
-
- [[nodiscard]] const_reverse_iterator
- crbegin() const
- {
- map(GL_READ_ONLY);
- return mkcspan().rbegin();
- }
-
- [[nodiscard]] const_reverse_iterator
- crend() const
- {
- map(GL_READ_ONLY);
- return mkcspan().rend();
- }
-
- [[nodiscard]] const auto &
- bufferName() const
- {
- return buffer_;
- }
-
- [[nodiscard]] size_type
- size() const
- {
- return size_;
- }
-
- void
- at(size_type pos, const T & value)
- {
- if (pos >= size()) {
- throw std::out_of_range {__FUNCTION__};
- }
- if (data_) {
- mkspan()[pos] = value;
- }
- else {
- glBindBuffer(target_, buffer_);
- glBufferSubData(target_, static_cast<GLintptr>(pos * sizeof(T)), sizeof(value), &value);
- glBindBuffer(target_, 0);
- }
- }
-
- [[nodiscard]] reference_type
- at(size_type pos)
- {
- if (pos >= size()) {
- throw std::out_of_range {__FUNCTION__};
- }
- map(GL_READ_WRITE);
- return mkspan()[pos];
- }
-
- [[nodiscard]] const_reference_type
- at(size_type pos) const
- {
- if (pos >= size()) {
- throw std::out_of_range {__FUNCTION__};
- }
- map(GL_READ_ONLY);
- return mkcspan()[pos];
- }
-
- [[nodiscard]] reference_type
- operator[](size_type pos)
- {
- map(GL_READ_WRITE);
- return mkspan()[pos];
- }
-
- [[nodiscard]] const_reference_type
- operator[](size_type pos) const
- {
- map(GL_READ_ONLY);
- return mkcspan()[pos];
- }
-
- [[nodiscard]] pointer_type
- data()
- {
- map(GL_READ_WRITE);
- return data_;
- }
-
- [[nodiscard]] const_pointer_type
- data() const
- {
- map(GL_READ_ONLY);
- return data_;
- }
-
- [[nodiscard]] reference_type
- front()
- {
- map(GL_READ_WRITE);
- return mkspan().front();
- }
-
- [[nodiscard]] reference_type
- back()
- {
- map(GL_READ_WRITE);
- return mkspan().back();
- }
-
- [[nodiscard]] const_reference_type
- front() const
- {
- map(GL_READ_ONLY);
- return mkcspan().front();
- }
-
- [[nodiscard]] const_reference_type
- back() const
- {
- map(GL_READ_ONLY);
- return mkcspan().back();
- }
-
- [[nodiscard]] bool
- empty() const
- {
- return !size();
- }
-
- [[nodiscard]] size_type
- capacity() const
- {
- return capacity_;
- }
-
- void
- unmap() const
- {
- if (data_) {
- glBindBuffer(target_, buffer_);
- glUnmapBuffer(target_);
- glBindBuffer(target_, 0);
- data_ = {};
- access_ = {};
- }
- }
-
- void
- reserve(size_type newCapacity)
- {
- if (newCapacity <= capacity_) {
- return;
- }
- newCapacity = std::max(newCapacity, capacity_ * 2);
-
- std::vector<T> existing;
- existing.reserve(size_);
- std::move(begin(), end(), std::back_inserter(existing));
- allocBuffer(newCapacity);
- std::move(existing.begin(), existing.end(), begin());
- }
-
- void
- resize(size_type newSize)
- requires std::is_default_constructible_v<T>
- {
- if (newSize == size_) {
- return;
- }
-
- if (const auto maintain = std::min(newSize, size_)) {
- std::vector<T> existing;
- const auto maintaind = static_cast<typename decltype(existing)::difference_type>(maintain);
- existing.reserve(maintain);
- std::move(begin(), end(), std::back_inserter(existing));
- allocBuffer(newSize);
- mapForAdd();
- std::move(existing.begin(), existing.begin() + maintaind, begin());
- }
- else {
- allocBuffer(newSize);
- mapForAdd();
- }
- if (newSize > size_) {
- for (auto & uninitialised : mkspan().subspan(size_, newSize - size_)) {
- new (&uninitialised) T {};
- }
- }
- setSize(newSize);
- }
-
- void
- shrink_to_fit()
- {
- if (capacity_ <= size_) {
- return;
- }
-
- std::vector<T> existing;
- existing.reserve(size_);
- map(is_trivial_dest ? GL_READ_ONLY : GL_READ_WRITE);
- std::move(begin(), end(), std::back_inserter(existing));
- allocBuffer(size_);
- map(GL_READ_WRITE);
- std::move(existing.begin(), existing.end(), begin());
- }
-
- void
- clear() noexcept(is_trivial_dest)
- {
- if constexpr (!is_trivial_dest) {
- map(GL_READ_WRITE);
- std::for_each(begin(), end(), [](auto && v) {
- v.~T();
- });
- }
- setSize(0);
- }
-
- template<typename... P>
- reference_type
- emplace_back(P &&... ps)
- requires std::is_constructible_v<T, P...>
- {
- auto newSize = size_ + 1;
- reserve(newSize);
- mapForAdd();
- new (&*end()) T {std::forward<P>(ps)...};
- setSize(newSize);
- return back();
- }
-
- template<typename... P>
- iterator
- emplace(iterator pos, P &&... ps)
- requires std::is_nothrow_constructible_v<T, P...>
- {
- auto newSize = size_ + 1;
- const auto idx = pos - begin();
- reserve(newSize);
- mapForAdd();
- pos = begin() + idx;
- std::move_backward(pos, end(), end() + 1);
- pos->~T();
- new (&*pos) T {std::forward<P>(ps)...};
- setSize(newSize);
- return pos;
- }
-
- reference_type
- push_back(T p)
- requires std::is_move_constructible_v<T>
- {
- auto newSize = size_ + 1;
- reserve(newSize);
- mapForAdd();
- new (&*end()) T {std::move(p)};
- setSize(newSize);
- return back();
- }
-
- iterator
- insert(iterator pos, T p)
- requires std::is_nothrow_move_constructible_v<T>
- {
- auto newSize = size_ + 1;
- const auto idx = pos - begin();
- reserve(newSize);
- mapForAdd();
- pos = begin() + idx;
- std::move_backward(pos, end(), end() + 1);
- pos->~T();
- new (&*pos) T {std::move(p)};
- setSize(newSize);
- return pos;
- }
-
- void
- pop_back()
- {
- if constexpr (!is_trivial_dest) {
- map(GL_READ_WRITE);
- back().~T();
- }
- --size_;
- }
-
- void
- erase(iterator pos)
- {
- erase(pos, pos + 1);
- }
-
- void
- erase(iterator pos, iterator to)
- {
- const auto eraseSize = to - pos;
- map(GL_READ_WRITE);
- std::move(to, end(), pos);
- if constexpr (!is_trivial_dest) {
- std::for_each(end() - eraseSize, end(), [](auto && v) {
- v.~T();
- });
- }
- setSize(size_ - static_cast<size_type>(eraseSize));
- }
-
-protected:
- void
- setSize(size_type s)
- {
- size_ = s;
- }
-
- void
- allocBuffer(size_type newCapacity)
- {
- if (newCapacity == 0) {
- return allocBuffer(1);
- }
- glBindBuffer(target_, buffer_);
- glBufferData(target_, static_cast<GLsizeiptr>(sizeof(T) * newCapacity), nullptr, GL_DYNAMIC_DRAW);
- glBindBuffer(target_, 0);
- capacity_ = newCapacity;
- data_ = {};
- access_ = {};
- }
-
- void
- map(GLenum access) const
- {
- if (size_ > 0) {
- mapMode(access);
- }
- }
-
- void
- mapForAdd() const
- {
- if (!data_) {
- mapMode(GL_READ_WRITE);
- }
- }
-
- void
- mapMode(GLenum access) const
- {
- if (data_ && access_ < access) {
- unmap();
- }
- if (!data_) {
- glBindBuffer(target_, buffer_);
- data_ = static_cast<T *>(glMapBuffer(target_, access));
- glBindBuffer(target_, 0);
- assert(data_);
- access_ = access;
- }
- }
-
- span
- mkspan() const
- {
- assert(!size_ || data_);
- return span {data_, size_};
- }
-
- const_span
- mkcspan() const
- {
- assert(!size_ || data_);
- return const_span {data_, size_};
- }
-
- glBuffer buffer_;
- GLenum target_;
- std::size_t capacity_ {};
- std::size_t size_ {};
- mutable T * data_;
- mutable GLenum access_ {};
-};
diff --git a/lib/glMappedBufferSpan.h b/lib/glMappedBufferSpan.h
new file mode 100644
index 0000000..d30c911
--- /dev/null
+++ b/lib/glMappedBufferSpan.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "special_members.h"
+#include <cstddef>
+#include <glad/gl.h>
+#include <span>
+#include <utility>
+
+template<typename T> class glMappedBufferSpan : public std::span<T> {
+public:
+ glMappedBufferSpan(GLuint buffer, size_t count, GLenum access, bool reinit) :
+ std::span<T> {[&]() {
+ if (reinit) {
+ glNamedBufferData(
+ buffer, static_cast<GLsizeiptr>(sizeof(T) * count), nullptr, GL_DYNAMIC_DRAW);
+ }
+ return static_cast<T *>(glMapNamedBuffer(buffer, access));
+ }(),
+ count},
+ buffer {buffer}
+ {
+ }
+
+ ~glMappedBufferSpan()
+ {
+ if (buffer) {
+ glUnmapNamedBuffer(buffer);
+ }
+ }
+
+ glMappedBufferSpan(glMappedBufferSpan && other) noexcept :
+ std::span<T> {other}, buffer {std::exchange(other.buffer, 0)}
+ {
+ }
+
+ glMappedBufferSpan &
+ operator=(glMappedBufferSpan && other) noexcept
+ {
+ std::span<T>::span = other;
+ if (buffer) {
+ glUnmapBuffer(buffer);
+ }
+ buffer = std::exchange(other.buffer, 0);
+ return *this;
+ }
+
+ NO_COPY(glMappedBufferSpan);
+
+private:
+ GLuint buffer;
+};
diff --git a/lib/glMappedBufferWriter.cpp b/lib/glMappedBufferWriter.cpp
deleted file mode 100644
index cc3c413..0000000
--- a/lib/glMappedBufferWriter.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "glMappedBufferWriter.h"
-#include <iterator>
-
-static_assert(std::weakly_incrementable<glMappedBufferWriter<int>>);
diff --git a/lib/glMappedBufferWriter.h b/lib/glMappedBufferWriter.h
deleted file mode 100644
index f97d7e1..0000000
--- a/lib/glMappedBufferWriter.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#pragma once
-
-#include "special_members.h"
-#include <cstddef>
-#include <glad/gl.h>
-#include <utility>
-
-template<typename T> class glMappedBufferWriter {
-public:
- using difference_type = std::ptrdiff_t;
-
- glMappedBufferWriter(GLenum target, GLuint buffer, size_t count, GLenum usage = GL_STATIC_DRAW) :
- target {target}, data {[&]() {
- glBindBuffer(target, buffer);
- glBufferData(target, static_cast<GLsizeiptr>(sizeof(T) * count), nullptr, usage);
- return static_cast<T *>(glMapBuffer(target, GL_WRITE_ONLY));
- }()}
- {
- }
-
- ~glMappedBufferWriter()
- {
- if (target) {
- glUnmapBuffer(target);
- }
- }
-
- glMappedBufferWriter(glMappedBufferWriter && other) noexcept :
- target {std::exchange(other.target, 0)}, data {std::exchange(other.data, nullptr)}
- {
- }
-
- glMappedBufferWriter &
- operator=(glMappedBufferWriter && other) noexcept
- {
- if (target) {
- glUnmapBuffer(target);
- }
- target = std::exchange(other.target, 0);
- data = std::exchange(other.data, nullptr);
- return *this;
- }
-
- NO_COPY(glMappedBufferWriter);
-
- glMappedBufferWriter &
- operator++()
- {
- data++;
- return *this;
- }
-
- glMappedBufferWriter &
- operator++(int)
- {
- glMappedBufferWriter rtn {data};
- data++;
- return rtn;
- }
-
- T &
- operator*()
- {
- return *data;
- }
-
- T *
- operator->() const
- {
- return data;
- }
-
-private:
- explicit glMappedBufferWriter(T * data) : target {0}, data {data} { }
-
- GLenum target;
- T * data;
-};
diff --git a/lib/gl_traits.h b/lib/gl_traits.h
index b3c6909..eff9304 100644
--- a/lib/gl_traits.h
+++ b/lib/gl_traits.h
@@ -14,27 +14,33 @@ struct gl_traits_base {
};
struct gl_traits_float : public gl_traits_base {
- static constexpr auto vertexAttribFunc {
- [](GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) -> GLuint {
- glVertexAttribPointer(index, size, type, GL_FALSE, stride, pointer);
- return 1;
- }};
+ template<GLenum type, GLint size>
+ static GLuint
+ vertexAttribFormatFunc(GLuint vao, GLuint index, GLuint offset)
+ {
+ glVertexArrayAttribFormat(vao, index, size, type, GL_FALSE, offset);
+ return 1;
+ }
};
struct gl_traits_longfloat : public gl_traits_base {
- static constexpr auto vertexAttribFunc {
- [](GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) -> GLuint {
- glVertexAttribLPointer(index, size, type, stride, pointer);
- return 1;
- }};
+ template<GLenum type, GLint size>
+ static GLuint
+ vertexAttribFormatFunc(GLuint vao, GLuint index, GLuint offset)
+ {
+ glVertexArrayAttribLFormat(vao, index, size, type, offset);
+ return 1;
+ }
};
struct gl_traits_integer : public gl_traits_base {
- static constexpr auto vertexAttribFunc {
- [](GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) -> GLuint {
- glVertexAttribIPointer(index, size, type, stride, pointer);
- return 1;
- }};
+ template<GLenum type, GLint size>
+ static GLuint
+ vertexAttribFormatFunc(GLuint vao, GLuint index, GLuint offset)
+ {
+ glVertexArrayAttribIFormat(vao, index, size, type, offset);
+ return 1;
+ }
};
template<> struct gl_traits<glm::f32> : public gl_traits_float {
@@ -42,36 +48,43 @@ template<> struct gl_traits<glm::f32> : public gl_traits_float {
static constexpr auto glUniformFunc {&glUniform1f};
static constexpr std::array glUniformvFunc {&glUniform1fv, &glUniform2fv, &glUniform3fv, &glUniform4fv};
static constexpr std::array glUniformmFunc {&glUniformMatrix2fv, &glUniformMatrix3fv, &glUniformMatrix4fv};
- static constexpr auto glTexParameterFunc {&glTexParameterf};
- static constexpr auto glTexParameterfFunc {&glTexParameterfv};
+ static constexpr auto glTextureParameterFunc {&glTextureParameterf};
+ static constexpr auto glTextureParametervFunc {&glTextureParameterfv};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<> struct gl_traits<glm::f64> : public gl_traits_longfloat {
static constexpr GLenum type {GL_DOUBLE};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<> struct gl_traits<glm::int8> : public gl_traits_integer {
static constexpr GLenum type {GL_BYTE};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<> struct gl_traits<glm::int16> : public gl_traits_integer {
static constexpr GLenum type {GL_SHORT};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<> struct gl_traits<glm::int32> : public gl_traits_integer {
static constexpr GLenum type {GL_INT};
static constexpr auto glUniformFunc {&glUniform1i};
static constexpr std::array glUniformvFunc {&glUniform1iv, &glUniform2iv, &glUniform3iv, &glUniform4iv};
- static constexpr auto glTexParameterFunc {&glTexParameteri};
- static constexpr auto glTexParameterfFunc {&glTexParameteriv};
+ static constexpr auto glTextureParameterFunc {&glTextureParameteri};
+ static constexpr auto glTextureParametervFunc {&glTextureParameteriv};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<> struct gl_traits<glm::uint8> : public gl_traits_integer {
static constexpr GLenum type {GL_UNSIGNED_BYTE};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<> struct gl_traits<glm::uint16> : public gl_traits_integer {
static constexpr GLenum type {GL_UNSIGNED_SHORT};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<> struct gl_traits<glm::uint32> : public gl_traits_integer {
@@ -79,35 +92,44 @@ template<> struct gl_traits<glm::uint32> : public gl_traits_integer {
static constexpr auto glUniformFunc {&glUniform1ui};
static constexpr std::array<decltype(&glUniform1uiv), 5> glUniformvFunc {
&glUniform1uiv, &glUniform2uiv, &glUniform3uiv, &glUniform4uiv};
+ static constexpr auto vertexArrayAttribFormat {&vertexAttribFormatFunc<type, 1>};
};
template<typename T, std::size_t S> struct gl_traits<std::array<T, S>> : public gl_traits<T> {
static constexpr GLint size {S * gl_traits<T>::size};
- static constexpr auto vertexAttribFunc {
- [](GLuint index, GLint, GLenum type, GLsizei stride, const void * pointer) -> GLuint {
- const auto base = static_cast<const T *>(pointer);
- for (GLuint e = 0; e < S; e++) {
- glVertexAttribPointer(index + e, gl_traits<T>::size, type, GL_FALSE, stride, base + e);
- }
- return S;
- }};
+ static constexpr auto vertexArrayAttribFormat {[](GLuint vao, GLuint index, GLuint offset) {
+ if constexpr (std::is_pod_v<T>) {
+ return gl_traits<T>::template vertexAttribFormatFunc<gl_traits<T>::type, S>(vao, index, offset);
+ }
+ else {
+ GLuint used = 0;
+ for (GLuint e = 0; e < S; e++) {
+ used += gl_traits<T>::template vertexAttribFormatFunc<gl_traits<T>::type, 1>(
+ vao, index + e, offset + (e * sizeof(T)));
+ }
+ return used;
+ }
+ }};
};
template<glm::length_t L, typename T, glm::qualifier Q> struct gl_traits<glm::vec<L, T, Q>> : public gl_traits<T> {
static constexpr GLint size {L};
+ static constexpr auto vertexArrayAttribFormat {[](GLuint vao, GLuint index, GLuint offset) {
+ return gl_traits<T>::template vertexAttribFormatFunc<gl_traits<T>::type, L>(vao, index, offset);
+ }};
};
template<glm::length_t C, glm::length_t R, typename T, glm::qualifier Q>
struct gl_traits<glm::mat<C, R, T, Q>> : public gl_traits<T> {
static constexpr GLint size {C * R};
- static constexpr auto vertexAttribFunc {
- [](GLuint index, GLint, GLenum type, GLsizei stride, const void * pointer) -> GLuint {
- const auto base = static_cast<const T *>(pointer);
- for (GLuint r = 0; r < R; r++) {
- glVertexAttribPointer(index + r, C, type, GL_FALSE, stride, base + (r * C));
- }
- return R;
- }};
+ static constexpr auto vertexArrayAttribFormat {[](GLuint vao, GLuint index, GLuint offset) {
+ GLuint used = 0;
+ for (GLuint row = 0; row < R; row++) {
+ used += gl_traits<T>::template vertexAttribFormatFunc<gl_traits<T>::type, C>(
+ vao, index + row, offset + (C * row * static_cast<GLuint>(sizeof(T))));
+ }
+ return used;
+ }};
};
template<typename T>
@@ -117,9 +139,9 @@ concept has_glUniformNv = requires { gl_traits<T>::glUniformvFunc; };
template<typename T>
concept has_glUniformMatrixNv = requires { gl_traits<T>::glUniformmFunc; };
template<typename T>
-concept has_glTexParameter = requires { gl_traits<T>::glTexParameterFunc; };
+concept has_glTextureParameter = requires { gl_traits<T>::glTextureParameterFunc; };
template<typename T>
-concept has_glTexParameterf = requires { gl_traits<T>::glTexParameterfFunc; };
+concept has_glTextureParameterv = requires { gl_traits<T>::glTextureParametervFunc; };
template<has_glUniform1 T>
void
@@ -163,17 +185,3 @@ glUniform(GLint location, std::span<const glm::mat<L, L, T, Q>> v)
(*gl_traits<T>::glUniformmFunc[L - 2])(
location, static_cast<GLsizei>(v.size()), GL_FALSE, glm::value_ptr(v.front()));
}
-
-template<has_glTexParameter T>
-void
-glTexParameter(GLenum target, GLenum pname, T param)
-{
- (*gl_traits<T>::glTexParameterFunc)(target, pname, param);
-}
-
-template<glm::length_t L, has_glTexParameterf T, glm::qualifier Q>
-void
-glTexParameter(GLenum target, GLenum pname, const glm::vec<L, T, Q> & param)
-{
- (*gl_traits<T>::glTexParameterfFunc)(target, pname, glm::value_ptr(param));
-}
diff --git a/lib/jsonParse.ll b/lib/jsonParse.ll
index 100bc46..abcd070 100644
--- a/lib/jsonParse.ll
+++ b/lib/jsonParse.ll
@@ -149,7 +149,10 @@ text [^\\\"]*
<*>. {
LexerError("Unexpected input");
- // Make iwyu think unistd.h is required
- [[maybe_unused]]static constexpr auto x=getpid;
- [[maybe_unused]]static constexpr auto y=printf;
}
+
+%%
+
+// Make iwyu think unistd.h is required
+[[maybe_unused]]static constexpr auto x=getpid;
+[[maybe_unused]]static constexpr auto y=printf;
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..4a835d3 100644
--- a/lib/maths.h
+++ b/lib/maths.h
@@ -76,6 +76,18 @@ constexpr auto degreesToRads = pi / 180.F;
constexpr auto earthMeanRadius = 6371.01F; // In km
constexpr auto astronomicalUnit = 149597890.F; // In km
+// GLM round is not constexpr :( And we can use lround to convert at the same time
+template<glm::length_t D, std::floating_point T, glm::qualifier Q>
+[[nodiscard]] constexpr glm::vec<D, long, Q>
+lround(const glm::vec<D, T, Q> & value)
+{
+ glm::vec<D, long, Q> out {};
+ for (glm::length_t axis = 0; axis < D; ++axis) {
+ out[axis] = std::lround(value[axis]);
+ }
+ return out;
+}
+
template<glm::length_t D>
constexpr GlobalPosition<D>
operator+(const GlobalPosition<D> & global, const RelativePosition<D> & relative)
@@ -504,11 +516,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/ray.h b/lib/ray.h
index 793e21e..642cd4d 100644
--- a/lib/ray.h
+++ b/lib/ray.h
@@ -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>