diff options
| author | untodesu <kirill@untode.su> | 2025-12-26 17:29:40 +0500 |
|---|---|---|
| committer | untodesu <kirill@untode.su> | 2025-12-26 17:29:40 +0500 |
| commit | 50c6db34574ce5c9d67e9a7c70a7cafb19ac2007 (patch) | |
| tree | 730a59d1f08b8344df7653b98d884328449fc8d1 /src/game/shared/world | |
| parent | e73282ec5c8fd2b04cdae5c2641e7bc622ccce1f (diff) | |
| download | voxelius-50c6db34574ce5c9d67e9a7c70a7cafb19ac2007.tar.bz2 voxelius-50c6db34574ce5c9d67e9a7c70a7cafb19ac2007.zip | |
Rework collision. Possibly fixes #19
Diffstat (limited to 'src/game/shared/world')
| -rw-r--r-- | src/game/shared/world/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/game/shared/world/ray_aabb.cc | 64 | ||||
| -rw-r--r-- | src/game/shared/world/ray_aabb.hh | 30 |
3 files changed, 96 insertions, 0 deletions
diff --git a/src/game/shared/world/CMakeLists.txt b/src/game/shared/world/CMakeLists.txt index db3f370..baa9b71 100644 --- a/src/game/shared/world/CMakeLists.txt +++ b/src/game/shared/world/CMakeLists.txt @@ -10,6 +10,8 @@ target_sources(shared PRIVATE "${CMAKE_CURRENT_LIST_DIR}/item_registry.hh" "${CMAKE_CURRENT_LIST_DIR}/item.cc" "${CMAKE_CURRENT_LIST_DIR}/item.hh" + "${CMAKE_CURRENT_LIST_DIR}/ray_aabb.cc" + "${CMAKE_CURRENT_LIST_DIR}/ray_aabb.hh" "${CMAKE_CURRENT_LIST_DIR}/ray_dda.cc" "${CMAKE_CURRENT_LIST_DIR}/ray_dda.hh" "${CMAKE_CURRENT_LIST_DIR}/voxel_registry.cc" diff --git a/src/game/shared/world/ray_aabb.cc b/src/game/shared/world/ray_aabb.cc new file mode 100644 index 0000000..f6f2638 --- /dev/null +++ b/src/game/shared/world/ray_aabb.cc @@ -0,0 +1,64 @@ +#include "shared/pch.hh" + +#include "shared/world/ray_aabb.hh" + +RayAABB::RayAABB(const glm::fvec3& start, const glm::fvec3& dir) noexcept +{ + reset(start, dir); +} + +void RayAABB::reset(const glm::fvec3& start, const glm::fvec3& dir) noexcept +{ + assert(std::isfinite(start.x)); + assert(std::isfinite(start.y)); + assert(std::isfinite(start.z)); + assert(std::isfinite(dir.x)); + assert(std::isfinite(dir.y)); + assert(std::isfinite(dir.z)); + + m_start_pos = start; + m_direction = dir; +} + +bool RayAABB::intersect(const math::AABBf& aabb, float& distance, glm::fvec3& surface) const noexcept +{ + // Adapted from https://github.com/gdbooks/3DCollisions/blob/master/Chapter3/raycast_aabb.md + + constexpr static std::array<glm::fvec3, 6> TNORMALS = { + glm::fvec3(-1.0f, 0.0f, 0.0f), + glm::fvec3(1.0f, 0.0f, 0.0f), + glm::fvec3(0.0f, -1.0f, 0.0f), + glm::fvec3(0.0f, 1.0f, 0.0f), + glm::fvec3(0.0f, 0.0f, -1.0f), + glm::fvec3(0.0f, 0.0f, 1.0f), + }; + + std::array<float, 6> tvalues; + tvalues[0] = (aabb.min.x - m_start_pos.x) / m_direction.x; + tvalues[1] = (aabb.max.x - m_start_pos.x) / m_direction.x; + tvalues[2] = (aabb.min.y - m_start_pos.y) / m_direction.y; + tvalues[3] = (aabb.max.y - m_start_pos.y) / m_direction.y; + tvalues[4] = (aabb.min.z - m_start_pos.z) / m_direction.z; + tvalues[5] = (aabb.max.z - m_start_pos.z) / m_direction.z; + + static_assert(tvalues.size() == TNORMALS.size()); + + auto tmin = std::max(std::max(std::min(tvalues[0], tvalues[1]), std::min(tvalues[2], tvalues[3])), std::min(tvalues[4], tvalues[5])); + auto tmax = std::min(std::min(std::max(tvalues[0], tvalues[1]), std::max(tvalues[2], tvalues[3])), std::max(tvalues[4], tvalues[5])); + + if(tmax < 0.0f || tmin > tmax) { + distance = std::numeric_limits<float>::quiet_NaN(); + return false; // no intersection + } + + for(std::size_t i = 0U; i < tvalues.size(); ++i) { + if(tvalues[i] == tmin) { + surface = TNORMALS[i]; + break; + } + } + + distance = tmin < 0.0f ? tmax : tmin; + + return true; +} diff --git a/src/game/shared/world/ray_aabb.hh b/src/game/shared/world/ray_aabb.hh new file mode 100644 index 0000000..49c0846 --- /dev/null +++ b/src/game/shared/world/ray_aabb.hh @@ -0,0 +1,30 @@ +#pragma once + +#include "core/math/aabb.hh" + +class RayAABB final { +public: + RayAABB(void) = default; + explicit RayAABB(const glm::fvec3& start, const glm::fvec3& dir) noexcept; + + constexpr const glm::fvec3& start_pos(void) const noexcept; + constexpr const glm::fvec3& direction(void) const noexcept; + + void reset(const glm::fvec3& start, const glm::fvec3& dir) noexcept; + + bool intersect(const math::AABBf& aabb, float& distance, glm::fvec3& surface) const noexcept; + +private: + glm::fvec3 m_start_pos; + glm::fvec3 m_direction; +}; + +constexpr const glm::fvec3& RayAABB::start_pos(void) const noexcept +{ + return m_start_pos; +} + +constexpr const glm::fvec3& RayAABB::direction(void) const noexcept +{ + return m_direction; +} |
