1
Fork 0
raytracer/include/octree.h

92 lines
2.4 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 auto child_pattern = {
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),
};
template<typename UnderlyingType>
struct Node {
using NodeType = Node<UnderlyingType>;
AABB extent;
int depth = 0;
std::vector<UnderlyingType> contained_objects;
std::array<std::unique_ptr<NodeType>, 8> children;
bool is_split = false;
void add(UnderlyingType& object, const AABB extent) {
if(is_split) {
for(auto& child : children) {
if(extent.inside(child->extent))
child->add(object, extent);
}
} else {
contained_objects.push_back(object);
if(contained_objects.size() >= max_contained_types && depth < max_octree_depth)
split();
}
}
void split() {
is_split = true;
const auto center = extent.center();
const auto split_size = extent.extent().x / 2.0f;
int i = 0;
for(auto& point : child_pattern) {
auto child = std::make_unique<NodeType>();
child->depth = depth + 1;
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);
children[i++] = std::move(child);
}
for(auto& object : contained_objects) {
for(auto& child : children) {
if(object.extent.inside(child->extent))
child->add(object, extent);
}
}
contained_objects.clear();
}
};
template<typename UnderlyingType>
struct Octree {
using NodeType = Node<UnderlyingType>;
NodeType root;
Octree(const glm::vec3 min, const glm::vec3 max) {
root = NodeType();
root.extent.min = min;
root.extent.max = max;
}
void add(UnderlyingType& object, const AABB extent) {
root.add(object, extent);
}
};