From 7354c74fb8f409336db3a6d70455fbc10232ae64 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Mon, 9 Nov 2015 14:15:36 +0100 Subject: [PATCH] simplify ray/chunk intersection test --- doc/todo | 8 ++++++++ src/ai/ai.cpp | 4 ++-- src/ui/ui.cpp | 4 ++-- src/world/Chunk.hpp | 15 +++++++++++---- src/world/World.hpp | 6 ++---- src/world/chunk.cpp | 8 ++++++-- src/world/world.cpp | 8 +++----- 7 files changed, 34 insertions(+), 19 deletions(-) diff --git a/doc/todo b/doc/todo index 39cb8a7..921221a 100644 --- a/doc/todo +++ b/doc/todo @@ -29,6 +29,9 @@ persistence store some kind of byte order mark? + world and player names should be normalized so they can safely + be used in path names + networking definitely needs throttling for the internets @@ -36,6 +39,11 @@ networking players stats (who's connected, their ping, and game-relevant things) should be sent to clients + some method for authenticating a player might be nice + + maybe stale and inexistent chunks should be visualized (e.g. by + drawing a semi-transparent box around them) + threading (clientside) networking and disk IO are prime candidates for threading diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index a2f5938..0d4c9e9 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -169,7 +169,7 @@ Player *AIController::ClosestVisiblePlayer(const Entity &e) noexcept { // LOS test, assumes all entities are see-through WorldCollision col; - if (world.Intersection(aim, glm::mat4(1.0f), reference, col) && col.depth < dist) { + if (world.Intersection(aim, reference, col) && col.depth < dist) { continue; } @@ -189,7 +189,7 @@ bool AIController::LineOfSight(const Entity &from, const Entity &to) const noexc return false; } WorldCollision col; - if (world.Intersection(aim, glm::mat4(1.0f), reference, col) && col.depth < dist) { + if (world.Intersection(aim, reference, col) && col.depth < dist) { return false; } return true; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index c45b34b..02f2781 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -97,10 +97,10 @@ void PlayerController::Invalidate() noexcept { void PlayerController::UpdatePlayer() noexcept { if (dirty) { Ray aim = player.Aim(); - if (!world.Intersection(aim, glm::mat4(1.0f), player.GetEntity().ChunkCoords(), aim_world)) { + if (!world.Intersection(aim, player.GetEntity().ChunkCoords(), aim_world)) { aim_world = WorldCollision(); } - if (!world.Intersection(aim, glm::mat4(1.0f), player.GetEntity(), aim_entity)) { + if (!world.Intersection(aim, player.GetEntity(), aim_entity)) { aim_entity = EntityCollision(); } if (aim_world && aim_entity) { diff --git a/src/world/Chunk.hpp b/src/world/Chunk.hpp index 4938c1b..d0dcf94 100644 --- a/src/world/Chunk.hpp +++ b/src/world/Chunk.hpp @@ -69,7 +69,11 @@ public: (idx / (side * side)) ); } - glm::mat4 ToTransform(const RoughLocation::Fine &pos, int idx) const noexcept; + /// get a chunk-local transform for block at given position and index + /// (position and index are redundant) + glm::mat4 ToTransform(const RoughLocation::Fine &position, int index) const noexcept; + /// same as above, but also apply offset to given reference + glm::mat4 ToTransform(const ExactLocation::Coarse &ref, const RoughLocation::Fine &pos, int idx) const noexcept; ExactLocation::Fine ToSceneCoords(const ExactLocation::Coarse &base, const ExactLocation::Fine &pos) const noexcept { return ExactLocation::Fine((position - base) * ExactLocation::Extent()) + pos; @@ -130,15 +134,17 @@ public: bool Intersection( const Ray &ray, - const glm::mat4 &M, + const ExactLocation::Coarse &reference, float &dist ) const noexcept { - return blank::Intersection(ray, Bounds(), M, &dist); + return blank::Intersection(ray, Bounds(), Transform(reference), &dist); } + /// check if given ray intersects any block of this chunk + /// given reference indicated the chunk offset of the ray in world space bool Intersection( const Ray &, - const glm::mat4 &M, + const ExactLocation::Coarse &reference, WorldCollision &) noexcept; bool Intersection( @@ -155,6 +161,7 @@ public: void Position(const ExactLocation::Coarse &pos) noexcept { position = pos; } const ExactLocation::Coarse &Position() const noexcept { return position; } + glm::mat4 Transform(const ExactLocation::Coarse &offset) const noexcept { return glm::translate((position - offset) * ExactLocation::Extent()); } diff --git a/src/world/World.hpp b/src/world/World.hpp index 8754d39..767f527 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -45,19 +45,17 @@ public: /// check if this ray hits a block /// depth in the collision is the distance between the ray's /// origin and the intersection point - /// M is the global transform for given reference chunk + /// reference is the chunk offset of the ray in world space bool Intersection( const Ray &, - const glm::mat4 &M, const ExactLocation::Coarse &reference, WorldCollision &); /// check if this ray hits an entity /// intersections with the reference are not tested - /// M is the global transform for the chunk of given reference entity + /// the ray is assumed to be in world space offset by entity's chunk coords bool Intersection( const Ray &, - const glm::mat4 &M, const Entity &reference, EntityCollision &); diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index cc305cd..9e95458 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -359,7 +359,7 @@ bool Chunk::IsSurface(const RoughLocation::Fine &pos) const noexcept { bool Chunk::Intersection( const Ray &ray, - const glm::mat4 &M, + const ExactLocation::Coarse &reference, WorldCollision &coll ) noexcept { int idx = 0; @@ -375,7 +375,7 @@ bool Chunk::Intersection( } float cur_dist; glm::vec3 cur_norm; - if (type.shape->Intersects(ray, M * ToTransform(RoughLocation::Fine(x, y, z), idx), cur_dist, cur_norm)) { + if (type.shape->Intersects(ray, ToTransform(reference, RoughLocation::Fine(x, y, z), idx), cur_dist, cur_norm)) { if (cur_dist < coll.depth) { coll.block = idx; coll.depth = cur_dist; @@ -560,6 +560,10 @@ glm::mat4 Chunk::ToTransform(const RoughLocation::Fine &pos, int idx) const noex return glm::translate(ToCoords(pos)) * BlockAt(idx).Transform(); } +glm::mat4 Chunk::ToTransform(const ExactLocation::Coarse &ref, const RoughLocation::Fine &pos, int idx) const noexcept { + return glm::translate(ExactLocation::Fine((position - ref) * ExactLocation::Extent()) + ToCoords(pos)) * BlockAt(idx).Transform(); +} + BlockLookup::BlockLookup(Chunk *c, const RoughLocation::Fine &p) noexcept : chunk(c), pos(p) { diff --git a/src/world/world.cpp b/src/world/world.cpp index c43747a..5e3420d 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -459,7 +459,6 @@ std::vector candidates; bool World::Intersection( const Ray &ray, - const glm::mat4 &M, const ExactLocation::Coarse &reference, WorldCollision &coll ) { @@ -467,7 +466,7 @@ bool World::Intersection( for (Chunk &cur_chunk : chunks) { float cur_dist; - if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(reference), cur_dist)) { + if (cur_chunk.Intersection(ray, reference, cur_dist)) { candidates.push_back({ &cur_chunk, cur_dist }); } } @@ -483,7 +482,7 @@ bool World::Intersection( for (Candidate &cand : candidates) { if (cand.dist > coll.depth) continue; WorldCollision cur_coll; - if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(reference), cur_coll)) { + if (cand.chunk->Intersection(ray, reference, cur_coll)) { if (cur_coll.depth < coll.depth) { coll = cur_coll; } @@ -495,7 +494,6 @@ bool World::Intersection( bool World::Intersection( const Ray &ray, - const glm::mat4 &M, const Entity &reference, EntityCollision &coll ) { @@ -507,7 +505,7 @@ bool World::Intersection( } float cur_dist; glm::vec3 cur_normal; - if (blank::Intersection(ray, cur_entity.Bounds(), M * cur_entity.Transform(reference.ChunkCoords()), &cur_dist, &cur_normal)) { + if (blank::Intersection(ray, cur_entity.Bounds(), cur_entity.Transform(reference.ChunkCoords()), &cur_dist, &cur_normal)) { // TODO: fine grained check goes here? maybe? if (cur_dist < coll.depth) { coll.entity = &cur_entity; -- 2.39.2