X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld.cpp;h=c24450cdb154e93d460cb4405146f8d3d8d08096;hb=5700ea3c08ea5e4a5c743f0413b65dc8eebfd220;hp=c958a65cf3144942f8d47af09576872fd48aae9c;hpb=4d0ef1687987a0801469c7262f81efd36636605a;p=blank.git diff --git a/src/world.cpp b/src/world.cpp index c958a65..c24450c 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,6 +1,7 @@ #include "world.hpp" #include +#include namespace blank { @@ -76,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) { @@ -89,7 +107,12 @@ void Chunk::Draw() { } -bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float *dist) const { +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)) { @@ -97,7 +120,7 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float * } } - if (!blkid && !dist) { + if (!blkid && !dist && !normal) { return true; } @@ -105,6 +128,7 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float * 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) { @@ -113,10 +137,12 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float * } const AABB bb{{x, y, z}, {x+1, y+1, z+1}}; float cur_dist; - if (blank::Intersection(ray, bb, M, &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; } } } @@ -133,9 +159,17 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float * 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 @@ -156,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); +} + }