Browse Source

Add structured binding support to math::vector

master
C. J. Howard 1 year ago
parent
commit
d1ac96e9e7
6 changed files with 191 additions and 88 deletions
  1. +1
    -1
      src/game/state/boot.cpp
  2. +47
    -25
      src/game/system/terrain.cpp
  3. +2
    -0
      src/game/system/terrain.hpp
  4. +7
    -7
      src/geom/hyperoctree.hpp
  5. +33
    -44
      src/geom/morton.hpp
  6. +101
    -11
      src/math/vector.hpp

+ 1
- 1
src/game/state/boot.cpp View File

@ -652,7 +652,7 @@ void boot::setup_scenes()
// Setup surface camera
ctx.surface_camera = new scene::camera();
ctx.surface_camera->set_perspective(math::radians<float>(45.0f), viewport_aspect_ratio, 0.1f, 500.0f);
ctx.surface_camera->set_perspective(math::radians<float>(45.0f), viewport_aspect_ratio, 0.1f, 10000.0f);
ctx.surface_camera->set_compositor(ctx.surface_compositor);
ctx.surface_camera->set_composite_index(0);
ctx.surface_camera->set_active(false);

+ 47
- 25
src/game/system/terrain.cpp View File

@ -57,30 +57,6 @@ terrain::terrain(entity::registry& registry):
for (std::size_t i = 0; i <= quadtree_type::max_depth; ++i)
quadtree_node_size[i] = 0.0f;
geom::quadtree64<geom::hyperoctree_order::dfs_pre> q;
q.insert(q.node(4, 0));
//q.insert(q.node(8, geom::morton::encode<std::uint64_t>(4, 4)));
// std::cout << "q size: " << q.size() << std::endl;
// q.erase(q.node(1, 0));
// std::cout << "q size: " << q.size() << std::endl;
std::cout << "q maxd : " << (std::size_t)q.max_depth << std::endl;
std::cout << "q res : " << (std::size_t)q.resolution << std::endl;
std::cout << "q cap : " << q.max_size() << std::endl;
std::cout << "set cap: " << std::set<std::uint64_t>().max_size() << std::endl;
std::cout << "q size: " << q.size() << std::endl;
for (auto it = q.begin(); it != q.end(); ++it)
{
const auto& node = *it;
auto [depth, location] = q.split(node);
std::cout << "depth: " << (std::size_t)depth << "; location: " << (std::size_t)location << std::endl;
}
registry.on_construct<component::terrain>().connect<&terrain::on_terrain_construct>(this);
registry.on_update<component::terrain>().connect<&terrain::on_terrain_update>(this);
registry.on_destroy<component::terrain>().connect<&terrain::on_terrain_destroy>(this);
@ -144,13 +120,19 @@ void terrain::update(double t, double dt)
geom::sphere<float> sphere;
sphere.center = cam.get_translation();
sphere.radius = patch_side_length;
//sphere.radius = patch_side_length;
sphere.radius = 1.0f;
// Determine camera position node
auto translation = cam.get_translation();
//visit_quadtree(cam.get_view_frustum().get_bounds(), quadtree_type::root);
visit_quadtree(sphere, quadtree_type::root);
}
);
balance_quadtree();
//std::cout << "qsize: " << quadtree.size() << std::endl;
std::size_t qvis = 0;
@ -340,6 +322,46 @@ void terrain::visit_quadtree(const geom::bounding_volume& volume, quadtre
}
}
void terrain::balance_quadtree()
{
std::unordered_set<quadtree_node_type> nodes;
for (const auto& node: quadtree)
{
auto [depth, location] = quadtree.split(node);
// Skip root node
if (depth < 2)
continue;
quadtree_node_type x, y;
geom::morton::decode(location, x, y);
--depth;
if (x < quadtree.resolution - 1)
{
if (y < quadtree.resolution - 1)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x + 1, y + 1)));
if (y > 0)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x + 1, y - 1)));
}
if (x > 0)
{
if (y < quadtree.resolution - 1)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x - 1, y + 1)));
if (y > 0)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x - 1, y - 1)));
}
}
for (const auto& node: nodes)
{
quadtree.insert(node);
}
}
geom::mesh* terrain::generate_patch_mesh(quadtree_node_type node) const
{
// Extract node depth

+ 2
- 0
src/game/system/terrain.hpp View File

@ -85,6 +85,8 @@ private:
typedef geom::unordered_quadtree16 quadtree_type;
typedef typename quadtree_type::node_type quadtree_node_type;
void balance_quadtree();
struct patch
{
geom::mesh* mesh;

+ 7
- 7
src/geom/hyperoctree.hpp View File

@ -32,16 +32,16 @@
namespace geom {
/// Orders in which hyperoctree nodes can be stored and iterated.
/// Orders in which hyperoctree nodes can be stored and traversed.
enum class hyperoctree_order
{
/// Hyperoctree nodes are unordered, potentially resulting in faster insertions through the internal use of `std::unordered_set` rather than `std::set`.
unordered,
/// Hyperoctree nodes are stored and iterated in depth-first preorder.
/// Hyperoctree nodes are stored and traversed in depth-first preorder.
dfs_pre,
/// Hyperoctree nodes are stored and iterated in breadth-first order.
/// Hyperoctree nodes are stored and traversed in breadth-first order.
bfs
};
@ -89,7 +89,7 @@ struct hyperoctree_container
*
* @tparam T Unsigned integral node identifier type.
* @tparam N Number of dimensions.
* @tparam Order Order in which nodes are stored and iterated.
* @tparam Order Order in which nodes are stored and traversed.
*
* @see http://codervil.blogspot.com/2015/10/octree-node-identifiers.html
* @see https://geidav.wordpress.com/2014/08/18/advanced-octrees-2-node-representations/
@ -309,7 +309,7 @@ public:
}
/**
* Constructs an identifier for first common ancestor of two nodes
* Constructs an identifier for the first common ancestor of two nodes
*
* @param a Identifier of the first node.
* @param b Identifier of the second node.
@ -470,7 +470,7 @@ public:
}
/// Returns the total number of nodes the hyperoctree is capable of containing.
static consteval std::size_t max_size() noexcept
consteval std::size_t max_size() const noexcept
{
return max_node_count;
}
@ -487,7 +487,7 @@ public:
}
/**
* Inserts a node and its siblings into the hyperoctree, creating ancestors as necessary.
* Inserts a node and its siblings into the hyperoctree, inserting ancestors as necessary.
*
* @param node Node to insert.
*

+ 33
- 44
src/geom/morton.hpp View File

@ -20,8 +20,7 @@
#ifndef ANTKEEPER_GEOM_MORTON_HPP
#define ANTKEEPER_GEOM_MORTON_HPP
#include <array>
#include <cstddef>
#include <concepts>
namespace geom {
@ -33,45 +32,11 @@ namespace morton {
*
* @param[in] x X-coordinate to encode.
* @param[in] y Y-coordinate to encode.
* @return Morton location code.
*/
template <typename T>
T encode(T x, T y);
/**
* Encodes 3D coordinates as a Morton location code.
*
* @param[in] x X-coordinate to encode.
* @param[in] y Y-coordinate to encode.
* @param[in] z Z-coordinate to encode.
* @return Morton location code.
*/
template <typename T>
T encode(T x, T y, T z);
/**
* Decodes 2D coordinates from a Morton location code.
*
* @param[in] code Morton location code to decode.
* @param[out] x Decoded x-coordinate.
* @param[out] y Decoded y-coordinate.
*/
template <typename T>
void decode(T code, T& x, T& y);
/**
* Decodes 3D coordinates from a Morton location code.
*
* @param[in] code Morton location code to decode.
* @param[out] x Decoded x-coordinate.
* @param[out] y Decoded y-coordinate.
* @param[out] z Decoded z-coordinate.
*/
template <typename T>
void decode(T code, T& x, T& y, T& z);
template <typename T>
T encode(T x, T y)
template <std::unsigned_integral T>
constexpr T encode(T x, T y) noexcept
{
auto expand = [](T x) -> T
{
@ -93,8 +58,17 @@ T encode(T x, T y)
return expand(x) | (expand(y) << 1);
}
template <typename T>
T encode(T x, T y, T z)
/**
* Encodes 3D coordinates as a Morton location code.
*
* @param[in] x X-coordinate to encode.
* @param[in] y Y-coordinate to encode.
* @param[in] z Z-coordinate to encode.
*
* @return Morton location code.
*/
template <std::unsigned_integral T>
constexpr T encode(T x, T y, T z) noexcept
{
auto expand = [](T x) -> T
{
@ -134,8 +108,15 @@ T encode(T x, T y, T z)
return expand(x) | (expand(y) << 1) | (expand(z) << 2);
}
template <typename T>
void decode(T code, T& x, T& y)
/**
* Decodes 2D coordinates from a Morton location code.
*
* @param[in] code Morton location code to decode.
* @param[out] x Decoded x-coordinate.
* @param[out] y Decoded y-coordinate.
*/
template <std::unsigned_integral T>
void decode(T code, T& x, T& y) noexcept
{
auto compress = [](T x) -> T
{
@ -158,8 +139,16 @@ void decode(T code, T& x, T& y)
y = compress(code >> 1);
}
template <typename T>
void decode(T code, T& x, T& y, T& z)
/**
* Decodes 3D coordinates from a Morton location code.
*
* @param[in] code Morton location code to decode.
* @param[out] x Decoded x-coordinate.
* @param[out] y Decoded y-coordinate.
* @param[out] z Decoded z-coordinate.
*/
template <std::unsigned_integral T>
void decode(T code, T& x, T& y, T& z) noexcept
{
auto compress = [](T x) -> T
{

+ 101
- 11
src/math/vector.hpp View File

@ -49,6 +49,8 @@ struct vector
/// Array of vector elements.
element_type elements[N];
/// @name Element access
/// @{
/**
* Returns a reference to the element at a given index.
*
@ -91,6 +93,18 @@ struct vector
}
/// @}
/// Returns a pointer to the element array.
/// @{
constexpr inline element_type* data() noexcept
{
return elements;
};
constexpr inline const element_type* data() const noexcept
{
return elements;
};
/// @}
/// Returns a reference to the first element.
/// @{
constexpr inline element_type& x() noexcept
@ -132,19 +146,10 @@ struct vector
return elements[2];
}
/// @}
/// Returns a pointer to the element array.
/// @{
constexpr inline element_type* data() noexcept
{
return elements;
};
constexpr inline const element_type* data() const noexcept
{
return elements;
};
/// @}
/// @name Iterators
/// @{
/// Returns an iterator to the first element.
/// @{
constexpr inline element_type* begin() noexcept
@ -208,12 +213,16 @@ struct vector
return std::reverse_iterator<const element_type*>(elements);
}
/// @}
/// @}
/// @name Capacity
/// @{
/// Returns the number of elements in the vector.
constexpr inline std::size_t size() const noexcept
{
return N;
};
/// @}
/// @private
template <class U, std::size_t... I>
@ -469,6 +478,28 @@ constexpr vector fma(const vector& x, T y, T z);
template <class T, std::size_t N>
constexpr vector<T, N> fract(const vector<T, N>& x);
/**
* Extracts the Ith element from a vector.
*
* @tparam I Index of an element.
* @tparam T Element type.
* @tparam N Number of elements.
*
* @param v Vector from which to extract an element.
*
* @return Reference to the Ith element of @p v.
*/
/// @{
template<std::size_t I, class T, std::size_t N>
constexpr T& get(math::vector<T, N>& v) noexcept;
template<std::size_t I, class T, std::size_t N>
constexpr T&& get(math::vector<T, N>&& v) noexcept;
template<std::size_t I, class T, std::size_t N>
constexpr const T& get(const math::vector<T, N>& v) noexcept;
template<std::size_t I, class T, std::size_t N>
constexpr const T&& get(const math::vector<T, N>&& v) noexcept;
/// @}
/**
* Performs a element-wise greater-than comparison of two vectors.
*
@ -1011,6 +1042,34 @@ constexpr inline vector fract(const vector& x)
return fract(x, std::make_index_sequence<N>{});
}
template<std::size_t I, class T, std::size_t N>
constexpr inline T& get(math::vector<T, N>& v) noexcept
{
static_assert(I < N);
return v.elements[I];
}
template<std::size_t I, class T, std::size_t N>
constexpr inline T&& get(math::vector<T, N>&& v) noexcept
{
static_assert(I < N);
return std::move(v.elements[I]);
}
template<std::size_t I, class T, std::size_t N>
constexpr inline const T& get(const math::vector<T, N>& v) noexcept
{
static_assert(I < N);
return v.elements[I];
}
template<std::size_t I, class T, std::size_t N>
constexpr inline const T&& get(const math::vector<T, N>&& v) noexcept
{
static_assert(I < N);
return std::move(v.elements[I]);
}
/// @private
template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
@ -1586,6 +1645,37 @@ std::istream& operator>>(std::istream& is, vector& x)
} // namespace math
// Bring vector operators into global namespace
using namespace math::operators;
// Structured binding support
namespace std
{
/**
* Provides access to the number of elements in a math::vector as a compile-time constant expression.
*
* @tparam T Element type.
* @tparam N Number of elements.
*/
template<class T, std::size_t N>
struct tuple_size<math::vector<T, N>>
{
/// Number of elements in the vector.
static constexpr std::size_t value = N;
};
/**
* Provides compile-time indexed access to the type of the elements in a math::vector using a tuple-like interface.
*
* @tparam T Element type.
* @tparam N Number of elements.
*/
template<std::size_t I, class T, std::size_t N>
struct tuple_element<I, math::vector<T, N>>
{
/// Type of elements in the vector.
using type = T;
};
}
#endif // ANTKEEPER_MATH_VECTOR_HPP

Loading…
Cancel
Save