49 lines
1.8 KiB
C++
49 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include "Universe.hpp"
|
|
#include "Chunk.hpp"
|
|
|
|
namespace world {
|
|
|
|
template<class Areas>
|
|
Universe::ray_result Raycast(const geometry::Ray& ray, const Areas& areas) {
|
|
//MAYBE: ray + offset to get float precision
|
|
Universe::ray_result target;
|
|
size_t dist = UINT32_MAX - 1;
|
|
for(auto& area: areas) {
|
|
if(ray.intersect(area.second->getBounding()) != geometry::IBox::ContainmentType::Disjoint) {
|
|
const auto &offset = area.second->getOffset().as_voxel();
|
|
const auto &chunks = area.second->getChunks();
|
|
std::shared_ptr<world::Chunk> chunk = nullptr;
|
|
chunk_pos chunk_vec(INT_MAX);
|
|
geometry::Ray::iterator it(ray);
|
|
glm::llvec3 point;
|
|
for (size_t i = 0; i < dist && it.next(point); i++) {
|
|
const auto pos = point - offset;
|
|
const chunk_pos cPos = glm::divide(pos);
|
|
if(cPos != chunk_vec) {
|
|
if (const auto it = chunks.find(cPos); it != chunks.end()) {
|
|
chunk = it->second;
|
|
chunk_vec = cPos;
|
|
} else if(chunks.inRange(cPos)) {
|
|
target.emplace<Universe::ray_out_of_range>(std::make_pair(area.first, cPos), offset);
|
|
break;
|
|
} else {
|
|
chunk = nullptr;
|
|
}
|
|
}
|
|
if(chunk != nullptr) {
|
|
const auto voxel = chunk->getAt(glm::modulo(pos));
|
|
if(voxel.is_solid()) {
|
|
target.emplace<Universe::ray_target>(std::make_pair(area.first, pos), voxel, offset);
|
|
dist = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return target;
|
|
}
|
|
|
|
} |