From: Daniel Karbach Date: Sun, 8 Mar 2015 21:52:01 +0000 (+0100) Subject: split world file X-Git-Url: http://git.localhorst.tv/?a=commitdiff_plain;h=804bde3fc09e4317eef629861638a68bfad3e343;p=blank.git split world file --- diff --git a/src/block.cpp b/src/block.cpp new file mode 100644 index 0000000..02e8476 --- /dev/null +++ b/src/block.cpp @@ -0,0 +1,40 @@ +#include "block.hpp" + + +namespace blank { + +const BlockType BlockType::DEFAULT; +const NullShape BlockType::DEFAULT_SHAPE; + +void BlockType::FillVBO( + const glm::vec3 &pos, + std::vector &vertices, + std::vector &colors, + std::vector &normals +) const { + shape->Vertices(vertices, pos); + colors.insert(colors.end(), shape->VertexCount(), color); + shape->Normals(normals); +} + +void BlockType::FillOutlineVBO( + std::vector &vertices, + std::vector &colors +) const { + shape->Outline(vertices); + colors.insert(colors.end(), shape->OutlineCount(), outline_color); +} + + +BlockTypeRegistry::BlockTypeRegistry() { + Add(BlockType::DEFAULT); +} + +int BlockTypeRegistry::Add(const BlockType &t) { + int id = types.size(); + types.push_back(t); + types.back().id = id; + return id; +} + +} diff --git a/src/block.hpp b/src/block.hpp new file mode 100644 index 0000000..1fa9c84 --- /dev/null +++ b/src/block.hpp @@ -0,0 +1,93 @@ +#ifndef BLANK_BLOCK_HPP_ +#define BLANK_BLOCK_HPP_ + +#include "geometry.hpp" +#include "model.hpp" +#include "shape.hpp" + +#include +#include + + +namespace blank { + +/// attributes of a type of block +struct BlockType { + + int id; + + bool visible; + + const Shape *shape; + glm::vec3 color; + glm::vec3 outline_color; + + explicit BlockType( + bool v = false, + const glm::vec3 &color = { 1, 1, 1 }, + const Shape *shape = &DEFAULT_SHAPE, + const glm::vec3 &outline_color = { -1, -1, -1 }) + : id(-1), visible(v), shape(shape), color(color), outline_color(outline_color) { } + + static const BlockType DEFAULT; + static const NullShape DEFAULT_SHAPE; + + + void FillVBO( + const glm::vec3 &pos, + std::vector &vertices, + std::vector &colors, + std::vector &normals + ) const; + + void FillModel(const glm::vec3 &pos, Model &m) const { + FillVBO(pos, m.vertices, m.colors, m.normals); + m.Invalidate(); + } + + + void FillOutlineVBO( + std::vector &vertices, + std::vector &colors + ) const; + + void FillOutlineModel(OutlineModel &m) const { + FillOutlineVBO(m.vertices, m.colors); + m.Invalidate(); + } + +}; + + +class BlockTypeRegistry { + +public: + BlockTypeRegistry(); + +public: + int Add(const BlockType &); + + size_t Size() const { return types.size(); } + + BlockType *operator [](int id) { return &types[id]; } + const BlockType *Get(int id) const { return &types[id]; } + +private: + std::vector types; + +}; + + +/// single 1x1x1 cube +struct Block { + + const BlockType *type; + + constexpr explicit Block(const BlockType *t = &BlockType::DEFAULT) + : type(t) { } + +}; + +} + +#endif diff --git a/src/chunk.cpp b/src/chunk.cpp new file mode 100644 index 0000000..e928a21 --- /dev/null +++ b/src/chunk.cpp @@ -0,0 +1,127 @@ +#include "chunk.hpp" + +#include +#include + + +namespace blank { + +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) { + Update(); + } + model.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; + } + float cur_dist; + glm::vec3 cur_norm; + glm::vec3 pos(float(x) + 0.5f, float(y) + 0.5f, float(z) + 0.5f); + if (blocks[id].type->shape->Intersects(ray, glm::translate(M, pos), 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 { + int count = 0; + for (const auto &block : blocks) { + count += block.type->shape->VertexCount(); + } + return count; +} + +void Chunk::Update() { + model.Clear(); + model.Reserve(VertexCount()); + + for (size_t i = 0; i < Size(); ++i) { + blocks[i].type->FillModel(ToCoords(i), model); + } + + model.Invalidate(); + dirty = false; +} + + +} diff --git a/src/chunk.hpp b/src/chunk.hpp new file mode 100644 index 0000000..9d2f319 --- /dev/null +++ b/src/chunk.hpp @@ -0,0 +1,84 @@ +#ifndef BLANK_CHUNK_HPP_ +#define BLANK_CHUNK_HPP_ + +#include "block.hpp" +#include "geometry.hpp" +#include "model.hpp" + +#include +#include + + +namespace blank { + +/// cube of size 16 (256 tiles, 4096 blocks) +class Chunk { + +public: + Chunk(); + + Chunk(Chunk &&); + Chunk &operator =(Chunk &&); + + static constexpr int Width() { return 16; } + static constexpr int Height() { return 16; } + static constexpr int Depth() { return 16; } + static glm::vec3 Extent() { return glm::vec3(Width(), Height(), Depth()); } + static constexpr int Size() { return Width() * Height() * Depth(); } + + static constexpr bool InBounds(const glm::vec3 &pos) { + return + pos.x >= 0 && pos.x < Width() && + pos.y >= 0 && pos.y < Height() && + pos.z >= 0 && pos.z < Depth(); + } + static constexpr int ToIndex(const glm::vec3 &pos) { + return int(pos.x) + int(pos.y) * Width() + int(pos.z) * Width() * Height(); + } + static constexpr bool InBounds(int idx) { + return idx >= 0 && idx < Size(); + } + static glm::vec3 ToCoords(int idx) { + return glm::vec3( + 0.5f + idx % Width(), + 0.5f + (idx / Width()) % Height(), + 0.5f + idx / (Width() * Height()) + ); + } + + void Invalidate() { dirty = true; } + + Block &BlockAt(int index) { return blocks[index]; } + const Block &BlockAt(int index) const { return blocks[index]; } + Block &BlockAt(const glm::vec3 &pos) { return BlockAt(ToIndex(pos)); } + const Block &BlockAt(const glm::vec3 &pos) const { return BlockAt(ToIndex(pos)); } + + bool Intersection( + const Ray &, + const glm::mat4 &M, + int *blkid = nullptr, + float *dist = nullptr, + glm::vec3 *normal = nullptr) const; + + void Position(const glm::vec3 &); + const glm::vec3 &Position() const { return position; } + const glm::mat4 &Transform() const { return transform; } + + void Draw(); + +private: + int VertexCount() const; + void Update(); + +private: + std::vector blocks; + Model model; + glm::vec3 position; + glm::mat4 transform; + bool dirty; + +}; + +} + +#endif diff --git a/src/world.cpp b/src/world.cpp index cca483d..d115378 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -6,159 +6,6 @@ namespace blank { -const BlockType BlockType::DEFAULT; -const NullShape BlockType::DEFAULT_SHAPE; - -void BlockType::FillVBO( - const glm::vec3 &pos, - std::vector &vertices, - std::vector &colors, - std::vector &normals -) const { - shape->Vertices(vertices, pos); - colors.insert(colors.end(), shape->VertexCount(), color); - shape->Normals(normals); -} - -void BlockType::FillOutlineVBO( - std::vector &vertices, - std::vector &colors -) const { - shape->Outline(vertices); - colors.insert(colors.end(), shape->OutlineCount(), outline_color); -} - - -BlockTypeRegistry::BlockTypeRegistry() { - Add(BlockType::DEFAULT); -} - -int BlockTypeRegistry::Add(const BlockType &t) { - int id = types.size(); - types.push_back(t); - types.back().id = id; - return id; -} - - -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) { - Update(); - } - model.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; - } - float cur_dist; - glm::vec3 cur_norm; - glm::vec3 pos(float(x) + 0.5f, float(y) + 0.5f, float(z) + 0.5f); - if (blocks[id].type->shape->Intersects(ray, glm::translate(M, pos), 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 { - int count = 0; - for (const auto &block : blocks) { - count += block.type->shape->VertexCount(); - } - return count; -} - -void Chunk::Update() { - model.Clear(); - model.Reserve(VertexCount()); - - for (size_t i = 0; i < Size(); ++i) { - blocks[i].type->FillModel(ToCoords(i), model); - } - - model.Invalidate(); - dirty = false; -} - - World::World() : blockType() , blockShape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }}) diff --git a/src/world.hpp b/src/world.hpp index 6f63915..60ec6f4 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -1,168 +1,19 @@ #ifndef BLANK_WORLD_HPP_ #define BLANK_WORLD_HPP_ +#include "block.hpp" +#include "chunk.hpp" #include "controller.hpp" -#include "geometry.hpp" -#include "model.hpp" #include "noise.hpp" #include "shader.hpp" #include "shape.hpp" #include -#include -#include #include namespace blank { -/// attributes of a type of block -struct BlockType { - - int id; - - bool visible; - - const Shape *shape; - glm::vec3 color; - glm::vec3 outline_color; - - explicit BlockType( - bool v = false, - const glm::vec3 &color = { 1, 1, 1 }, - const Shape *shape = &DEFAULT_SHAPE, - const glm::vec3 &outline_color = { -1, -1, -1 }) - : id(-1), visible(v), shape(shape), color(color), outline_color(outline_color) { } - - static const BlockType DEFAULT; - static const NullShape DEFAULT_SHAPE; - - - void FillVBO( - const glm::vec3 &pos, - std::vector &vertices, - std::vector &colors, - std::vector &normals - ) const; - - void FillModel(const glm::vec3 &pos, Model &m) const { - FillVBO(pos, m.vertices, m.colors, m.normals); - m.Invalidate(); - } - - - void FillOutlineVBO( - std::vector &vertices, - std::vector &colors - ) const; - - void FillOutlineModel(OutlineModel &m) const { - FillOutlineVBO(m.vertices, m.colors); - m.Invalidate(); - } - -}; - - -class BlockTypeRegistry { - -public: - BlockTypeRegistry(); - -public: - int Add(const BlockType &); - - size_t Size() const { return types.size(); } - - BlockType *operator [](int id) { return &types[id]; } - const BlockType *Get(int id) const { return &types[id]; } - -private: - std::vector types; - -}; - - -/// single 1x1x1 cube -struct Block { - - const BlockType *type; - - constexpr explicit Block(const BlockType *t = &BlockType::DEFAULT) - : type(t) { } - -}; - - -/// cube of size 16 (256 tiles, 4096 blocks) -class Chunk { - -public: - Chunk(); - - Chunk(Chunk &&); - Chunk &operator =(Chunk &&); - - static constexpr int Width() { return 16; } - static constexpr int Height() { return 16; } - static constexpr int Depth() { return 16; } - static glm::vec3 Extent() { return glm::vec3(Width(), Height(), Depth()); } - static constexpr int Size() { return Width() * Height() * Depth(); } - - static constexpr bool InBounds(const glm::vec3 &pos) { - return - pos.x >= 0 && pos.x < Width() && - pos.y >= 0 && pos.y < Height() && - pos.z >= 0 && pos.z < Depth(); - } - static constexpr int ToIndex(const glm::vec3 &pos) { - return int(pos.x) + int(pos.y) * Width() + int(pos.z) * Width() * Height(); - } - static constexpr bool InBounds(int idx) { - return idx >= 0 && idx < Size(); - } - static glm::vec3 ToCoords(int idx) { - return glm::vec3( - 0.5f + idx % Width(), - 0.5f + (idx / Width()) % Height(), - 0.5f + idx / (Width() * Height()) - ); - } - - void Invalidate() { dirty = true; } - - Block &BlockAt(int index) { return blocks[index]; } - const Block &BlockAt(int index) const { return blocks[index]; } - Block &BlockAt(const glm::vec3 &pos) { return BlockAt(ToIndex(pos)); } - const Block &BlockAt(const glm::vec3 &pos) const { return BlockAt(ToIndex(pos)); } - - bool Intersection( - const Ray &, - const glm::mat4 &M, - int *blkid = nullptr, - float *dist = nullptr, - glm::vec3 *normal = nullptr) const; - - void Position(const glm::vec3 &); - const glm::vec3 &Position() const { return position; } - const glm::mat4 &Transform() const { return transform; } - - void Draw(); - -private: - int VertexCount() const; - void Update(); - -private: - std::vector blocks; - Model model; - glm::vec3 position; - glm::mat4 transform; - bool dirty; - -}; - - class World { public: