X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld.cpp;h=c24450cdb154e93d460cb4405146f8d3d8d08096;hb=5700ea3c08ea5e4a5c743f0413b65dc8eebfd220;hp=96b48ee120d96ee4e79bec833936fb7ae310c2e8;hpb=ac8765b510707d77cac9620778f40ddf3a4ad2a2;p=blank.git diff --git a/src/world.cpp b/src/world.cpp index 96b48ee..c24450c 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,5 +1,8 @@ #include "world.hpp" +#include +#include + namespace blank { @@ -74,10 +77,27 @@ int BlockTypeRegistry::Add(const BlockType &t) { Chunk::Chunk() : blocks(Size()) , model() +, transform(1.0f) , dirty(false) { } +Chunk::Chunk(Chunk &&other) +: blocks(std::move(other.blocks)) +, model(std::move(other.model)) +, transform(other.transform) +, dirty(other.dirty) { + +} + +Chunk &Chunk::operator =(Chunk &&other) { + blocks = std::move(other.blocks); + model = std::move(other.model); + transform = other.transform; + dirty = other.dirty; + return *this; +} + void Chunk::Draw() { if (dirty) { @@ -87,6 +107,70 @@ void Chunk::Draw() { } +bool Chunk::Intersection( + const Ray &ray, + const glm::mat4 &M, + int *blkid, + float *dist, + glm::vec3 *normal) const { + { // rough check + const AABB bb{{0, 0, 0}, {Width(), Height(), Depth()}}; + if (!blank::Intersection(ray, bb, M)) { + return false; + } + } + + if (!blkid && !dist && !normal) { + return true; + } + + // TODO: should be possible to heavily optimize this + int id = 0; + int closest_id = -1; + float closest_dist = std::numeric_limits::infinity(); + glm::vec3 closest_normal(0, 1, 0); + for (int z = 0; z < Depth(); ++z) { + for (int y = 0; y < Height(); ++y) { + for (int x = 0; x < Width(); ++x, ++id) { + if (!blocks[id].type->visible) { + continue; + } + const AABB bb{{x, y, z}, {x+1, y+1, z+1}}; + float cur_dist; + glm::vec3 cur_norm; + if (blank::Intersection(ray, bb, M, &cur_dist, &cur_norm)) { + if (cur_dist < closest_dist) { + closest_id = id; + closest_dist = cur_dist; + closest_normal = cur_norm; + } + } + } + } + } + + if (closest_id < 0) { + return false; + } + + if (blkid) { + *blkid = closest_id; + } + if (dist) { + *dist = closest_dist; + } + if (normal) { + *normal = closest_normal; + } + return true; +} + +void Chunk::Position(const glm::vec3 &pos) { + position = pos; + transform = glm::translate(pos * Extent()); +} + + int Chunk::VertexCount() const { // TODO: query blocks as soon as type shapes are implemented return Size() * 6 * 6; @@ -106,4 +190,101 @@ void Chunk::Update() { dirty = false; } + +World::World() +: blockType() +, chunks() { + blockType.Add(BlockType(true, glm::vec3(1, 1, 1))); + blockType.Add(BlockType(true, glm::vec3(1, 0, 0))); + blockType.Add(BlockType(true, glm::vec3(0, 1, 0))); + blockType.Add(BlockType(true, glm::vec3(0, 0, 1))); +} + + +void World::Generate() { + for (int z = -1; z < 2; ++z) { + for (int y = -1; y < 2; ++y) { + for (int x = -1; x < 2; ++x) { + Generate(glm::vec3(x, y, z)); + } + } + } +} + +Chunk &World::Generate(const glm::vec3 &pos) { + chunks.emplace_back(); + Chunk &chunk = chunks.back(); + chunk.Position(pos); + chunk.BlockAt(glm::vec3(0, 0, 0)) = Block(blockType[4]); + chunk.BlockAt(glm::vec3(0, 0, 1)) = Block(blockType[1]); + chunk.BlockAt(glm::vec3(1, 0, 0)) = Block(blockType[2]); + chunk.BlockAt(glm::vec3(1, 0, 1)) = Block(blockType[3]); + chunk.BlockAt(glm::vec3(2, 0, 0)) = Block(blockType[4]); + chunk.BlockAt(glm::vec3(2, 0, 1)) = Block(blockType[1]); + chunk.BlockAt(glm::vec3(3, 0, 0)) = Block(blockType[2]); + chunk.BlockAt(glm::vec3(3, 0, 1)) = Block(blockType[3]); + chunk.BlockAt(glm::vec3(2, 0, 2)) = Block(blockType[4]); + chunk.BlockAt(glm::vec3(2, 0, 3)) = Block(blockType[1]); + chunk.BlockAt(glm::vec3(3, 0, 2)) = Block(blockType[2]); + chunk.BlockAt(glm::vec3(3, 0, 3)) = Block(blockType[3]); + chunk.BlockAt(glm::vec3(1, 1, 0)) = Block(blockType[1]); + chunk.BlockAt(glm::vec3(1, 1, 1)) = Block(blockType[4]); + chunk.BlockAt(glm::vec3(2, 1, 1)) = Block(blockType[3]); + chunk.BlockAt(glm::vec3(2, 2, 1)) = Block(blockType[2]); + chunk.Invalidate(); + return chunk; +} + +bool World::Intersection( + const Ray &ray, + const glm::mat4 &M, + Chunk **chunk, + int *blkid, + float *dist, + glm::vec3 *normal) { + Chunk *closest_chunk = nullptr; + int closest_blkid = -1; + float closest_dist = std::numeric_limits::infinity(); + glm::vec3 closest_normal; + + for (Chunk &cur_chunk : chunks) { + int cur_blkid; + float cur_dist; + glm::vec3 cur_normal; + if (cur_chunk.Intersection(ray, M * cur_chunk.Transform(), &cur_blkid, &cur_dist, &cur_normal)) { + if (cur_dist < closest_dist) { + closest_chunk = &cur_chunk; + closest_blkid = cur_blkid; + closest_dist = cur_dist; + closest_normal = cur_normal; + } + } + } + + if (chunk) { + *chunk = closest_chunk; + } + if (blkid) { + *blkid = closest_blkid; + } + if (dist) { + *dist = closest_dist; + } + if (normal) { + *normal = closest_normal; + } + return closest_chunk; +} + + +Chunk &World::Next(const Chunk &to, const glm::vec3 &dir) { + const glm::vec3 tgt_pos = to.Position() + dir; + for (Chunk &chunk : chunks) { + if (chunk.Position() == tgt_pos) { + return chunk; + } + } + return Generate(tgt_pos); +} + }