1
Fork 0
raytracer/include/octree.h

90 lines
2.3 KiB
C
Raw Normal View History

2020-07-30 10:06:47 -04:00
#pragma once
2022-03-27 21:31:09 -04:00
#include <memory>
2020-07-30 10:06:47 -04:00
#include "aabb.h"
constexpr int max_contained_types = 16;
constexpr int max_octree_depth = 2;
constexpr std::array child_pattern = {
2020-07-30 10:06:47 -04:00
glm::vec3(+1, -1, -1),
glm::vec3(+1, -1, +1),
glm::vec3(+1, +1, -1),
glm::vec3(+1, +1, +1),
glm::vec3(-1, -1, -1),
glm::vec3(-1, -1, +1),
glm::vec3(-1, +1, -1),
glm::vec3(-1, +1, +1),
};
2022-08-16 07:41:12 -04:00
template<typename UnderlyingType> struct Node {
2020-07-30 10:06:47 -04:00
using NodeType = Node<UnderlyingType>;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
AABB extent;
int depth = 0;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
std::vector<UnderlyingType> contained_objects;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
std::array<std::unique_ptr<NodeType>, 8> children;
bool is_split = false;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
void add(UnderlyingType& object, const AABB extent) {
2022-08-16 07:41:12 -04:00
if (is_split) {
for (auto& child : children) {
if (extent.inside(child->extent))
2020-07-30 10:06:47 -04:00
child->add(object, extent);
}
} else {
contained_objects.push_back(object);
2022-08-16 07:41:12 -04:00
if (contained_objects.size() >= max_contained_types && depth < max_octree_depth)
2020-07-30 10:06:47 -04:00
split();
}
}
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
void split() {
is_split = true;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
const auto center = extent.center();
const auto split_size = extent.extent().x / 2.0f;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
int i = 0;
2022-08-16 07:41:12 -04:00
for (auto& point : child_pattern) {
2020-07-30 10:06:47 -04:00
auto child = std::make_unique<NodeType>();
child->depth = depth + 1;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
const auto position = center + point * split_size;
child->extent.min = glm::vec3(position.x - split_size, position.y - split_size, position.z - split_size);
child->extent.max = glm::vec3(position.x + split_size, position.y + split_size, position.z + split_size);
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
children[i++] = std::move(child);
}
2022-08-16 07:41:12 -04:00
for (auto& object : contained_objects) {
for (auto& child : children) {
if (object.extent.inside(child->extent))
2020-07-30 10:06:47 -04:00
child->add(object, extent);
}
}
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
contained_objects.clear();
}
};
2022-08-16 07:41:12 -04:00
template<typename UnderlyingType> struct Octree {
2020-07-30 10:06:47 -04:00
using NodeType = Node<UnderlyingType>;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
NodeType root;
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
Octree(const glm::vec3 min, const glm::vec3 max) {
root = NodeType();
root.extent.min = min;
root.extent.max = max;
}
2022-08-16 07:41:12 -04:00
2020-07-30 10:06:47 -04:00
void add(UnderlyingType& object, const AABB extent) {
root.add(object, extent);
}
};