]> git.localhorst.tv Git - blank.git/blobdiff - src/world.cpp
separate build directory for intermediates
[blank.git] / src / world.cpp
index c958a65cf3144942f8d47af09576872fd48aae9c..2ac65abf696164405406c8f238bcf1d7cbd6efe6 100644 (file)
@@ -1,6 +1,7 @@
 #include "world.hpp"
 
 #include <limits>
+#include <glm/gtx/transform.hpp>
 
 
 namespace blank {
@@ -60,6 +61,27 @@ void BlockType::FillVBO(
        normals.insert(normals.end(), 6, glm::vec3( 1.0f,  0.0f,  0.0f)); // right
 }
 
+void BlockType::FillOutlineVBO(
+       std::vector<glm::vec3> &vertices,
+       std::vector<glm::vec3> &colors
+) const {
+       vertices = std::vector<glm::vec3>({
+               { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f },
+               { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 0.0f },
+               { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f },
+               { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 0.0f },
+               { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f },
+               { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 1.0f },
+               { 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f },
+               { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 1.0f },
+               { 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 1.0f },
+               { 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f },
+               { 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 1.0f },
+               { 0.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f },
+       });
+       colors.resize(24, outline_color);
+}
+
 
 BlockTypeRegistry::BlockTypeRegistry() {
        Add(BlockType::DEFAULT);
@@ -76,10 +98,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 +128,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 +141,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 +149,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<float>::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 +158,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 +180,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 +211,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<float>::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);
+}
+
 }