85 lines
3.2 KiB
C++
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
|