X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2FWorld.cpp;h=d51520ef5b2828c1d22902e1e00902bccb504884;hb=955fbb45dedb570520fc45d2ce69f420bed2ad08;hp=82701ce8686f48f20b3f24039a1239547375671f;hpb=c04ea5a6f67d446ea29aa2e88dc4c666956d7732;p=blank.git diff --git a/src/world/World.cpp b/src/world/World.cpp index 82701ce..d51520e 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -1,10 +1,12 @@ #include "World.hpp" +#include "WorldCollision.hpp" #include "../graphics/BlockLighting.hpp" #include "../graphics/DirectionalLighting.hpp" #include #include +#include #include @@ -28,18 +30,24 @@ World::World(const Config &config) { // white block BlockType type(true, { 1.0f, 1.0f, 1.0f }, &blockShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = block_fill; blockType.Add(type); } { // white slab BlockType type(true, { 1.0f, 1.0f, 1.0f }, &slabShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = slab_fill; blockType.Add(type); } { // white stair BlockType type(true, { 1.0f, 1.0f, 1.0f }, &stairShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = stair_fill; blockType.Add(type); } @@ -47,18 +55,24 @@ World::World(const Config &config) { // red block BlockType type(true, { 1.0f, 0.0f, 0.0f }, &blockShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = block_fill; blockType.Add(type); } { // red slab BlockType type(true, { 1.0f, 0.0f, 0.0f }, &slabShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = slab_fill; blockType.Add(type); } { // red stair BlockType type(true, { 1.0f, 0.0f, 0.0f }, &stairShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = stair_fill; blockType.Add(type); } @@ -66,18 +80,24 @@ World::World(const Config &config) { // green block BlockType type(true, { 0.0f, 1.0f, 0.0f }, &blockShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = block_fill; blockType.Add(type); } { // green slab BlockType type(true, { 0.0f, 1.0f, 0.0f }, &slabShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = slab_fill; blockType.Add(type); } { // green stair BlockType type(true, { 0.0f, 1.0f, 0.0f }, &stairShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = stair_fill; blockType.Add(type); } @@ -85,18 +105,24 @@ World::World(const Config &config) { // blue block BlockType type(true, { 0.0f, 0.0f, 1.0f }, &blockShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = block_fill; blockType.Add(type); } { // blue slab BlockType type(true, { 0.0f, 0.0f, 1.0f }, &slabShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = slab_fill; blockType.Add(type); } { // blue stair BlockType type(true, { 0.0f, 0.0f, 1.0f }, &stairShape); type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = stair_fill; blockType.Add(type); } @@ -105,6 +131,8 @@ World::World(const Config &config) BlockType type(true, { 1.0f, 1.0f, 0.0f }, &blockShape); type.luminosity = 15; type.block_light = true; + type.collision = true; + type.collide_block = true; type.fill = block_fill; blockType.Add(type); } @@ -175,15 +203,18 @@ bool World::Intersection( return chunk; } -bool World::Intersection(const Entity &e) { +bool World::Intersection(const Entity &e, std::vector &col) { AABB box = e.Bounds(); glm::mat4 M = e.Transform(player->ChunkCoords()); + bool any = false; + // TODO: this only needs to check the chunks surrounding the entity's chunk position + // need find out if that is quicker than the rough chunk bounds test for (Chunk &cur_chunk : chunks.Loaded()) { - if (cur_chunk.Intersection(box, M, cur_chunk.Transform(player->ChunkCoords()))) { - return true; + if (cur_chunk.Intersection(box, M, cur_chunk.Transform(player->ChunkCoords()), col)) { + any = true; } } - return false; + return any; } @@ -197,20 +228,59 @@ Chunk &World::Next(const Chunk &to, const glm::tvec3 &dir) { } +namespace { + +std::vector col; + +} + void World::Update(int dt) { for (Entity &entity : entities) { entity.Update(dt); } for (Entity &entity : entities) { - if (entity.WorldCollidable() && Intersection(entity)) { + col.clear(); + if (entity.WorldCollidable() && Intersection(entity, col)) { // entity collides with the world - std::cout << entity.Name() << " entity intersects world" << std::endl; + Resolve(entity, col); } } chunks.Rebase(player->ChunkCoords()); chunks.Update(dt); } +void World::Resolve(Entity &e, std::vector &col) { + // determine displacement for each cardinal axis and move entity accordingly + glm::vec3 min_disp(0.0f); + glm::vec3 max_disp(0.0f); + for (const WorldCollision &c : col) { + if (!c.Blocks()) continue; + glm::vec3 local_disp(c.normal * c.depth); + // swap if neccessary (normal may point away from the entity) + if (dot(c.normal, e.Position() - c.BlockCoords()) < 0) { + local_disp *= -1; + } + min_disp = min(min_disp, local_disp); + max_disp = max(max_disp, local_disp); + } + // for each axis + // if only one direction is set, use that as the final + // if both directions are set, use average + glm::vec3 final_disp(0.0f); + for (int axis = 0; axis < 3; ++axis) { + if (std::abs(min_disp[axis]) > std::numeric_limits::epsilon()) { + if (std::abs(max_disp[axis]) > std::numeric_limits::epsilon()) { + final_disp[axis] = (min_disp[axis] + max_disp[axis]) * 0.5f; + } else { + final_disp[axis] = min_disp[axis]; + } + } else if (std::abs(max_disp[axis]) > std::numeric_limits::epsilon()) { + final_disp[axis] = max_disp[axis]; + } + } + e.Move(final_disp); +} + void World::Render(BlockLighting &chunk_prog, DirectionalLighting &entity_prog) { chunk_prog.Activate();