From 482114e156e91729f2529ea6bb1fe98dacdee97f Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Thu, 19 Feb 2015 20:34:09 +0100 Subject: [PATCH] very basic chunk model --- src/app.cpp | 141 ++++++-------------------------------------------- src/app.hpp | 7 +-- src/init.cpp | 9 ++++ src/init.hpp | 3 ++ src/model.cpp | 44 +++++++++++----- src/model.hpp | 36 ++++++++----- src/world.cpp | 102 ++++++++++++++++++++++++++++++++++++ src/world.hpp | 91 ++++++++++++++++++++++++++++++++ 8 files changed, 281 insertions(+), 152 deletions(-) create mode 100644 src/world.cpp create mode 100644 src/world.hpp diff --git a/src/app.cpp b/src/app.cpp index e7ed579..8c957a7 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -17,126 +17,12 @@ Application::Application() , move_velocity(0.003f) , pitch_sensitivity(-0.0025f) , yaw_sensitivity(-0.001f) +, testBlockType(true) , cam() -, model({ - // vertices - { 0.0f, 0.0f, 1.0f }, // front, red - { 1.0f, 0.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, // back, cyan - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, // top, green - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, // bottom, magenta - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, // left, blue - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 0.0f, 0.0f }, // right, yellow - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f }, -}, { - // colors - { 1.0f, 0.0f, 0.0f }, // front, red - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 1.0f }, // back, cyan - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 0.0f }, // top, green - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 1.0f }, // bottom, magenta - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, // left, blue - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 1.0f, 1.0f, 0.0f }, // right, yellow - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, -}, { - // normals - { 0.0f, 0.0f, 1.0f }, // front, red - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, -1.0f }, // back, cyan - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 1.0f, 0.0f }, // top, green - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, // bottom, magenta - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, // left, blue - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, // right, yellow - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, -}) -, modelCtrl() -, light_position(5.0f, 5.0f, 5.0f) +, chunk() +, light_position(17.0f, 17.0f, 17.0f) , light_color(1.0f, 1.0f, 1.0f) -, light_power(50.0f) +, light_power(100.0f) , m_handle(0) , v_handle(0) , mv_handle(0) @@ -152,6 +38,7 @@ Application::Application() , up(false) , down(false) { GLContext::EnableVSync(); + GLContext::EnableDepthTest(); GLContext::EnableBackfaceCulling(); program.LoadShader( GL_VERTEX_SHADER, @@ -218,8 +105,15 @@ Application::Application() glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); - modelCtrl.Position(glm::vec3(0, 0, -4)); - cam.Position(glm::vec3(0, 0, 4)); + cam.Position(glm::vec3(0, 4, 4)); + + chunk.BlockAt(glm::vec3(0, 0, 0)) = Block(&testBlockType); + chunk.BlockAt(glm::vec3(1, 0, 0)) = Block(&testBlockType); + chunk.BlockAt(glm::vec3(1, 1, 0)) = Block(&testBlockType); + chunk.BlockAt(glm::vec3(1, 1, 1)) = Block(&testBlockType); + chunk.BlockAt(glm::vec3(2, 1, 1)) = Block(&testBlockType); + chunk.BlockAt(glm::vec3(2, 2, 1)) = Block(&testBlockType); + chunk.Invalidate(); m_handle = program.UniformLocation("M"); v_handle = program.UniformLocation("V"); @@ -325,15 +219,14 @@ void Application::Update(int dt) { cam.OrientationVelocity(vel); cam.Update(dt); - modelCtrl.Update(dt); } void Application::Render() { - glClear(GL_COLOR_BUFFER_BIT); + GLContext::Clear(); program.Use(); - glm::mat4 m(modelCtrl.Transform()); + glm::mat4 m(1.0f); glm::mat4 mv(cam.View() * m); glm::mat4 mvp(cam.MakeMVP(m)); glUniformMatrix4fv(m_handle, 1, GL_FALSE, &m[0][0]); @@ -344,7 +237,7 @@ void Application::Render() { glUniform3f(light_color_handle, light_color.x, light_color.y, light_color.z); glUniform1f(light_power_handle, light_power); - model.Draw(); + chunk.Draw(); window.Flip(); } diff --git a/src/app.hpp b/src/app.hpp index f3ee141..d9b7046 100644 --- a/src/app.hpp +++ b/src/app.hpp @@ -7,8 +7,8 @@ #include "camera.hpp" #include "controller.hpp" #include "init.hpp" -#include "model.hpp" #include "shader.hpp" +#include "world.hpp" namespace blank { @@ -42,9 +42,10 @@ private: float pitch_sensitivity; float yaw_sensitivity; + BlockType testBlockType; + Camera cam; - Model model; - FPSController modelCtrl; + Chunk chunk; glm::vec3 light_position; glm::vec3 light_color; diff --git a/src/init.cpp b/src/init.cpp index 40f76de..9e73c28 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -142,10 +142,19 @@ void GLContext::EnableVSync() { } } +void GLContext::EnableDepthTest() { + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); +} + void GLContext::EnableBackfaceCulling() { glEnable(GL_CULL_FACE); } +void GLContext::Clear() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + InitGLEW::InitGLEW() { glewExperimental = GL_TRUE; diff --git a/src/init.hpp b/src/init.hpp index 51ab3f8..d596cbc 100644 --- a/src/init.hpp +++ b/src/init.hpp @@ -83,8 +83,11 @@ public: GLContext &operator =(const GLContext &) = delete; static void EnableVSync(); + static void EnableDepthTest(); static void EnableBackfaceCulling(); + static void Clear(); + private: SDL_GLContext handle; diff --git a/src/model.cpp b/src/model.cpp index bbfc97f..032fc15 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -3,17 +3,35 @@ namespace blank { -Model::Model( - std::vector &&vtx, - std::vector &&col, - std::vector &&norm -) -: vertices(vtx) -, colors(col) -, normals(norm) -, handle{} { +Model::Model() +: vertices() +, colors() +, normals() +, handle{} +, dirty(false) { glGenBuffers(ATTRIB_COUNT, handle); +} + +Model::~Model() { + glDeleteBuffers(ATTRIB_COUNT, handle); +} + + +void Model::Clear() { + vertices.clear(); + colors.clear(); + normals.clear(); + Invalidate(); +} +void Model::Reserve(int s) { + vertices.reserve(s); + colors.reserve(s); + normals.reserve(s); +} + + +void Model::Update() { glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW); @@ -22,14 +40,16 @@ Model::Model( glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_NORMAL]); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), GL_STATIC_DRAW); -} -Model::~Model() { - glDeleteBuffers(ATTRIB_COUNT, handle); + dirty = false; } void Model::Draw() { + if (dirty) { + Update(); + } + glEnableVertexAttribArray(ATTRIB_VERTEX); glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); glVertexAttribPointer( diff --git a/src/model.hpp b/src/model.hpp index 02ab3f2..1e9dab9 100644 --- a/src/model.hpp +++ b/src/model.hpp @@ -11,27 +11,37 @@ namespace blank { class Model { public: - enum Attribute { - ATTRIB_VERTEX, - ATTRIB_COLOR, - ATTRIB_NORMAL, - ATTRIB_COUNT, - }; + std::vector vertices; + std::vector colors; + std::vector normals; public: - explicit Model( - std::vector &&vertices, - std::vector &&colors, - std::vector &&normals); + Model(); ~Model(); + Model(const Model &) = delete; + Model &operator =(const Model &) = delete; + + void Invalidate() { dirty = true; } + + void Clear(); + void Reserve(int); + void Draw(); private: - std::vector vertices; - std::vector colors; - std::vector normals; + void Update(); + +private: + enum Attribute { + ATTRIB_VERTEX, + ATTRIB_COLOR, + ATTRIB_NORMAL, + ATTRIB_COUNT, + }; + GLuint handle[ATTRIB_COUNT]; + bool dirty; }; diff --git a/src/world.cpp b/src/world.cpp new file mode 100644 index 0000000..2dd7b30 --- /dev/null +++ b/src/world.cpp @@ -0,0 +1,102 @@ +#include "world.hpp" + + +namespace blank { + +const BlockType BlockType::DEFAULT; + +void BlockType::FillVBO( + const glm::vec3 &pos, + std::vector &vertices, + std::vector &colors, + std::vector &normals +) const { + vertices.emplace_back(pos.x , pos.y , pos.z + 1); // front + vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); + vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z + 1); + vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); + vertices.emplace_back(pos.x , pos.y , pos.z ); // back + vertices.emplace_back(pos.x , pos.y + 1, pos.z ); + vertices.emplace_back(pos.x + 1, pos.y , pos.z ); + vertices.emplace_back(pos.x + 1, pos.y , pos.z ); + vertices.emplace_back(pos.x , pos.y + 1, pos.z ); + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); + vertices.emplace_back(pos.x , pos.y + 1, pos.z ); // top + vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); + vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z + 1); + vertices.emplace_back(pos.x , pos.y , pos.z ); // bottom + vertices.emplace_back(pos.x + 1, pos.y , pos.z ); + vertices.emplace_back(pos.x , pos.y , pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y , pos.z ); + vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); + vertices.emplace_back(pos.x , pos.y , pos.z + 1); + vertices.emplace_back(pos.x , pos.y , pos.z ); // left + vertices.emplace_back(pos.x , pos.y , pos.z + 1); + vertices.emplace_back(pos.x , pos.y + 1, pos.z ); + vertices.emplace_back(pos.x , pos.y + 1, pos.z ); + vertices.emplace_back(pos.x , pos.y , pos.z + 1); + vertices.emplace_back(pos.x , pos.y + 1, pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y , pos.z ); // right + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); + vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y , pos.z + 1); + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z ); + vertices.emplace_back(pos.x + 1, pos.y + 1, pos.z + 1); + + colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // front + colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // back + colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // top + colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // bottom + colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // left + colors.insert(colors.end(), 6, glm::vec3(1.0f, 1.0f, 1.0f)); // right + + normals.insert(normals.end(), 6, glm::vec3( 0.0f, 0.0f, 1.0f)); // front + normals.insert(normals.end(), 6, glm::vec3( 0.0f, 0.0f, -1.0f)); // back + normals.insert(normals.end(), 6, glm::vec3( 0.0f, 1.0f, 0.0f)); // top + normals.insert(normals.end(), 6, glm::vec3( 0.0f, -1.0f, 0.0f)); // bottom + normals.insert(normals.end(), 6, glm::vec3(-1.0f, 0.0f, 0.0f)); // left + normals.insert(normals.end(), 6, glm::vec3( 1.0f, 0.0f, 0.0f)); // right +} + + +Chunk::Chunk() +: blocks(Size()) +, model() +, dirty(false) { + +} + + +void Chunk::Draw() { + if (dirty) { + Update(); + } + model.Draw(); +} + + +int Chunk::VertexCount() const { + // TODO: query blocks as soon as type shapes are implemented + return Size() * 6 * 6; +} + +void Chunk::Update() { + model.Clear(); + model.Reserve(VertexCount()); + + for (int i = 0; i < Size(); ++i) { + if (blocks[i].type->visible) { + blocks[i].type->FillModel(ToCoords(i), model); + } + } + + model.Invalidate(); + dirty = false; +} + +} diff --git a/src/world.hpp b/src/world.hpp new file mode 100644 index 0000000..304c63a --- /dev/null +++ b/src/world.hpp @@ -0,0 +1,91 @@ +#ifndef BLANK_WORLD_HPP_ +#define BLANK_WORLD_HPP_ + +#include "model.hpp" + +#include +#include +#include + + +namespace blank { + +/// attributes of a type of block +struct BlockType { + + bool visible; + + constexpr explicit BlockType(bool v = false) + : visible(v) { } + + static const BlockType DEFAULT; + + + 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); + } + +}; + + +/// 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(); + + static constexpr int Width() { return 16; } + static constexpr int Height() { return 16; } + static constexpr int Depth() { return 16; } + static constexpr int Size() { return Width() * Height() * Depth(); } + + static constexpr int ToIndex(const glm::vec3 &pos) { + return pos.x + pos.y * Width() + pos.z * Width() * Height(); + } + static glm::vec3 ToCoords(int idx) { + return glm::vec3( + idx % Width(), + (idx / Width()) % Height(), + idx / (Width() * Height()) + ); + } + + void Invalidate() { dirty = true; } + + Block &BlockAt(const glm::vec3 &pos) { return blocks[ToIndex(pos)]; } + const Block &BlockAt(const glm::vec3 &pos) const { return blocks[ToIndex(pos)]; } + + void Draw(); + +private: + int VertexCount() const; + void Update(); + +private: + std::vector blocks; + Model model; + bool dirty; + +}; + +} + +#endif -- 2.39.2