accelerated-raytracer/src/AABB.h

85 lines
3.2 KiB
C++

#ifndef RAYTRYCPP_AABB_H
#define RAYTRYCPP_AABB_H
#include "KDAxis.h"
#include "RenderObject.h"
#include <array>
#include <utility>
namespace raytry {
struct AABB {
std::array<std::pair<float, float>, KD::Axis::Z + 1> pairs{std::pair{0.0f, 1.0f}, std::pair{0.0f, 1.0f}, std::pair{0.0f, 1.0f}};
[[nodiscard]] std::optional<std::pair<QVector3D, QVector3D>> slabtest(const Ray& ray) const {
QVector3D tNear{-INFINITY, -INFINITY, -INFINITY};
QVector3D tFar{INFINITY, INFINITY, INFINITY};
for (unsigned int a = KD::Axis::X; a <= KD::Axis::Z; ++a) {
if (qFuzzyIsNull(ray.directionVec[a])) {
if (ray.originVec[a] < pairs[a].first || ray.originVec[a] > pairs[a].second) {
return std::nullopt;
}
} else {
float t1 = (pairs[a].first - ray.originVec[a]) / ray.directionVec[a];
float t2 = (pairs[a].second - ray.originVec[a]) / ray.directionVec[a];
if (t1 > t2) {
std::swap(t1, t2);
}
if (t1 > tNear[a]) {
tNear[a] = t1;
}
if (t2 < tFar[a]) {
tFar[a] = t2;
}
if (tNear[a] > tFar[a] || tFar[a] < 0) {
return std::nullopt;
}
}
}
return std::make_pair(tNear, tFar);
}
[[nodiscard]] std::optional<std::pair<QVector3D, QVector3D>> fastslabtest(const Ray& ray, const QVector3D& invDirection) const {
QVector3D t0{pairs[KD::X].first, pairs[KD::Y].first, pairs[KD::Z].first};
QVector3D t1{pairs[KD::X].second, pairs[KD::Y].second, pairs[KD::Z].second};
t0 = (t0 - ray.originVec) * invDirection;
t1 = (t1 - ray.originVec) * invDirection;
float minc = -INFINITY;
float maxc = INFINITY;
for (unsigned int a = KD::Axis::X; a <= KD::Axis::Z; ++a) {
if (t1[a] < t0[a]) {
std::swap(t1[a], t0[a]);
}
minc = std::max(minc, t0[a]);
maxc = std::min(maxc, t1[a]);
}
if (maxc < std::max(0.0f, minc)) {
return std::nullopt;
} else {
return std::make_pair(t0, t1);
}
}
const std::pair<float, float>& operator[](std::size_t idx) const {
return pairs[idx];
}
std::pair<float, float>& operator[](std::size_t idx) {
return pairs[idx];
}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg) const {
return dbg << "AABB(" << pairs[KD::X].first << ", " << pairs[KD::Y].first << ", " << pairs[KD::Z].first <<
" -> " << pairs[KD::X].second << ", " << pairs[KD::Y].second << ", " << pairs[KD::Z].second << ")";
}
friend QDebug operator<<(QDebug dbg, const AABB& box) {
return box.operator<<(std::move(dbg));
}
#endif
};
}// namespace raytry
#endif//RAYTRYCPP_AABB_H