, 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)
, up(false)
, down(false) {
GLContext::EnableVSync();
+ GLContext::EnableDepthTest();
GLContext::EnableBackfaceCulling();
program.LoadShader(
GL_VERTEX_SHADER,
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");
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]);
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();
}
#include "camera.hpp"
#include "controller.hpp"
#include "init.hpp"
-#include "model.hpp"
#include "shader.hpp"
+#include "world.hpp"
namespace blank {
float pitch_sensitivity;
float yaw_sensitivity;
+ BlockType testBlockType;
+
Camera cam;
- Model model;
- FPSController modelCtrl;
+ Chunk chunk;
glm::vec3 light_position;
glm::vec3 light_color;
}
}
+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;
GLContext &operator =(const GLContext &) = delete;
static void EnableVSync();
+ static void EnableDepthTest();
static void EnableBackfaceCulling();
+ static void Clear();
+
private:
SDL_GLContext handle;
namespace blank {
-Model::Model(
- std::vector<glm::vec3> &&vtx,
- std::vector<glm::vec3> &&col,
- std::vector<glm::vec3> &&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);
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(
class Model {
public:
- enum Attribute {
- ATTRIB_VERTEX,
- ATTRIB_COLOR,
- ATTRIB_NORMAL,
- ATTRIB_COUNT,
- };
+ std::vector<glm::vec3> vertices;
+ std::vector<glm::vec3> colors;
+ std::vector<glm::vec3> normals;
public:
- explicit Model(
- std::vector<glm::vec3> &&vertices,
- std::vector<glm::vec3> &&colors,
- std::vector<glm::vec3> &&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<glm::vec3> vertices;
- std::vector<glm::vec3> colors;
- std::vector<glm::vec3> normals;
+ void Update();
+
+private:
+ enum Attribute {
+ ATTRIB_VERTEX,
+ ATTRIB_COLOR,
+ ATTRIB_NORMAL,
+ ATTRIB_COUNT,
+ };
+
GLuint handle[ATTRIB_COUNT];
+ bool dirty;
};
--- /dev/null
+#include "world.hpp"
+
+
+namespace blank {
+
+const BlockType BlockType::DEFAULT;
+
+void BlockType::FillVBO(
+ const glm::vec3 &pos,
+ std::vector<glm::vec3> &vertices,
+ std::vector<glm::vec3> &colors,
+ std::vector<glm::vec3> &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;
+}
+
+}
--- /dev/null
+#ifndef BLANK_WORLD_HPP_
+#define BLANK_WORLD_HPP_
+
+#include "model.hpp"
+
+#include <vector>
+#include <GL/glew.h>
+#include <glm/glm.hpp>
+
+
+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<glm::vec3> &vertices,
+ std::vector<glm::vec3> &colors,
+ std::vector<glm::vec3> &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<Block> blocks;
+ Model model;
+ bool dirty;
+
+};
+
+}
+
+#endif