166 lines
3.9 KiB
C++
166 lines
3.9 KiB
C++
#pragma once
|
|
/*
|
|
* Copyright (C) 2024 Brett Terpstra
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef BLT_MATH_AABB_H
|
|
#define BLT_MATH_AABB_H
|
|
|
|
#include <array>
|
|
#include <blt/math/vectors.h>
|
|
#include <blt/std/types.h>
|
|
|
|
namespace blt
|
|
{
|
|
// yes I could use the vector (see tower defense game commit log for this)
|
|
// this feels nicer
|
|
template <typename T = float>
|
|
class axis_t
|
|
{
|
|
public:
|
|
axis_t(const T min, const T max): m_min(min), m_max(max)
|
|
{}
|
|
|
|
[[nodiscard]] bool intersects(const T p) const
|
|
{
|
|
return p >= m_min && p <= m_max;
|
|
}
|
|
|
|
template <typename G>
|
|
[[nodiscard]] bool intersects(const axis_t<G>& other) const
|
|
{
|
|
return static_cast<T>(other.m_min) <= m_max && static_cast<T>(other.m_max) >= m_min;
|
|
}
|
|
|
|
[[nodiscard]] T min() const
|
|
{
|
|
return m_min;
|
|
}
|
|
|
|
[[nodiscard]] T max() const
|
|
{
|
|
return m_max;
|
|
}
|
|
|
|
private:
|
|
T m_min, m_max;
|
|
};
|
|
|
|
namespace detail
|
|
{
|
|
template <u32 Axis, typename T>
|
|
class axis_aligned_bounding_box_base_t
|
|
{
|
|
public:
|
|
[[nodiscard]] vec<T, Axis> get_center() const
|
|
{
|
|
vec<T, Axis> min;
|
|
for (u32 i = 0; i < Axis; i++)
|
|
min[i] = m_axes[i].min();
|
|
const auto center = get_size() / 2.0f;
|
|
return min + center;
|
|
}
|
|
|
|
[[nodiscard]] vec<T, Axis> get_size() const
|
|
{
|
|
vec<T, Axis> size;
|
|
for (u32 i = 0; i < Axis; i++)
|
|
size[i] = m_axes[i].max() - m_axes[i].min();
|
|
return size;
|
|
}
|
|
|
|
template <typename G>
|
|
[[nodiscard]] bool intersects(const axis_aligned_bounding_box_base_t<Axis, G>& other) const
|
|
{
|
|
for (u32 i = 0; i < Axis; i++)
|
|
if (!m_axes[i].intersects(other.m_axes[i]))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
template <typename G>
|
|
[[nodiscard]] bool intersects(const vec<G, Axis>& point) const
|
|
{
|
|
for (u32 i = 0; i < Axis; i++)
|
|
if (!m_axes[i].intersects(point[i]))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
axis_t<T>& operator[](u32 i)
|
|
{
|
|
return m_axes[i];
|
|
}
|
|
|
|
axis_t<T>& axis(u32 i)
|
|
{
|
|
if (i >= Axis)
|
|
throw std::out_of_range("Axis index out of range");
|
|
return m_axes[i];
|
|
}
|
|
|
|
protected:
|
|
std::array<axis_t<T>, Axis> m_axes;
|
|
};
|
|
}
|
|
|
|
template <u32 Axis, typename T>
|
|
class axis_aligned_bounding_box_t : public detail::axis_aligned_bounding_box_base_t<Axis, T>
|
|
{
|
|
public:
|
|
using detail::axis_aligned_bounding_box_base_t<Axis, T>::axis_aligned_bounding_box_base_t;
|
|
};
|
|
|
|
template <typename T>
|
|
class axis_aligned_bounding_box_t<2, T> : public detail::axis_aligned_bounding_box_base_t<2, T>
|
|
{
|
|
public:
|
|
using detail::axis_aligned_bounding_box_base_t<2, T>::axis_aligned_bounding_box_base_t;
|
|
|
|
[[nodiscard]] vec2 min() const
|
|
{
|
|
return {this->m_axes[0].min(), this->m_axes[1].min()};
|
|
}
|
|
|
|
[[nodiscard]] vec2 max() const
|
|
{
|
|
return {this->m_axes[0].max(), this->m_axes[1].max()};
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
class axis_aligned_bounding_box_t<3, T> : public detail::axis_aligned_bounding_box_base_t<3, T>
|
|
{
|
|
public:
|
|
using detail::axis_aligned_bounding_box_base_t<2, T>::axis_aligned_bounding_box_base_t;
|
|
|
|
[[nodiscard]] vec3 min() const
|
|
{
|
|
return {this->m_axes[0].min(), this->m_axes[1].min(), this->m_axes[2].min()};
|
|
}
|
|
|
|
[[nodiscard]] vec3s max() const
|
|
{
|
|
return {this->m_axes[0].max(), this->m_axes[1].max(), this->m_axes[2].max()};
|
|
}
|
|
};
|
|
|
|
using aabb_2d_t = axis_aligned_bounding_box_t<2, float>;
|
|
using aabb_3d_t = axis_aligned_bounding_box_t<3, float>;
|
|
}
|
|
|
|
#endif //BLT_MATH_AABB_H
|