map.cpp
mapgen.cpp
mesh.cpp
- mesh_gen_thread.cpp
+ mesh_gen_mgr.cpp
render_engine.cpp
scene.cpp
server.cpp
-#include <iostream>
-#include <stdexcept>
#include "block_def.hpp"
using namespace std;
void Camera::update(double yaw, double pitch)
{
yaw = radians(yaw);
- pitch = radians(clamp(pitch, -89.0, 89.0));
+ pitch = radians(pitch);
m_front = normalize(vec3(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));
m_right = normalize(cross(m_front, m_world_up));
#include "chunk.hpp"
#include "cube.hpp"
#include "face_dir.hpp"
+#include "log.hpp"
#include "map.hpp"
#include "mesh.hpp"
#include "texture.hpp"
{
try {
return getBlock(pos);
- } catch (std::out_of_range &) {
+ } catch (out_of_range &) {
return nullptr;
}
}
{
try {
setBlock(pos, block);
- } catch (std::out_of_range &) {
+ } catch (out_of_range &) {
+ }
+}
+
+void Chunk::addMeshUpdateTask()
+{
+ mesh_gen_mgr->addTask(this);
+}
+
+void Chunk::addMeshUpdateTaskWithEdge()
+{
+ addMeshUpdateTask();
+ for (int i = 0; i < 6; i++) {
+ if (Chunk *neighbor = map->getChunk(pos + face_dir[i])) {
+ neighbor->addMeshUpdateTask();
+ }
}
}
void Chunk::updateMesh()
{
- std::vector<GLfloat> vertices;
- std::vector<Texture> textures;
+ log(string("Update Chunk Mesh at ") + to_string(pos.x) + " " + to_string(pos.y) + " " + to_string(pos.z));
+
+ if (mesh_created && ! effect_finished)
+ return;
+
+ bool mesh_created_before = mesh_created;
+ mesh_created = true;
+
+ vector<GLfloat> vertices;
+ vector<Texture> textures;
+ bool any_drawable_block = false;
for (int x = 0; x < SIZE; x++) {
for (int y = 0; y < SIZE; y++) {
BlockDef *def = block->getDef();
if (! def->drawable)
continue;
- vec3 pos(x, y, z);
- vec3 pos_from_mesh_origin = pos - vec3(SIZE / 2 + 0.5);
+ ivec3 bpos(x, y, z);
+ vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5);
for (int facenr = 0; facenr < 6; facenr++) {
- const Block *neighbor = map->getBlockRelativePos(this, pos + (vec3)face_dir[facenr]);
- if (neighbor && ! neighbor->getDef()->drawable) {
+ ivec3 npos = bpos + face_dir[facenr];
+ const Block *neighbor_own, *neighbor;
+ neighbor_own = neighbor = getBlockNoEx(npos);
+ if (! neighbor)
+ neighbor = map->getBlock(pos * SIZE + npos);
+ if (neighbor && ! neighbor->getDef()->drawable)
+ any_drawable_block = true;
+ if (! mesh_created_before)
+ neighbor = neighbor_own;
+ if (! mesh_created_before && ! neighbor || neighbor && ! neighbor->getDef()->drawable) {
textures.push_back(def->tiles[facenr]);
for (int vertex_index = 0; vertex_index < 6; vertex_index++) {
for (int attribute_index = 0; attribute_index < 5; attribute_index++) {
}
}
}
-
- bool is_new = ! deleteMesh();
- if (textures.size() == 0) {
+ if (! any_drawable_block) {
+ if (! mesh_created_before) {
+ afterEffect();
+ } else if (mesh) {
+ mesh->reset();
+ }
return;
}
-
- mesh = new Mesh(scene);
+
+ if (! mesh) {
+ mesh = new Mesh(scene);
+ } else {
+ mesh->reset();
+ }
mesh->pos = pos * SIZE + SIZE / 2;
- mesh->size = vec3(1.0);
- mesh->configureVertexObjects(&vertices[0], vertices.size() * sizeof(GLfloat));
+ mesh->vertexConfig(&vertices[0], vertices.size() * sizeof(GLfloat));
mesh->textures = textures;
mesh->vertices_per_texture = 6;
- if (is_new)
- mesh->effect = Mesh::Effect::Type::FLYIN;
+ if (! mesh_created_before) {
+ mesh->effect = Mesh::Effect(Mesh::Effect::Type::FLYIN, Chunk::staticAfterEffect, this);
+ }
mesh->addToScene();
}
-void Chunk::addMeshUpdateTask()
+Chunk::Chunk(Map *m, const glm::ivec3 &p, const Data &d, MeshGenMgr *mgt, Scene *s) : map(m), data(d), pos(p), mesh_gen_mgr(mgt), scene(s)
{
- mesh_gen_thread->addTask(this);
+ addMeshUpdateTask();
}
-bool Chunk::deleteMesh()
+Chunk::~Chunk()
{
if (mesh) {
mesh->removeFromScene();
delete mesh;
- mesh = nullptr;
- return true;
}
- return false;
}
-Chunk::Chunk(Map *m, const glm::ivec3 &p, const Data &d, MeshGenThread *mgt, Scene *s) : map(m), data(d), pos(p), mesh_gen_thread(mgt), scene(s)
+void Chunk::staticAfterEffect(void *chunk)
{
- addMeshUpdateTask();
+ if (chunk) {
+ ((Chunk *)chunk)->afterEffect();
+ }
}
-Chunk::~Chunk()
+void Chunk::afterEffect()
{
- deleteMesh();
+ effect_finished = true;
+ addMeshUpdateTaskWithEdge();
}
#include "block.hpp"
#include "gl.hpp"
-#include "mesh_gen_thread.hpp"
+#include "mesh_gen_mgr.hpp"
#define DRAGONBLOCKS_CHUNK_SIZE 16
class Mesh;
class Scene;
- class Chunk : public MeshGenThread::MeshGenerator
+ class Chunk : public MeshGenMgr::MeshGenerator
{
public:
static void checkPos(const glm::ivec3 &);
void setBlock(const glm::ivec3 &, const Block &);
void setBlockNoEx(const glm::ivec3 &, const Block &);
void addMeshUpdateTask();
+ void addMeshUpdateTaskWithEdge();
void updateMesh();
- Chunk(Map *, const glm::ivec3 &, const Data &, MeshGenThread *, Scene *);
+ Chunk(Map *, const glm::ivec3 &, const Data &, MeshGenMgr *, Scene *);
~Chunk();
private:
+ static void staticAfterEffect(void *);
+
Map *map;
Mesh *mesh = nullptr;
- MeshGenThread *mesh_gen_thread;
+ MeshGenMgr *mesh_gen_mgr;
Scene *scene;
Data data;
+ bool effect_finished = false;
+ bool mesh_created = false;
- bool deleteMesh();
+ void afterEffect();
+ void deleteMesh();
};
};
Texture::bilinear_filter = false;
Texture::initArgs();
- render_engine = RenderEngine::create();
+ render_engine = new RenderEngine;
render_engine->window->setSize(1250, 750);
render_engine->window->setPos(0, 0);
mapgen = new Mapgen;
- map = new Map(mapgen, render_engine->mesh_gen_thread, render_engine->scene);
+ map = new Map(mapgen, render_engine->mesh_gen_mgr, render_engine->scene);
game = new Game(mapgen);
-
+
log("Initialisation complete.");
}
+
+void Client::start()
+{
+ render_engine->mesh_gen_mgr->start();
+ render_engine->loop();
+}
Mapgen *mapgen;
RenderEngine *render_engine;
+ void start();
+
Client();
~Client();
};
{
gametype = Gametype::CLIENT;
client = new Client();
- client->render_engine->loop();
+ client->start();
}
extern "C" void _dragonblocks_start_server()
{
gametype = Gametype::SERVER;
server = new Server();
+ server->start();
}
extern "C" void _dragonblocks_start_mainmenu()
{
gametype = Gametype::MAINMENU;
mainmenu = new Mainmenu();
+ mainmenu->start();
}
-#include <iostream>
#include <string>
#include "gldebug.hpp"
+#include "log.hpp"
using namespace std;
+using namespace dragonblocks;
-GLenum glCheckError_(const char *file, int line)
+GLenum dragonblocks::checkGLError(const char *file, int line)
{
GLenum errorCode;
if ((errorCode = glGetError()) != GL_NO_ERROR)
case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
}
- cout << error << " | " << file << " (" << line << ")" << endl;
+ log(string("OpenGL Error: ") + error + " | " + file + " (" + ")");
}
return errorCode;
}
#include "gl.hpp"
-#define glCheckError() glCheckError_(__FILE__, __LINE__)
-#define CHECKERR glCheckError();
-
-GLenum glCheckError_(const char *file, int line);
+#define CHECKERR dragonblocks::checkGLError(__FILE__, __LINE__);
+namespace dragonblocks
+{
+ GLenum checkGLError(const char *file, int line);
+}
void InputHandler::processKeyInput(double dtime)
{
- map<int, bool> keysDown;
+ set<int> keysDown;
for (auto it = listened_keys.begin(); it != listened_keys.end(); it++) {
- if (window->wasKeyDown(it->first)) {
- keysDown[it->first] = true;
+ int key = *it;
+ if (window->wasKeyDown(key)) {
+ keysDown.insert(key);
}
}
onKeyPress(dtime, keysDown);
{
yaw += x;
pitch -= y;
+ pitch = clamp(pitch, -89.0, 89.0);
camera->update(yaw, pitch);
}
-void InputHandler::onKeyPress(double dtime, map<int, bool> keysDown)
+void InputHandler::onKeyPress(double dtime, set<int> keys)
{
vec3 vel = vec3(speed * dtime);
vec3 front = camera->front(), right = camera->right(), up = camera->up();
front = normalize(vec3(front.x, 0, front.z));
up = normalize(vec3(0, up.y, 0));
}
- if (keysDown[GLFW_KEY_W]) {
+ if (keys.find(GLFW_KEY_W) != keys.end()) {
camera->pos += vel * front;
- } else if (keysDown[GLFW_KEY_S]) {
+ } else if (keys.find(GLFW_KEY_S) != keys.end()) {
camera->pos -= vel * front;
}
- if (keysDown[GLFW_KEY_D]) {
+ if (keys.find(GLFW_KEY_D) != keys.end()) {
camera->pos += vel * right;
- } else if (keysDown[GLFW_KEY_A]) {
+ } else if (keys.find(GLFW_KEY_A) != keys.end()) {
camera->pos -= vel * right;
}
- if (keysDown[GLFW_KEY_SPACE]) {
+ if (keys.find(GLFW_KEY_SPACE) != keys.end()) {
camera->pos += vel * up;
- } else if (keysDown[GLFW_KEY_LEFT_SHIFT]) {
+ } else if (keys.find(GLFW_KEY_LEFT_SHIFT) != keys.end()) {
camera->pos -= vel * up;
}
}
void InputHandler::listenFor(int key)
{
- listened_keys[key] = true;
+ listened_keys.insert(key);
}
void InputHandler::dontListenFor(int key)
#pragma once
-#include <map>
+#include <set>
#include "gl.hpp"
namespace dragonblocks
void processMouseInput(double);
void processKeyInput(double);
void onMouseMove(double, double, double);
- void onKeyPress(double, std::map<int, bool>);
+ void onKeyPress(double, std::set<int>);
void listenFor(int);
void dontListenFor(int);
private:
Camera *camera;
Window *window;
- std::map<int, bool> listened_keys;
+ std::set<int> listened_keys;
};
}
using namespace dragonblocks;
-Mainmenu::Mainmenu()
+void Mainmenu::start()
{
log("Main Menu is not available yet.");
}
class Mainmenu
{
public:
- Mainmenu();
+ void start();
};
}
#include <stdexcept>
-#include "face_dir.hpp"
#include "map.hpp"
#include "mapgen.hpp"
ivec3 Map::getChunkPos(const vec3 &p)
{
- return floor(p / 16.0F);
+ return floor(p / (float)DRAGONBLOCKS_CHUNK_SIZE);
}
ivec3 Map::getBlockPos(const ivec3 &p)
{
- return ((p % 16) + ivec3(16)) % 16;
+ return ((p % DRAGONBLOCKS_CHUNK_SIZE) + ivec3(DRAGONBLOCKS_CHUNK_SIZE)) % DRAGONBLOCKS_CHUNK_SIZE;
}
uint16_t Map::getChunkPosHash(const ivec3 &p)
{
- return (uint16_t)p.x + (uint16_t)p.y * 1000 + (uint16_t)p.z * 1000000;
+ return (uint16_t)p.x + (uint16_t)p.y * DRAGONBLOCKS_MAP_SIZE + (uint16_t)p.z * DRAGONBLOCKS_MAP_SIZE * DRAGONBLOCKS_MAP_SIZE;
}
const Block *Map::getBlock(const glm::ivec3 &p)
return nullptr;
}
-const Block *Map::getBlockRelativePos(Chunk *chunk, const glm::ivec3 &p)
-{
- const Block *b = nullptr;
- try {
- b = chunk->getBlock(p);
- } catch (std::out_of_range &) {
- b = getBlock(chunk->pos * 16 + p);
- }
- return b;
-}
-
void Map::setBlock(const glm::ivec3 &p, BlockDef *def)
{
Chunk *chunk = getChunk(Map::getChunkPos(p));
if (chunks[poshash])
return;
- chunks[poshash] = new Chunk(this, p, data, mesh_gen_thread, scene);
-
- for (int i = 0; i < 6; i++) {
- if (Chunk *neighbor = getChunk(p + face_dir[i]))
- neighbor->addMeshUpdateTask();
- }
+ chunks[poshash] = new Chunk(this, p, data, mesh_gen_mgr, scene);
}
void Map::createChunk(const glm::ivec3 &p)
chunks.clear();
}
-Map::Map(Mapgen *m, MeshGenThread *mgt, Scene *s) : mapgen(m), mesh_gen_thread(mgt), scene(s)
+Map::Map(Mapgen *m, MeshGenMgr *mgt, Scene *s) : mapgen(m), mesh_gen_mgr(mgt), scene(s)
{
}
class BlockDef;
class Block;
class Mapgen;
- class MeshGenThread;
+ class MeshGenMgr;
class Scene;
class Map
Chunk *getChunk(const glm::ivec3 &);
void clear();
- Map(Mapgen *, MeshGenThread *, Scene *);
+ Map(Mapgen *, MeshGenMgr *, Scene *);
~Map();
private:
std::map<uint16_t, Chunk*> chunks;
Mapgen *mapgen;
- MeshGenThread *mesh_gen_thread;
+ MeshGenMgr *mesh_gen_mgr;
Scene *scene;
};
}
+#include <stdexcept>
+#include <cstdlib>
+#include <cstring>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/constants.hpp>
#include "gldebug.hpp"
using namespace glm;
using namespace dragonblocks;
-double Mesh::Effect::grow_time = 0.5; // s
-double Mesh::Effect::flyin_time = 0.5; // s
+double Mesh::Effect::grow_time = 0.25; // s
+double Mesh::Effect::flyin_time = 0.4; // s
double Mesh::Effect::flyin_offset = 20; // m
double Mesh::Effect::rotate_speed = 1; // turns/s
-mat4 Mesh::Effect::getModelMatrix(double dtime, vec3 pos, vec3 size, vec3 rotation_axis, float rotation_angle, void *extra_data)
+mat4 Mesh::Effect::getModelMatrix(double dtime, vec3 pos, vec3 size, vec3 rotation_axis, float rotation_angle)
{
mat4 trans = mat4(1.0);
return trans;
}
-Mesh::Effect::Effect(Mesh::Effect::Type t, void (*callback)(void *))
+Mesh::Effect::Effect(Mesh::Effect::Type t, void (*o)(void *), void *e) : type(t), on_finish(o), extra_data(e)
{
- type = t;
- on_finish = callback;
switch(type) {
case Mesh::Effect::Type::FLYIN:
expires = true;
}
}
-void Mesh::configureVertexObjects(const GLvoid *vertices, GLsizeiptr vertices_size)
+void Mesh::vertexConfig(const GLvoid *v, GLsizei s)
{
- glGenVertexArrays(1, &VAO); CHECKERR
- glGenBuffers(1, &VBO); CHECKERR
-
- glBindVertexArray(VAO); CHECKERR
- glBindBuffer(GL_ARRAY_BUFFER, VBO); CHECKERR
-
- glBufferData(GL_ARRAY_BUFFER, vertices_size, vertices, GL_STATIC_DRAW); CHECKERR
-
- GLsizei stride = 5 * sizeof(GLfloat); CHECKERR
-
- glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, (GLvoid *)(0 * sizeof(GLfloat))); CHECKERR
- glEnableVertexAttribArray(0); CHECKERR
- glVertexAttribPointer(1, 2, GL_FLOAT, false, stride, (GLvoid *)(3 * sizeof(GLfloat))); CHECKERR
- glEnableVertexAttribArray(1); CHECKERR
-
- glBindBuffer(GL_ARRAY_BUFFER, 0); CHECKERR
- glBindVertexArray(0); CHECKERR
+ if (vertices_changed || configured)
+ throw runtime_error("Attempt to configure Mesh that is already configured");
+ vertices = malloc(s);
+ memcpy(vertices, v, s);
+ vertices_size = s;
+ vertices_changed = true;
}
void Mesh::render(double dtime, ShaderProgram *shader_program)
{
+ if (vertices_changed) {
+ runVertexConfig();
+ }
+
+ if (! configured)
+ return;
+
shader_program->use(); CHECKERR
- mat4 model_matrix = effect.getModelMatrix(dtime, pos, size, rotation_axis, rotation_angle, extra_data); CHECKERR
+ mat4 model_matrix = effect.getModelMatrix(dtime, pos, size, rotation_axis, rotation_angle); CHECKERR
shader_program->set("model", model_matrix); CHECKERR
glBindTexture(GL_TEXTURE_2D, 0); CHECKERR
}
+void Mesh::reset()
+{
+ removeFromScene();
+ pos = vec3(0.0);
+ size = vec3(1.0);
+ rotation_axis = vec3(0.0, 1.0, 0.0);
+ vertices_per_texture = 0;
+ textures = {};
+ rotation_angle = 0;
+ if (VAO) {
+ glDeleteVertexArrays(1, &VAO); CHECKERR
+ }
+ if (VBO) {
+ glDeleteBuffers(1, &VAO); CHECKERR
+ }
+ vertices_changed = false;
+ if (vertices) {
+ free(vertices);
+ }
+ vertices = NULL;
+ configured = false;
+}
+
void Mesh::addToScene()
{
scene->add(this);
scene->remove(this);
}
-Mesh::Mesh(Scene *s): pos(0.0), size(1.0), rotation_axis(0.0, 1.0, 0.0), scene(s)
+Mesh::Mesh(Scene *s): scene(s)
{
+ reset();
+}
+
+void Mesh::runVertexConfig()
+{
+ if (! vertices || vertices_size == 0)
+ throw runtime_error("Invalid Mesh configuration");
+
+ glGenVertexArrays(1, &VAO); CHECKERR
+ glGenBuffers(1, &VBO); CHECKERR
+
+ glBindVertexArray(VAO); CHECKERR
+ glBindBuffer(GL_ARRAY_BUFFER, VBO); CHECKERR
+
+ glBufferData(GL_ARRAY_BUFFER, vertices_size, vertices, GL_STATIC_DRAW); CHECKERR
+
+ GLsizei stride = 5 * sizeof(GLfloat); CHECKERR
+
+ glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, (GLvoid *)(0 * sizeof(GLfloat))); CHECKERR
+ glEnableVertexAttribArray(0); CHECKERR
+ glVertexAttribPointer(1, 2, GL_FLOAT, false, stride, (GLvoid *)(3 * sizeof(GLfloat))); CHECKERR
+ glEnableVertexAttribArray(1); CHECKERR
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0); CHECKERR
+ glBindVertexArray(0); CHECKERR
+
+ free(vertices);
+ vertices = NULL;
+ vertices_changed = false;
+ configured = true;
}
ROTATE
};
- glm::mat4 getModelMatrix(double, glm::vec3, glm::vec3, glm::vec3, float, void *);
+ glm::mat4 getModelMatrix(double, glm::vec3, glm::vec3, glm::vec3, float);
Effect() = default;
- Effect(Type, void (*)(void *) = nullptr);
+ Effect(Type, void (*)(void *) = nullptr, void * = nullptr);
Effect(const Effect &) = default;
private:
Type type = Type::NONE;
double time_left;
- void (*on_finish)(void *) = nullptr;
+ void (*on_finish)(void *);
+ void *extra_data;
bool expires;
};
int vertices_per_texture;
glm::vec3 pos, size, rotation_axis;
- float rotation_angle = 0;
- std::vector<Texture> textures;
- void *extra_data = nullptr;
+ float rotation_angle;
+ std::vector<Texture> textures;
Effect effect;
- void configureVertexObjects(const GLvoid *, GLsizeiptr);
+ void reset();
+ void vertexConfig(const GLvoid *v, GLsizei s);
void render(double dtime, ShaderProgram *);
void addToScene();
void removeFromScene();
-
+ void runVertexConfig();
+
Mesh(Scene *);
private:
- GLuint VAO, VBO;
+ GLuint VAO = 0, VBO = 0;
Scene *scene;
+ GLvoid *vertices = NULL;
+ GLsizeiptr vertices_size;
+ bool configured;
+ bool vertices_changed;
+
};
}
--- /dev/null
+#include <set>
+#include "mesh_gen_mgr.hpp"
+#include "window.hpp"
+
+using namespace std;
+using namespace dragonblocks;
+
+void MeshGenMgr::MeshGenerator::updateMesh()
+{
+}
+
+void MeshGenMgr::addTask(MeshGenMgr::MeshGenerator *gen)
+{
+ queued_jobs.push(gen);
+}
+
+void MeshGenMgr::step()
+{
+ if (! runJob()) {
+ generateJobList();
+ }
+}
+
+void MeshGenMgr::run()
+{
+ while (true) {
+ step();
+ }
+}
+
+void MeshGenMgr::generateJobList()
+{
+ set<MeshGenMgr::MeshGenerator *> active_jobs_set;
+ while (! queued_jobs.empty()) {
+ MeshGenMgr::MeshGenerator *gen = queued_jobs.front();
+ queued_jobs.pop();
+ if (active_jobs_set.find(gen) == active_jobs_set.end()) {
+ active_jobs_set.insert(gen);
+ active_jobs.push(gen);
+ }
+ }
+}
+
+
+bool MeshGenMgr::runJob()
+{
+ if (active_jobs.empty())
+ return false;
+ MeshGenMgr::MeshGenerator *gen = active_jobs.front();
+ active_jobs.pop();
+ if (gen) {
+ gen->updateMesh();
+ }
+ return true;
+}
+
+void MeshGenMgr::start()
+{
+ mesh_gen_thread = thread(&MeshGenMgr::run, this);
+}
--- /dev/null
+#pragma once
+
+#include <thread>
+#include <queue>
+
+namespace dragonblocks
+{
+ class Window;
+
+ class MeshGenMgr : public std::thread
+ {
+ public:
+ class MeshGenerator
+ {
+ public:
+ virtual void updateMesh();
+ };
+
+ void addTask(MeshGenerator *);
+ void step();
+ void run();
+ void start();
+
+ private:
+ void generateJobList();
+ bool runJob();
+
+ std::queue<MeshGenerator *> queued_jobs;
+ std::queue<MeshGenerator *> active_jobs;
+ std::thread mesh_gen_thread;
+ };
+}
+++ /dev/null
-#include "mesh_gen_thread.hpp"
-
-using namespace std;
-using namespace dragonblocks;
-
-void MeshGenThread::MeshGenerator::updateMesh()
-{
-}
-
-void MeshGenThread::addTask(MeshGenThread::MeshGenerator *gen)
-{
- queued_jobs[gen] = true;
-}
-
-void MeshGenThread::step()
-{
- if (! runJob()) {
- generateJobList();
- }
-}
-
-void MeshGenThread::generateJobList()
-{
- for (auto it = queued_jobs.begin(); it != queued_jobs.end(); it++) {
- active_jobs.push_back(it->first);
- }
- queued_jobs.clear();
-}
-
-
-bool MeshGenThread::runJob()
-{
- int s = active_jobs.size();
- if (s == 0)
- return false;
- MeshGenThread::MeshGenerator *gen = active_jobs[s - 1];
- active_jobs.pop_back();
- if (gen) {
- gen->updateMesh();
- }
- return true;
-}
-
+++ /dev/null
-#pragma once
-
-#include <map>
-#include <vector>
-
-namespace dragonblocks
-{
- class MeshGenThread // TODO: extend std::thread or something
- {
- public:
- class MeshGenerator
- {
- public:
- virtual void updateMesh();
- };
-
- void addTask(MeshGenerator *);
- void step();
-
- private:
- void generateJobList();
- bool runJob();
-
- std::map<MeshGenerator *, bool> queued_jobs; // This sucks i should use std::queue instead but i need to somehow make sure that a task isnt in there twice
- std::vector<MeshGenerator *> active_jobs;
-
- };
-}
#include "gldebug.hpp"
#include "input_handler.hpp"
#include "map.hpp" // this one three
-#include "mesh_gen_thread.hpp"
+#include "mesh_gen_mgr.hpp"
#include "render_engine.hpp"
#include "scene.hpp"
#include "shader_program.hpp"
using namespace glm;
using namespace dragonblocks;
-RenderEngine *RenderEngine::singleton = nullptr;
-
-RenderEngine *RenderEngine::create()
-{
- if (singleton)
- throw runtime_error("RenderEngine already exists");
- return singleton = new RenderEngine;
-}
-
void RenderEngine::render()
{
double dtime = glfwGetTime() - last_time;
{
while (! window->shouldClose()) {
render();
- mesh_gen_thread->step();
loadChunks();
}
}
updateProjectionMatrix();
}
-RenderEngine::~RenderEngine()
-{
- delete window;
- delete camera;
- delete input_handler;
- delete mesh_gen_thread;
- delete scene;
- delete shader_program;
-}
-
RenderEngine::RenderEngine()
{
if (! glfwInit())
window = Window::create(this);
camera = new Camera;
input_handler = new InputHandler(camera, window);
- mesh_gen_thread = new MeshGenThread;
+ mesh_gen_mgr = new MeshGenMgr;
scene = new Scene;
GLenum glew_init_err = glewInit();
last_time = glfwGetTime();
}
+
+RenderEngine::~RenderEngine()
+{
+ delete window;
+ delete camera;
+ delete input_handler;
+ delete mesh_gen_mgr;
+ delete scene;
+ delete shader_program;
+}
{
class Camera;
class InputHandler;
- class MeshGenThread;
+ class MeshGenMgr;
class ShaderProgram;
class Scene;
class Window;
class RenderEngine
{
public:
- static RenderEngine *create();
-
Camera *camera;
InputHandler *input_handler;
- MeshGenThread *mesh_gen_thread;
+ MeshGenMgr *mesh_gen_mgr;
Scene *scene;
ShaderProgram *shader_program;
Window *window;
void setRenderDistance(double);
void setFov(double);
+ RenderEngine();
~RenderEngine();
- private:
- static RenderEngine *singleton;
-
+ private:
double last_time;
double render_distance;
double fov;
-
- RenderEngine();
};
}
void Scene::add(Mesh *m)
{
- list[m] = true;
+ meshes.insert(m);
}
void Scene::remove(Mesh *m)
{
- list.erase(m);
+ meshes.erase(m);
}
void Scene::render(double dtime, ShaderProgram *shader_program)
{
- for (auto it = list.begin(); it != list.end(); it++) {
- it->first->render(dtime, shader_program);
+ auto renderlist = meshes;
+ for (auto it = renderlist.begin(); it != renderlist.end(); it++) {
+ Mesh *mesh = *it;
+ mesh->render(dtime, shader_program);
}
}
void Scene::clear()
{
- list.clear();
+ meshes.clear();
}
Scene::~Scene()
#pragma once
-#include <map>
+#include <set>
namespace dragonblocks
{
void remove(Mesh *);
void render(double, ShaderProgram *);
void clear();
+ void run();
~Scene();
private:
- std::map<Mesh *, bool> list;
+ std::set<Mesh *> meshes;
};
}
using namespace dragonblocks;
-Server::Server()
+void Server::start()
{
log("Server is not available yet.");
}
class Server
{
public:
- Server();
+ void start();
};
}
#include <stdexcept>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
+#include "gldebug.hpp"
#include "log.hpp"
#include "texture.hpp"
void Texture::bind() const
{
- glBindTexture(GL_TEXTURE_2D, id);
+ glBindTexture(GL_TEXTURE_2D, id); CHECKERR
}
void Texture::load(const string &path)
unsigned char *data = stbi_load(path.c_str(), &width, &height, &nrChannels, 0);
if (! data)
throw runtime_error("Failed to load texture " + path);
- glGenTextures(1, &id);
+ glGenTextures(1, &id); CHECKERR
bind();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Texture::min_filter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Texture::mag_filter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Texture::min_filter); CHECKERR
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Texture::mag_filter); CHECKERR
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); CHECKERR
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECKERR
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); CHECKERR
if (Texture::mipmap)
- glGenerateMipmap(GL_TEXTURE_2D);
+ glGenerateMipmap(GL_TEXTURE_2D); CHECKERR
stbi_image_free(data);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D, 0); CHECKERR
log("Loaded texture " + path);
}
return glfwGetKey(id, key) == GLFW_PRESS;
}
+void Window::makeContextCurrent() const
+{
+ glfwMakeContextCurrent(id);
+}
+
ivec2 Window::getSize() const
{
return ivec2(width, height);
glfwTerminate();
throw runtime_error("Failed to create GLFW window");
}
- glfwMakeContextCurrent(id);
+ makeContextCurrent();
glfwSetInputMode(id, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetWindowPosCallback(id, Window::windowPosCallback);
glfwSetFramebufferSizeCallback(id, Window::framebufferSizeCallback);
void swapBuffers();
bool shouldClose() const;
bool wasKeyDown(int) const;
+ void makeContextCurrent() const;
glm::ivec2 getSize() const;
glm::ivec2 getCursorPos() const;
glm::ivec2 getCursorDelta();