From: Daniel Karbach Date: Wed, 9 Dec 2015 16:22:03 +0000 (+0100) Subject: indexed iteration in ray/world collision tests X-Git-Url: http://git.localhorst.tv/?p=blank.git;a=commitdiff_plain;h=5a5b12ae26b832dd8493be2d30f97d14aee2268c indexed iteration in ray/world collision tests --- diff --git a/src/world/ChunkIndex.hpp b/src/world/ChunkIndex.hpp index 1823de7..eb961a9 100644 --- a/src/world/ChunkIndex.hpp +++ b/src/world/ChunkIndex.hpp @@ -47,6 +47,10 @@ public: int Extent() const noexcept { return extent; } + // raw iteration access, may contain nullptrs + std::vector::const_iterator begin() const noexcept { return chunks.begin(); } + std::vector::const_iterator end() const noexcept { return chunks.end(); } + ExactLocation::Coarse CoordsBegin() const noexcept { return base - ExactLocation::Coarse(extent); } ExactLocation::Coarse CoordsEnd() const noexcept { return base + ExactLocation::Coarse(extent + 1); } diff --git a/src/world/world.cpp b/src/world/world.cpp index 9203136..243fb8a 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -779,12 +779,22 @@ bool World::Intersection( const ExactLocation::Coarse &reference, WorldCollision &coll ) { + // only consider chunks of the idex closest to reference + // this makes the ray not be infinite anymore (which means it's + // actually a line segment), but oh well + ChunkIndex *index = chunks.ClosestIndex(reference); + if (!index) { + return false; + } + candidates.clear(); - for (Chunk &cur_chunk : chunks) { + // TODO: convert to coords based iteration and trim based + // on ray direction + for (Chunk *cur_chunk : *index) { float cur_dist; - if (cur_chunk.Intersection(ray, reference, cur_dist)) { - candidates.push_back({ &cur_chunk, cur_dist }); + if (cur_chunk && cur_chunk->Intersection(ray, reference, cur_dist)) { + candidates.push_back({ cur_chunk, cur_dist }); } } @@ -859,16 +869,19 @@ bool World::Intersection( const glm::ivec3 &reference, std::vector &col ) { + // this only works if box's diameter is < than 16 + ExactLocation::Coarse begin(reference - 1); + ExactLocation::Coarse end(reference + 2); + bool any = false; - for (Chunk &cur_chunk : chunks) { - if (manhattan_radius(cur_chunk.Position() - reference) > 1) { - // chunk is not one of the 3x3x3 surrounding the entity - // since there's no entity which can extent over 16 blocks, they can be skipped - // TODO: change to indexed (like with entity) - continue; - } - if (cur_chunk.Intersection(box, M, cur_chunk.Transform(reference), col)) { - any = true; + for (ExactLocation::Coarse pos(begin); pos.z < end.z; ++pos.z) { + for (pos.y = begin.y; pos.y < end.y; ++pos.y) { + for (pos.x = begin.x; pos.x < end.x; ++pos.x) { + Chunk *chunk = chunks.Get(pos); + if (chunk && chunk->Intersection(box, M, chunk->Transform(reference), col)) { + any = true; + } + } } } return any;