From: Daniel Karbach Date: Wed, 24 Jun 2015 14:26:44 +0000 (+0200) Subject: test entities for world collision X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=c04ea5a6f67d446ea29aa2e88dc4c666956d7732;p=blank.git test entities for world collision useless and slow as hell, but hey, it's a start ^^ --- diff --git a/src/app/Application.cpp b/src/app/Application.cpp index 67438db..a5613f9 100644 --- a/src/app/Application.cpp +++ b/src/app/Application.cpp @@ -32,7 +32,10 @@ Application::Application(const Config &config) Entity &Application::MakeTestEntity(World &world) { Entity &e = world.AddEntity(); + e.Name("test"); e.Position({ 0.0f, 0.0f, 0.0f }); + e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } }); + e.WorldCollidable(true); e.SetShape(world.BlockTypes()[1].shape, { 1.0f, 1.0f, 0.0f }); e.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f })); return e; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 410072d..c71b7c1 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -356,7 +356,7 @@ void Interface::Update(int dt) { void Interface::CheckAim() { float dist; - if (world.Intersection(aim, glm::mat4(1.0f), &aim_chunk, &aim_block, &dist, &aim_normal)) { + if (world.Intersection(aim, glm::mat4(1.0f), aim_chunk, aim_block, dist, aim_normal)) { outline.Clear(); aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outline); outline_transform = glm::scale(glm::vec3(1.0002f)); diff --git a/src/world/Chunk.hpp b/src/world/Chunk.hpp index 8d6816c..8a2ded6 100644 --- a/src/world/Chunk.hpp +++ b/src/world/Chunk.hpp @@ -143,6 +143,11 @@ public: float &dist, glm::vec3 &normal) const noexcept; + bool Intersection( + const AABB &box, + const glm::mat4 &Mbox, + const glm::mat4 &Mchunk) const noexcept; + void Position(const Pos &pos) noexcept { position = pos; } const Pos &Position() const noexcept { return position; } glm::mat4 Transform(const Pos &offset) const noexcept { diff --git a/src/world/Entity.cpp b/src/world/Entity.cpp index 6b23cac..844f74b 100644 --- a/src/world/Entity.cpp +++ b/src/world/Entity.cpp @@ -1,6 +1,5 @@ #include "Entity.hpp" -#include "../model/geometry.hpp" #include "../model/Shape.hpp" #include @@ -17,11 +16,14 @@ namespace blank { Entity::Entity() noexcept : shape(nullptr) , model() +, name("anonymous") +, bounds() , velocity(0, 0, 0) , position(0, 0, 0) , chunk(0, 0, 0) , angular_velocity(1.0f, 0.0f, 0.0f, 0.0f) -, rotation(1.0f) { +, rotation(1.0f) +, world_collision(false) { } diff --git a/src/world/Entity.hpp b/src/world/Entity.hpp index 83c1f6f..7c96f4f 100644 --- a/src/world/Entity.hpp +++ b/src/world/Entity.hpp @@ -3,15 +3,16 @@ #include "Block.hpp" #include "Chunk.hpp" +#include "../model/geometry.hpp" #include "../model/Model.hpp" +#include #include #include namespace blank { -class Ray; class Shape; class Entity { @@ -24,6 +25,15 @@ public: void SetShape(const Shape *, const glm::vec3 &color); void SetShapeless() noexcept; + const std::string &Name() const noexcept { return name; } + void Name(const std::string &n) { name = n; } + + const AABB &Bounds() const noexcept { return bounds; } + void Bounds(const AABB &b) noexcept { bounds = b; } + + bool WorldCollidable() const noexcept { return world_collision; } + void WorldCollidable(bool b) noexcept { world_collision = b; } + const glm::vec3 &Velocity() const noexcept { return velocity; } void Velocity(const glm::vec3 &) noexcept; @@ -51,6 +61,10 @@ private: const Shape *shape; Model model; + std::string name; + + AABB bounds; + glm::vec3 velocity; Block::Pos position; Chunk::Pos chunk; @@ -58,6 +72,8 @@ private: glm::quat angular_velocity; glm::mat4 rotation; + bool world_collision; + }; } diff --git a/src/world/World.cpp b/src/world/World.cpp index 529968e..82701ce 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -3,6 +3,7 @@ #include "../graphics/BlockLighting.hpp" #include "../graphics/DirectionalLighting.hpp" +#include #include #include @@ -113,6 +114,9 @@ World::World(const Config &config) generate.Solids({ 1, 4, 7, 10 }); player = &AddEntity(); + player->Name("player"); + player->Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } }); + player->WorldCollidable(true); player->Position(config.spawn); chunks.GenerateSurrounding(player->ChunkCoords()); @@ -131,12 +135,13 @@ std::vector candidates; } bool World::Intersection( - const Ray &ray, - const glm::mat4 &M, - Chunk **chunk, - int *blkid, - float *dist, - glm::vec3 *normal) { + const Ray &ray, + const glm::mat4 &M, + Chunk *&chunk, + int &blkid, + float &dist, + glm::vec3 &normal +) { candidates.clear(); for (Chunk &cur_chunk : chunks.Loaded()) { @@ -148,39 +153,37 @@ bool World::Intersection( if (candidates.empty()) return false; - Chunk *closest_chunk = nullptr; - float closest_dist = std::numeric_limits::infinity(); - int closest_blkid = -1; - glm::vec3 closest_normal; + chunk = nullptr; + dist = std::numeric_limits::infinity(); + blkid = -1; for (Candidate &cand : candidates) { - if (cand.dist > closest_dist) continue; + if (cand.dist > dist) continue; int cur_blkid; float cur_dist; glm::vec3 cur_normal; if (cand.chunk->Intersection(ray, M * cand.chunk->Transform(player->ChunkCoords()), cur_blkid, cur_dist, cur_normal)) { - if (cur_dist < closest_dist) { - closest_chunk = cand.chunk; - closest_blkid = cur_blkid; - closest_dist = cur_dist; - closest_normal = cur_normal; + if (cur_dist < dist) { + chunk = cand.chunk; + blkid = cur_blkid; + dist = cur_dist; + normal = cur_normal; } } } - if (chunk) { - *chunk = closest_chunk; - } - if (blkid) { - *blkid = closest_blkid; - } - if (dist) { - *dist = closest_dist; - } - if (normal) { - *normal = closest_normal; + return chunk; +} + +bool World::Intersection(const Entity &e) { + AABB box = e.Bounds(); + glm::mat4 M = e.Transform(player->ChunkCoords()); + for (Chunk &cur_chunk : chunks.Loaded()) { + if (cur_chunk.Intersection(box, M, cur_chunk.Transform(player->ChunkCoords()))) { + return true; + } } - return closest_chunk; + return false; } @@ -198,6 +201,12 @@ void World::Update(int dt) { for (Entity &entity : entities) { entity.Update(dt); } + for (Entity &entity : entities) { + if (entity.WorldCollidable() && Intersection(entity)) { + // entity collides with the world + std::cout << entity.Name() << " entity intersects world" << std::endl; + } + } chunks.Rebase(player->ChunkCoords()); chunks.Update(dt); } diff --git a/src/world/World.hpp b/src/world/World.hpp index ae70494..7f38942 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -21,7 +21,7 @@ class World { public: struct Config { // initial player position - glm::vec3 spawn = { 4.0f, 4.0f, 4.0f }; + glm::vec3 spawn = { 0.0f, 0.0f, 0.0f }; // direction facing towards(!) the light glm::vec3 light_direction = { -1.0f, -3.0f, -2.0f }; // fade out reaches 1/e (0.3679) at 1/fog_density, @@ -39,10 +39,12 @@ public: bool Intersection( const Ray &, const glm::mat4 &M, - Chunk **chunk = nullptr, - int *blkid = nullptr, - float *dist = nullptr, - glm::vec3 *normal = nullptr); + Chunk *&chunk, + int &blkid, + float &dist, + glm::vec3 &normal); + + bool Intersection(const Entity &e); BlockTypeRegistry &BlockTypes() { return blockType; } diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index c114526..2216617 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -481,6 +481,30 @@ bool Chunk::Intersection( } } +bool Chunk::Intersection( + const AABB &box, + const glm::mat4 &Mbox, + const glm::mat4 &Mchunk +) const noexcept { + if (!blank::Intersection(box, Mbox, Bounds(), Mchunk)) { + return false; + } + for (int idx = 0, z = 0; z < depth; ++z) { + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x, ++idx) { + const BlockType &type = Type(idx); + if (!type.visible) { + continue; + } + if (type.shape->Intersects(Mchunk * ToTransform(Pos(x, y, z), idx), box, Mbox)) { + return true; + } + } + } + } + return false; +} + namespace {