From: Elias Fleckenstein Date: Wed, 3 Mar 2021 14:59:00 +0000 (+0100) Subject: New structure X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=061ecaebe1efa3d908a47f4f7bb7a665f8d0d456;p=dragonblocks3d.git New structure --- diff --git a/.gitignore b/.gitignore index d552926..d38d963 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,5 @@ compile_commands.json CTestTestfile.cmake _deps libdragonblocks.so -dragonblockslauncher +dragonblocks.bin oprofile_data/ diff --git a/CMakeLists.txt b/CMakeLists.txt index fb1894d..df2de30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,5 +6,43 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -add_subdirectory("${PROJECT_SOURCE_DIR}/src/dragonblocks/") -add_subdirectory("${PROJECT_SOURCE_DIR}/src/dragonblockslauncher/") +add_library(dragonblocks SHARED + src/animations.cpp + src/async_mgr.cpp + src/block.cpp + src/block_def.cpp + src/box_vertices.cpp + src/camera.cpp + src/chunk.cpp + src/client.cpp + src/entity.cpp + src/face_dir.cpp + src/game.cpp + src/gl.cpp + src/input_handler.cpp + src/local_entity.cpp + src/local_player.cpp + src/map.cpp + src/mapgen.cpp + src/mesh.cpp + src/render_engine.cpp + src/scene.cpp + src/shader_program.cpp + src/texture.cpp + src/tile_def.cpp + src/window.cpp +) + +target_link_libraries(dragonblocks + GL + GLEW + glfw +) + +target_include_directories(dragonblocks PUBLIC + "${PROJECT_SOURCE_DIR}/lib/" +) + +add_executable(dragonblocks.bin src/launcher/main.c) + +target_link_libraries(dragonblocks.bin dl) diff --git a/later_use/dynamiclibrary.cpp b/later_use/dynamiclibrary.cpp new file mode 100644 index 0000000..e450931 --- /dev/null +++ b/later_use/dynamiclibrary.cpp @@ -0,0 +1,26 @@ +// Just some code to use later when C++ Runtime Mods are introduced + +class DynamicLibrary +{ + public: + std::string filename; + std::string error; + bool success; + void *handle; + DynamicLibrary(std::string); +}; +DynamicLibrary *loadDynamicLibrary(std::string); + +DynamicLibrary::DynamicLibrary(std::string f) +{ + filename = f; + + handle = dlmopen(LM_ID_BASE, filename.c_str(), RTLD_NOW | RTLD_GLOBAL); + + if (handle) { + success = true; + } else { + error = dlerror(); + success = false; + } +} diff --git a/later_use/network_mgr.hpp b/later_use/network_mgr.hpp new file mode 100644 index 0000000..600b76b --- /dev/null +++ b/later_use/network_mgr.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include +#include "udp_socket.hpp" + +namespace dragonblocks +{ + class NetworkMgr + { + public: + class IPeer + { + public: + UDPSocket::Address *address; + NetworkMgr *network_mgr; + }; + + class INamespace + { + public: + virtual void handle(Packet *); + }; + + UDPSocket *socket; + std::queue out_queue; + std::set peers_set; + std::map
peers; + void sendPacket(Packet *); + void disconnectPeer(IPeer *); + std::map namespaces; + }; +} diff --git a/later_use/network_packet.hpp b/later_use/network_packet.hpp new file mode 100644 index 0000000..93e9fb6 --- /dev/null +++ b/later_use/network_packet.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace dragonblocks +{ + class Connection; + + class NetworkPacket + { + public: + enum Type + { + INVALID, + TOSERVER_HELLO, + TOCLIENT_HELLO, + TOSERVER_BYE, + TOCLIENT_BYE, + TYPE_COUNT, + }; + + std::stringstream content; + + NetworkPacket() = default; + NetworkPacket(const Type &); + NetworkPacket(const NetworkPacket &) = default; + + private: + Type type = INVALID; + }; +} diff --git a/later_use/peer.cpp b/later_use/peer.cpp new file mode 100644 index 0000000..9ea61d4 --- /dev/null +++ b/later_use/peer.cpp @@ -0,0 +1,13 @@ +#include +#include "connection.hpp" + +using namespace std; +using namespace dragonblocks; + +void Connection::setAddress(const string &addr) +{ + if(inet_pton(AF_INET, addr.c_str(), &address.sin_addr) <= 0) + throw runtime_error(string("Invalid address: ") + addr); +} + + diff --git a/later_use/peer.hpp b/later_use/peer.hpp new file mode 100644 index 0000000..5a148b9 --- /dev/null +++ b/later_use/peer.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include "network_packet.hpp" + +namespace dragonblocks +{ + std::queue in_packets; + std::queue out_packets; +} diff --git a/later_use/udp_socket.cpp b/later_use/udp_socket.cpp new file mode 100644 index 0000000..04ce87a --- /dev/null +++ b/later_use/udp_socket.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include "udp_socket.hpp" + +#define PACKSIZE DRAGONBLOCKS_UPD_SOCKET_PACKAGE_SIZE + +using namespace std; +using namespace dragonblocks; + +UDPSocket::Address::Address(const string &adr, int port) +{ + address.sin_family = AF_INET; + address.sin_port = htons(port); + inet_pton(AF_INET, adr.c_str(), &address.sin_addr); +} +void UDPSocket::connect() +{ + if (::connect(sockfd, (struct sockaddr *)&address.address, address.length) < 0) + throw runtime_error("Connection failed"); +} + +void UDPSocket::bind() +{ + if (::bind(sockfd, (struct sockaddr *)&address.address, address.length) < 0) + throw runtime_error("Bind failed"); +} + +void UDPSocket::close() +{ + ::close(sockfd); +} + +void UDPSocket::send(const std::string &str, Address *addr) +{ + if (! addr) { + addr = &address; + } + sendto(sockfd, str.c_str(), min((int)str.size(), PACKSIZE), MSG_CONFIRM, (struct sockaddr *)&addr->address, addr->length); +} + +string UDPSocket::recv(Address *addr) +{ + if (! addr) { + addr = &address; + } + char buffer[PACKSIZE + 1] = {0}; // include \0 at the end + recvfrom(sockfd, buffer, PACKSIZE, MSG_WAITALL, (struct sockaddr *)&addr->address, (socklen_t *)&addr->length); + return buffer; +} + +UDPSocket::UDPSocket(const string &adr, int port) : address(adr, port) +{ + sockfd = socket(AF_INET, SOCK_DGRAM, 0); +} diff --git a/later_use/udp_socket.hpp b/later_use/udp_socket.hpp new file mode 100644 index 0000000..3dec081 --- /dev/null +++ b/later_use/udp_socket.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#define DRAGONBLOCKS_UPD_SOCKET_PACKAGE_SIZE 1024 + +namespace dragonblocks +{ + class UDPSocket + { + public: + class Address + { + public: + struct sockaddr_in address; + int length; + + Address() = default; + Address(const std::string &, int); + }; + + void connect(); + void bind(); + void close(); + void send(const std::string &, Address * = nullptr); // server specifies address + std::string recv(Address * = nullptr); // server provides a buffer for the address + + UDPSocket(const std::string &, int); + + private: + int sockfd; + Address address; // for client, this is the address of the server; for server it is the own address. + }; +} diff --git a/shaders/vertex.glsl b/shaders/vertex.glsl index 28fc533..b418d98 100755 --- a/shaders/vertex.glsl +++ b/shaders/vertex.glsl @@ -16,3 +16,4 @@ void main() gl_Position = projection * cameraRelCoords; ourTexCoord = aTexCoord; } + diff --git a/src/animations.cpp b/src/animations.cpp new file mode 100644 index 0000000..14eeff1 --- /dev/null +++ b/src/animations.cpp @@ -0,0 +1,35 @@ +#include +#include "animations.hpp" + +using namespace glm; +using namespace dragonblocks; + +vec3 FlyInAnimation::getPos(vec3 pos) +{ + pos.y -= offset * time_left / last_for; + return pos; +} + +FlyInAnimation::FlyInAnimation(double l, double o, void (*on)(void *), void *e) : Mesh::IAnimation(l, on, e), last_for(l), offset(o) +{ +} + +vec3 GrowAnimation::getSize(vec3 size) +{ + size *= 1 - time_left / last_for; + return size; +} + +GrowAnimation::GrowAnimation(double l, void (*o)(void *), void *e) : Mesh::IAnimation(l, o, e), last_for(l) +{ +} + +float RotateAnimation::getRotationAngle(float rotation_angle) +{ + rotation_angle += glfwGetTime() * speed * pi() * 2; + return rotation_angle; +} + +RotateAnimation::RotateAnimation(double s) : speed(s) +{ +} diff --git a/src/animations.hpp b/src/animations.hpp new file mode 100644 index 0000000..642521b --- /dev/null +++ b/src/animations.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "gl.hpp" +#include "mesh.hpp" + +namespace dragonblocks +{ + class FlyInAnimation : public Mesh::IAnimation + { + public: + double last_for; + double offset; + + glm::vec3 getPos(glm::vec3); + + FlyInAnimation(double = 0.4, double = 20.0, void (*)(void *) = nullptr, void * = nullptr); + }; + + class GrowAnimation : public Mesh::IAnimation + { + public: + double last_for; + + glm::vec3 getSize(glm::vec3); + + GrowAnimation(double = 0.25, void (*)(void *) = nullptr, void * = nullptr); + }; + + class RotateAnimation : public Mesh::IAnimation + { + public: + double speed; + + float getRotationAngle(float); + + RotateAnimation(double = 1.0); + }; +} diff --git a/src/async_mgr.cpp b/src/async_mgr.cpp new file mode 100644 index 0000000..b72d0eb --- /dev/null +++ b/src/async_mgr.cpp @@ -0,0 +1,41 @@ +#include +#include +#include "async_mgr.hpp" + +using namespace std; +using namespace dragonblocks; + +void AsyncMgr::ITask::doAsyncTask() +{ +} + +void AsyncMgr::addTask(AsyncMgr::ITask *t) +{ + mtx.lock(); + queued_jobs.push_back(t); + mtx.unlock(); +} + +void AsyncMgr::run() +{ + while (true) { + set active_set; + mtx.lock(); + vector active = queued_jobs; + queued_jobs.clear(); + mtx.unlock(); + for (auto it = active.begin(); it != active.end(); it++) { + AsyncMgr::ITask *t = *it; + if (active_set.find(t) == active_set.end()) { + t->doAsyncTask(); + } + } + } +} + + + +void AsyncMgr::start() +{ + async_thread = thread(&AsyncMgr::run, this); +} diff --git a/src/async_mgr.hpp b/src/async_mgr.hpp new file mode 100644 index 0000000..a62be0d --- /dev/null +++ b/src/async_mgr.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include + +namespace dragonblocks +{ + class AsyncMgr : public std::thread + { + public: + class ITask + { + public: + virtual void doAsyncTask(); + }; + + void addTask(ITask *); + void run(); + void start(); + + private: + std::mutex mtx; + std::vector queued_jobs; + std::thread async_thread; + }; +} diff --git a/src/block.cpp b/src/block.cpp new file mode 100644 index 0000000..b226914 --- /dev/null +++ b/src/block.cpp @@ -0,0 +1,12 @@ +#include "block.hpp" + +using namespace dragonblocks; + +BlockDef *Block::getDef() const +{ + return def; +} + +Block::Block(BlockDef *d) : def(d) +{ +} diff --git a/src/block.hpp b/src/block.hpp new file mode 100644 index 0000000..6a4e1d5 --- /dev/null +++ b/src/block.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "gl.hpp" + +namespace dragonblocks +{ + class BlockDef; + class Block + { + public: + BlockDef *getDef() const; + + Block() = default; + Block(const Block &) = default; + Block(BlockDef *); + + private: + BlockDef *def = nullptr; + }; +} + diff --git a/src/block_def.cpp b/src/block_def.cpp new file mode 100644 index 0000000..a797320 --- /dev/null +++ b/src/block_def.cpp @@ -0,0 +1,15 @@ +#include "block_def.hpp" + +using namespace std; +using namespace dragonblocks; + +BlockDef::BlockDef(const string &n, const TileDef &t) : name(n), tile_def(t) +{ + if (tile_def.size() == 0) { + drawable = false; + } +} + +BlockDef::BlockDef(const string &n) : BlockDef(n, TileDef()) +{ +} diff --git a/src/block_def.hpp b/src/block_def.hpp new file mode 100644 index 0000000..140422d --- /dev/null +++ b/src/block_def.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include "gl.hpp" +#include "tile_def.hpp" + +namespace dragonblocks +{ + class BlockDef + { + public: + std::string name; + TileDef tile_def; + bool drawable = true; + + BlockDef(const std::string &); + BlockDef(const std::string &, const TileDef &); + }; +} diff --git a/src/box_vertices.cpp b/src/box_vertices.cpp new file mode 100644 index 0000000..1148614 --- /dev/null +++ b/src/box_vertices.cpp @@ -0,0 +1,46 @@ +#include "box_vertices.hpp" + +GLfloat dragonblocks::box_vertices[6][6][5] = { +// x y z s t + -0.5, -0.5, -0.5, +0.0, +0.0, + +0.5, -0.5, -0.5, +1.0, +0.0, + +0.5, +0.5, -0.5, +1.0, +1.0, + +0.5, +0.5, -0.5, +1.0, +1.0, + -0.5, +0.5, -0.5, +0.0, +1.0, + -0.5, -0.5, -0.5, +0.0, +0.0, + + -0.5, -0.5, +0.5, +0.0, +0.0, + +0.5, +0.5, +0.5, +1.0, +1.0, + +0.5, -0.5, +0.5, +1.0, +0.0, + +0.5, +0.5, +0.5, +1.0, +1.0, + -0.5, -0.5, +0.5, +0.0, +0.0, + -0.5, +0.5, +0.5, +0.0, +1.0, + + -0.5, +0.5, +0.5, +1.0, +1.0, + -0.5, -0.5, -0.5, +0.0, +0.0, + -0.5, +0.5, -0.5, +0.0, +1.0, + -0.5, -0.5, -0.5, +0.0, +0.0, + -0.5, +0.5, +0.5, +1.0, +1.0, + -0.5, -0.5, +0.5, +1.0, +0.0, + + +0.5, +0.5, +0.5, +1.0, +1.0, + +0.5, +0.5, -0.5, +0.0, +1.0, + +0.5, -0.5, -0.5, +0.0, +0.0, + +0.5, -0.5, -0.5, +0.0, +0.0, + +0.5, -0.5, +0.5, +1.0, +0.0, + +0.5, +0.5, +0.5, +1.0, +1.0, + + -0.5, -0.5, -0.5, +0.0, +1.0, + +0.5, -0.5, -0.5, +1.0, +1.0, + +0.5, -0.5, +0.5, +1.0, +0.0, + +0.5, -0.5, +0.5, +1.0, +0.0, + -0.5, -0.5, +0.5, +0.0, +0.0, + -0.5, -0.5, -0.5, +0.0, +1.0, + + -0.5, +0.5, -0.5, +0.0, +1.0, + +0.5, +0.5, -0.5, +1.0, +1.0, + +0.5, +0.5, +0.5, +1.0, +0.0, + +0.5, +0.5, +0.5, +1.0, +0.0, + -0.5, +0.5, +0.5, +0.0, +0.0, + -0.5, +0.5, -0.5, +0.0, +1.0, +}; diff --git a/src/box_vertices.hpp b/src/box_vertices.hpp new file mode 100644 index 0000000..7fa551b --- /dev/null +++ b/src/box_vertices.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "gl.hpp" + +namespace dragonblocks +{ + extern GLfloat box_vertices[6][6][5]; +} diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..71405e7 --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,55 @@ +#include +#include "camera.hpp" + +using namespace glm; +using namespace dragonblocks; + +mat4 Camera::getViewMatrix() const +{ + return lookAt(pos, pos + m_front, m_up); +} + +void Camera::toggleMode() +{ + m_third_person = ! m_third_person; +} + +void Camera::update(double yaw, double pitch, const vec3 &p) +{ + yaw = radians(yaw); + 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)); + m_up = normalize(cross(m_right, m_front)); + + pos = p; + + if (m_third_person) { + pos -= m_front * 2.0f; + } +} + +vec3 Camera::up() const +{ + return m_up; +} + +vec3 Camera::front() const +{ + return m_front; +} + +vec3 Camera::right() const +{ + return m_right; +} + +bool Camera::thirdPerson() const +{ + return m_third_person; +} + +Camera::Camera() : pos(0, 0, 0), m_up(0, 1, 0), m_world_up(0, 1, 0), m_front(0, 0, -1) +{ +} diff --git a/src/camera.hpp b/src/camera.hpp new file mode 100644 index 0000000..7e01840 --- /dev/null +++ b/src/camera.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "gl.hpp" + +namespace dragonblocks +{ + class Camera + { + public: + glm::mat4 getViewMatrix() const; + void toggleMode(); + void update(double, double, const glm::vec3 &); + glm::vec3 up() const; + glm::vec3 front() const; + glm::vec3 right() const; + bool thirdPerson() const; + + Camera(); + + private: + glm::vec3 pos; + bool m_third_person; + glm::vec3 m_up; + glm::vec3 m_world_up; + glm::vec3 m_front; + glm::vec3 m_right; + }; +} diff --git a/src/chunk.cpp b/src/chunk.cpp new file mode 100644 index 0000000..bf356e0 --- /dev/null +++ b/src/chunk.cpp @@ -0,0 +1,181 @@ +#include +#include +#include "animations.hpp" +#include "block_def.hpp" +#include "box_vertices.hpp" +#include "chunk.hpp" +#include "face_dir.hpp" +#include "map.hpp" +#include "mesh.hpp" +#include "texture.hpp" + +#define SIZE DRAGONBLOCKS_CHUNK_SIZE + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +bool Chunk::checkPos(const ivec3 &pos) +{ + return pos.x >= 0 && pos.y >= 0 && pos.z >= 0 && pos.x < SIZE && pos.y < SIZE && pos.z < SIZE; +} + +const Block *Chunk::getBlock(const ivec3 &pos) const +{ + const Block *b = getBlockNoEx(pos); + if (! b) { + throw out_of_range("Block position out of range"); + } + return b; +} + +const Block *Chunk::getBlockNoEx(const ivec3 &pos) const +{ + return Chunk::checkPos(pos) ? &data.blocks[pos.x][pos.y][pos.z] : nullptr; +} + +void Chunk::setBlock(const ivec3 &pos, const Block &block) +{ + if (! Chunk::checkPos(pos)) { + throw out_of_range("Block position out of range"); + } + data.blocks[pos.x][pos.y][pos.z] = block; +} + +void Chunk::setBlockNoEx(const ivec3 &pos, const Block &block) +{ + try { + setBlock(pos, block); + } catch (out_of_range &) { + } +} + +void Chunk::addMeshUpdateTask() +{ + async_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() +{ + cout << "Update Chunk Mesh at " << pos.x << " " << pos.y << " " << pos.z << endl; + + if (mesh_created && ! animation_finished) + return; + + bool mesh_created_before = mesh_created; + mesh_created = true; + + vector vertices; + vector textures; + bool any_drawable_block = false; + + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + for (int z = 0; z < SIZE; z++) { + Block *block = &data.blocks[x][y][z]; + BlockDef *def = block->getDef(); + if (! def->drawable) + continue; + ivec3 bpos(x, y, z); + vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5); + for (int facenr = 0; facenr < 6; facenr++) { + 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->tile_def.get(facenr)); + for (int vertex_index = 0; vertex_index < 6; vertex_index++) { + for (int attribute_index = 0; attribute_index < 5; attribute_index++) { + GLdouble value = box_vertices[facenr][vertex_index][attribute_index]; + switch (attribute_index) { + case 0: + value += pos_from_mesh_origin.x; + break; + case 1: + value += pos_from_mesh_origin.y; + break; + case 2: + value += pos_from_mesh_origin.z; + break; + } + vertices.push_back(value); + } + } + } + } + } + } + } + + if (! any_drawable_block) { + if (! mesh_created_before) { + afterAnimation(); + } else if (mesh) { + mesh->die(); + mesh = nullptr; + } + return; + } + + Mesh *oldmesh = mesh; + + mesh = new Mesh(scene, shader_program, &vertices[0], vertices.size()); + mesh->pos = pos * SIZE + SIZE / 2; + mesh->minp = vec3(- SIZE / 2); + mesh->maxp = vec3(+ SIZE / 2); + mesh->textures = textures; + mesh->vertices_per_texture = 6; + if (! mesh_created_before) { + mesh->animation = new FlyInAnimation(0.4, 20.0, Chunk::staticAfterAnimation, this); + } + + if (oldmesh) { + oldmesh->die(); + } +} + +void Chunk::doAsyncTask() +{ + updateMesh(); +} + +Chunk::Chunk(Map *m, const ivec3 &p, const Data &d, AsyncMgr *a, Scene *s, ShaderProgram *sh) : map(m), data(d), pos(p), async_mgr(a), scene(s), shader_program(sh) +{ + addMeshUpdateTask(); +} + +Chunk::~Chunk() +{ + if (mesh) { + mesh->die(); + } +} + +void Chunk::staticAfterAnimation(void *chunk) +{ + if (chunk) { + ((Chunk *)chunk)->afterAnimation(); + } +} + +void Chunk::afterAnimation() +{ + animation_finished = true; + addMeshUpdateTaskWithEdge(); +} diff --git a/src/chunk.hpp b/src/chunk.hpp new file mode 100644 index 0000000..ac12851 --- /dev/null +++ b/src/chunk.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include "block.hpp" +#include "gl.hpp" +#include "async_mgr.hpp" + +#define DRAGONBLOCKS_CHUNK_SIZE 16 + +namespace dragonblocks +{ + class Map; + class Mesh; + class Scene; + class ShaderProgram; + + class Chunk : public AsyncMgr::ITask + { + public: + static bool checkPos(const glm::ivec3 &); + + class Data + { + public: + Block blocks[DRAGONBLOCKS_CHUNK_SIZE][DRAGONBLOCKS_CHUNK_SIZE][DRAGONBLOCKS_CHUNK_SIZE]; + Data() = default; + Data(const Data &) = default; + }; + + glm::ivec3 pos; + + const Block *getBlock(const glm::ivec3 &) const; + const Block *getBlockNoEx(const glm::ivec3 &) const; + void setBlock(const glm::ivec3 &, const Block &); + void setBlockNoEx(const glm::ivec3 &, const Block &); + void addMeshUpdateTask(); + void addMeshUpdateTaskWithEdge(); + void updateMesh(); + void doAsyncTask(); + + Chunk(Map *, const glm::ivec3 &, const Data &, AsyncMgr *, Scene *, ShaderProgram *); + ~Chunk(); + + private: + static void staticAfterAnimation(void *); + + Map *map; + AsyncMgr *async_mgr; + Scene *scene; + ShaderProgram *shader_program; + Mesh *mesh = nullptr; + Data data; + bool animation_finished = false; + bool mesh_created = false; + + void afterAnimation(); + }; +}; diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 0000000..0b6809f --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,88 @@ +#include +#include +#include "async_mgr.hpp" +#include "client.hpp" +#include "game.hpp" +#include "gl.hpp" +#include "input_handler.hpp" +#include "local_player.hpp" +#include "map.hpp" +#include "mapgen.hpp" +#include "render_engine.hpp" +#include "shader_program.hpp" +#include "texture.hpp" +#include "window.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +void Client::run() +{ + async_mgr->start(); + while (render_engine->running()) { + double dtime = glfwGetTime() - last_time; + last_time = glfwGetTime(); + + player->step(dtime); + + render_engine->render(dtime); + + input_handler->processInput(dtime); + + // process keys + if (input_handler->wasKeyDown(GLFW_KEY_F11)) { + render_engine->window->toggleFullscreen(); + } + } +} + +Client::Client() +{ + cout << "Initalizing Client..." << endl; + + Texture::mipmap = true; + Texture::bilinear_filter = false; + Texture::initArgs(); + + async_mgr = new AsyncMgr; + + input_handler = new InputHandler(); + input_handler->mouse_sensitivity = 20; + input_handler->listenFor(GLFW_KEY_F11); + + render_engine = new RenderEngine; + render_engine->render_distance = 1000; + render_engine->fov = 86.1; + render_engine->sky = vec3(0.52941176470588, 0.8078431372549, 0.92156862745098); // HTML skyblue + render_engine->window->setSize(1250, 750); + render_engine->window->setPos(0, 0); + render_engine->window->setTitle("Dragonblocks"); + + input_handler->setWindow(render_engine->window); + + shader_program = new ShaderProgram("shaders"); + + mapgen = new Mapgen; + + map = new Map(mapgen, async_mgr, render_engine->scene, shader_program); + + Texture player_texture; + player_texture.load("textures/stone.png"); + + player = new LocalPlayer(map, render_engine->scene, player_texture, shader_program, render_engine->camera, input_handler); + player->pitch_move = false; + player->speed = 10; + player->setSize(vec3(0.75, 1.5, 0.75)); + + game = new Game(mapgen); + + last_time = glfwGetTime(); + + cout << "Initialisation done." << endl; +} + +extern "C" void _dragonblocks_start_client() +{ + Client().run(); +} diff --git a/src/client.hpp b/src/client.hpp new file mode 100644 index 0000000..d50886a --- /dev/null +++ b/src/client.hpp @@ -0,0 +1,33 @@ +#pragma once + +namespace dragonblocks +{ + class AsyncMgr; + class Game; + class InputHandler; + class Map; + class LocalPlayer; + class Mapgen; + class RenderEngine; + class ShaderProgram; + + class Client + { + public: + AsyncMgr *async_mgr; + Game *game; + InputHandler *input_handler; + LocalPlayer *player; + Map *map; + Mapgen *mapgen; + RenderEngine *render_engine; + ShaderProgram *shader_program; + + void run(); + + Client(); + + private: + double last_time; + }; +} diff --git a/src/dragonblocks/CMakeLists.txt b/src/dragonblocks/CMakeLists.txt deleted file mode 100644 index bb7c5e4..0000000 --- a/src/dragonblocks/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -cmake_minimum_required(VERSION 3.0) - -set(srcpath "${PROJECT_SOURCE_DIR}/src/dragonblocks") - -add_library(dragonblocks SHARED - block.cpp - block_def.cpp - camera.cpp - chunk.cpp - client.cpp - core.cpp - cube.cpp - face_dir.cpp - game.cpp - gldebug.cpp - input_handler.cpp - log.cpp - map.cpp - mapgen.cpp - mesh.cpp - mesh_gen_mgr.cpp - player.cpp - render_engine.cpp - scene.cpp - shader_program.cpp - texture.cpp - window.cpp - world.cpp -) - -target_link_libraries(dragonblocks - GL - GLEW - glfw -) - -target_include_directories(dragonblocks PUBLIC - "${PROJECT_SOURCE_DIR}/lib/" - "${PROJECT_SOURCE_DIR}/src/" -) - diff --git a/src/dragonblocks/block.cpp b/src/dragonblocks/block.cpp deleted file mode 100644 index b226914..0000000 --- a/src/dragonblocks/block.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "block.hpp" - -using namespace dragonblocks; - -BlockDef *Block::getDef() const -{ - return def; -} - -Block::Block(BlockDef *d) : def(d) -{ -} diff --git a/src/dragonblocks/block.hpp b/src/dragonblocks/block.hpp deleted file mode 100644 index 6a4e1d5..0000000 --- a/src/dragonblocks/block.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "gl.hpp" - -namespace dragonblocks -{ - class BlockDef; - class Block - { - public: - BlockDef *getDef() const; - - Block() = default; - Block(const Block &) = default; - Block(BlockDef *); - - private: - BlockDef *def = nullptr; - }; -} - diff --git a/src/dragonblocks/block_def.cpp b/src/dragonblocks/block_def.cpp deleted file mode 100644 index 2e200ee..0000000 --- a/src/dragonblocks/block_def.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "block_def.hpp" - -using namespace std; -using namespace dragonblocks; - -BlockDef::BlockDef(const string &n, const vector &t) : name(n), tiles(t) -{ - int s = tiles.size(); - if (s == 0) { - drawable = false; - } else { - for (int i = 0; s < 6; i += s) { - for (int j = 0; j < i && j + i < 6; j++) { - tiles[i + j] = tiles[j]; - } - } - } -} - -BlockDef::BlockDef(const string &n, const Texture &t) : BlockDef(n, {t, t, t, t, t, t}) -{ -} - -BlockDef::BlockDef(const string &n) : BlockDef(n, vector()) -{ -} diff --git a/src/dragonblocks/block_def.hpp b/src/dragonblocks/block_def.hpp deleted file mode 100644 index b4ac3c7..0000000 --- a/src/dragonblocks/block_def.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include -#include "gl.hpp" -#include "texture.hpp" - -namespace dragonblocks -{ - class BlockDef - { - public: - std::string name; - std::vector tiles; - bool drawable = true; - - BlockDef(const std::string &); - BlockDef(const std::string &, const Texture &); - BlockDef(const std::string &, const std::vector &); - }; -} diff --git a/src/dragonblocks/camera.cpp b/src/dragonblocks/camera.cpp deleted file mode 100644 index 2aa749d..0000000 --- a/src/dragonblocks/camera.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include "camera.hpp" - -using namespace glm; -using namespace dragonblocks; - -mat4 Camera::getViewMatrix() const -{ - return lookAt(pos, pos + m_front, m_up); -} - -void Camera::update(double yaw, double pitch) -{ - yaw = radians(yaw); - 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)); - m_up = normalize(cross(m_right, m_front)); -} - -vec3 Camera::up() const -{ - return m_up; -} - -vec3 Camera::front() const -{ - return m_front; -} - -vec3 Camera::right() const -{ - return m_right; -} - -Camera::Camera() : pos(0, 0, 0), m_up(0, 1, 0), m_world_up(0, 1, 0), m_front(0, 0, -1) -{ -} diff --git a/src/dragonblocks/camera.hpp b/src/dragonblocks/camera.hpp deleted file mode 100644 index 4ed82df..0000000 --- a/src/dragonblocks/camera.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "gl.hpp" - -namespace dragonblocks -{ - class Camera - { - public: - glm::vec3 pos; - - glm::mat4 getViewMatrix() const; - void update(double, double); - glm::vec3 up() const; - glm::vec3 front() const; - glm::vec3 right() const; - - Camera(); - - private: - glm::vec3 m_up; - glm::vec3 m_world_up; - glm::vec3 m_front; - glm::vec3 m_right; - }; -} diff --git a/src/dragonblocks/chunk.cpp b/src/dragonblocks/chunk.cpp deleted file mode 100644 index 2100511..0000000 --- a/src/dragonblocks/chunk.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include "block_def.hpp" -#include "chunk.hpp" -#include "cube.hpp" -#include "face_dir.hpp" -#include "log.hpp" -#include "map.hpp" -#include "mesh.hpp" -#include "texture.hpp" - -#define SIZE DRAGONBLOCKS_CHUNK_SIZE - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -void Chunk::checkPos(const ivec3 &pos) -{ - if (pos.x < 0 || pos.y < 0 || pos.z < 0 || pos.x >= SIZE || pos.y >= SIZE || pos.z >= SIZE) - throw out_of_range("Block position out of range"); -} - -const Block *Chunk::getBlock(const ivec3 &pos) const -{ - Chunk::checkPos(pos); - return &data.blocks[pos.x][pos.y][pos.z]; -} - -const Block *Chunk::getBlockNoEx(const ivec3 &pos) const -{ - try { - return getBlock(pos); - } catch (out_of_range &) { - return nullptr; - } -} - -void Chunk::setBlock(const ivec3 &pos, const Block &block) -{ - Chunk::checkPos(pos); - data.blocks[pos.x][pos.y][pos.z] = block; -} - -void Chunk::setBlockNoEx(const ivec3 &pos, const Block &block) -{ - try { - setBlock(pos, block); - } 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() -{ - log(string("Update Chunk Mesh at ") + to_string(pos.x) + " " + to_string(pos.y) + " " + to_string(pos.z)); - - if (mesh_created && ! animation_finished) - return; - - bool mesh_created_before = mesh_created; - mesh_created = true; - - vector vertices; - vector textures; - bool any_drawable_block = false; - - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - for (int z = 0; z < SIZE; z++) { - Block *block = &data.blocks[x][y][z]; - BlockDef *def = block->getDef(); - if (! def->drawable) - continue; - ivec3 bpos(x, y, z); - vec3 pos_from_mesh_origin = vec3(bpos) - vec3(SIZE / 2 + 0.5); - for (int facenr = 0; facenr < 6; facenr++) { - 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++) { - int index = facenr * 6 * 5 + vertex_index * 5 + attribute_index; - GLdouble value = cube[index]; - switch (attribute_index) { - case 0: - value += pos_from_mesh_origin.x; - break; - case 1: - value += pos_from_mesh_origin.y; - break; - case 2: - value += pos_from_mesh_origin.z; - break; - } - vertices.push_back(value); - } - } - } - } - } - } - } - - if (! any_drawable_block) { - if (! mesh_created_before) { - afterAnimation(); - } else if (mesh) { - delete mesh; - mesh = nullptr; - } - return; - } - - Mesh *oldmesh = mesh; - - mesh = new Mesh(scene, &vertices[0], vertices.size() * sizeof(GLfloat)); - mesh->pos = pos * SIZE + SIZE / 2; - mesh->minp = vec3(- SIZE / 2 - 1); - mesh->maxp = vec3(+ SIZE / 2 + 1); - mesh->textures = textures; - mesh->vertices_per_texture = 6; - if (! mesh_created_before) { - mesh->animation = Mesh::Animation(Mesh::Animation::Type::FLYIN, Chunk::staticAfterAnimation, this); - } - - if (oldmesh) { - oldmesh->die(); - } -} - -Chunk::Chunk(Map *m, const glm::ivec3 &p, const Data &d, MeshGenMgr *mg, Scene *s) : map(m), data(d), pos(p), mesh_gen_mgr(mg), scene(s) -{ - addMeshUpdateTask(); -} - -Chunk::~Chunk() -{ - if (mesh) { - delete mesh; - } -} - -void Chunk::staticAfterAnimation(void *chunk) -{ - if (chunk) { - ((Chunk *)chunk)->afterAnimation(); - } -} - -void Chunk::afterAnimation() -{ - animation_finished = true; - addMeshUpdateTaskWithEdge(); -} diff --git a/src/dragonblocks/chunk.hpp b/src/dragonblocks/chunk.hpp deleted file mode 100644 index 5561c38..0000000 --- a/src/dragonblocks/chunk.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "block.hpp" -#include "gl.hpp" -#include "mesh_gen_mgr.hpp" - -#define DRAGONBLOCKS_CHUNK_SIZE 16 - -namespace dragonblocks -{ - class Map; - class Mesh; - class Scene; - - class Chunk : public MeshGenMgr::MeshGenerator - { - public: - static void checkPos(const glm::ivec3 &); - - class Data - { - public: - Block blocks[DRAGONBLOCKS_CHUNK_SIZE][DRAGONBLOCKS_CHUNK_SIZE][DRAGONBLOCKS_CHUNK_SIZE]; - Data() = default; - Data(const Data &) = default; - }; - - glm::ivec3 pos; - - const Block *getBlock(const glm::ivec3 &) const; - const Block *getBlockNoEx(const glm::ivec3 &) const; - 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 &, MeshGenMgr *, Scene *); - ~Chunk(); - - private: - static void staticAfterAnimation(void *); - - Map *map; - Mesh *mesh = nullptr; - MeshGenMgr *mesh_gen_mgr; - Scene *scene; - Data data; - bool animation_finished = false; - bool mesh_created = false; - - void afterAnimation(); - }; -}; diff --git a/src/dragonblocks/client.cpp b/src/dragonblocks/client.cpp deleted file mode 100644 index c8fa8db..0000000 --- a/src/dragonblocks/client.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "camera.hpp" -#include "client.hpp" -#include "game.hpp" -#include "gl.hpp" -#include "input_handler.hpp" -#include "log.hpp" -#include "map.hpp" -#include "mapgen.hpp" -#include "player.hpp" -#include "render_engine.hpp" -#include "texture.hpp" -#include "window.hpp" - -using namespace glm; -using namespace dragonblocks; - -Client::Client() -{ - log("Initalizing..."); - - Texture::mipmap = true; - Texture::bilinear_filter = false; - Texture::initArgs(); - - render_engine = new RenderEngine; - - render_engine->window->setSize(1250, 750); - render_engine->window->setPos(0, 0); - render_engine->window->setTitle("Dragonblocks"); - render_engine->window->toggleFullscreen(); - render_engine->input_handler->mouse_sensitivity = 20; - - render_engine->setSky(vec3(0.52941176470588, 0.8078431372549, 0.92156862745098)); - render_engine->setRenderDistance(1000); - render_engine->setFov(86.1); - - mapgen = new Mapgen; - - map = new Map(mapgen, render_engine->mesh_gen_mgr, render_engine->scene); - - player = Player::createLocalplayer(render_engine->camera, render_engine->input_handler, map); - - player->pitch_move = false; - player->yaw = 0; - player->pitch = 0; - player->speed = 10; - player->pos = vec3(8, 8, 8); - - game = new Game(mapgen); - - log("Initialisation complete."); -} - -void Client::start() -{ - render_engine->startMeshGenMgr(); - while (render_engine->running()) { - render_engine->render(); - } -} diff --git a/src/dragonblocks/client.hpp b/src/dragonblocks/client.hpp deleted file mode 100644 index f779b68..0000000 --- a/src/dragonblocks/client.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -namespace dragonblocks -{ - class Game; - class Map; - class Mapgen; - class Player; - class RenderEngine; - - class Client - { - public: - Game *game; - Map *map; - Mapgen *mapgen; - Player *player; - RenderEngine *render_engine; - - void start(); - - Client(); - ~Client(); - }; -} diff --git a/src/dragonblocks/core.cpp b/src/dragonblocks/core.cpp deleted file mode 100644 index a04ee56..0000000 --- a/src/dragonblocks/core.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "core.hpp" -#include "client.hpp" -#include "render_engine.hpp" - -using namespace dragonblocks; - -Gametype dragonblocks::gametype; -Client *dragonblocks::client = nullptr; - -extern "C" void _dragonblocks_start_client() -{ - gametype = Gametype::CLIENT; - client = new Client(); - client->start(); -} diff --git a/src/dragonblocks/core.hpp b/src/dragonblocks/core.hpp deleted file mode 100644 index 788e899..0000000 --- a/src/dragonblocks/core.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace dragonblocks -{ - class Client; - - enum Gametype - { - CLIENT - }; - - extern Gametype gametype; - extern Client *client; -} diff --git a/src/dragonblocks/cube.cpp b/src/dragonblocks/cube.cpp deleted file mode 100644 index e132b70..0000000 --- a/src/dragonblocks/cube.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "cube.hpp" - -GLfloat dragonblocks::cube[DRAGONBLOCKS_CUBE_VERTEX_COUNT] = { -// x y z s t - -0.5, -0.5, -0.5, +0.0, +0.0, - +0.5, -0.5, -0.5, +1.0, +0.0, - +0.5, +0.5, -0.5, +1.0, +1.0, - +0.5, +0.5, -0.5, +1.0, +1.0, - -0.5, +0.5, -0.5, +0.0, +1.0, - -0.5, -0.5, -0.5, +0.0, +0.0, - - -0.5, -0.5, +0.5, +0.0, +0.0, - +0.5, +0.5, +0.5, +1.0, +1.0, - +0.5, -0.5, +0.5, +1.0, +0.0, - +0.5, +0.5, +0.5, +1.0, +1.0, - -0.5, -0.5, +0.5, +0.0, +0.0, - -0.5, +0.5, +0.5, +0.0, +1.0, - - -0.5, +0.5, +0.5, +1.0, +1.0, - -0.5, -0.5, -0.5, +0.0, +0.0, - -0.5, +0.5, -0.5, +0.0, +1.0, - -0.5, -0.5, -0.5, +0.0, +0.0, - -0.5, +0.5, +0.5, +1.0, +1.0, - -0.5, -0.5, +0.5, +1.0, +0.0, - - +0.5, +0.5, +0.5, +1.0, +1.0, - +0.5, +0.5, -0.5, +0.0, +1.0, - +0.5, -0.5, -0.5, +0.0, +0.0, - +0.5, -0.5, -0.5, +0.0, +0.0, - +0.5, -0.5, +0.5, +1.0, +0.0, - +0.5, +0.5, +0.5, +1.0, +1.0, - - -0.5, -0.5, -0.5, +0.0, +1.0, - +0.5, -0.5, -0.5, +1.0, +1.0, - +0.5, -0.5, +0.5, +1.0, +0.0, - +0.5, -0.5, +0.5, +1.0, +0.0, - -0.5, -0.5, +0.5, +0.0, +0.0, - -0.5, -0.5, -0.5, +0.0, +1.0, - - -0.5, +0.5, -0.5, +0.0, +1.0, - +0.5, +0.5, -0.5, +1.0, +1.0, - +0.5, +0.5, +0.5, +1.0, +0.0, - +0.5, +0.5, +0.5, +1.0, +0.0, - -0.5, +0.5, +0.5, +0.0, +0.0, - -0.5, +0.5, -0.5, +0.0, +1.0, -}; diff --git a/src/dragonblocks/cube.hpp b/src/dragonblocks/cube.hpp deleted file mode 100644 index cf6ab7c..0000000 --- a/src/dragonblocks/cube.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "gl.hpp" - -#define DRAGONBLOCKS_CUBE_VERTEX_COUNT 5 * 6 * 6 // 5 floats per vertex, 6 vertices per face, 6 faces - -namespace dragonblocks -{ - extern GLfloat cube[DRAGONBLOCKS_CUBE_VERTEX_COUNT]; -} diff --git a/src/dragonblocks/face_dir.cpp b/src/dragonblocks/face_dir.cpp deleted file mode 100644 index 677623b..0000000 --- a/src/dragonblocks/face_dir.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "face_dir.hpp" - -using namespace glm; - -ivec3 dragonblocks::face_dir[6] = { - {+0, +0, -1}, - {+0, +0, +1}, - {-1, +0, +0}, - {+1, +0, +0}, - {+0, -1, +0}, - {+0, +1, +0}, -}; diff --git a/src/dragonblocks/face_dir.hpp b/src/dragonblocks/face_dir.hpp deleted file mode 100644 index 32034ef..0000000 --- a/src/dragonblocks/face_dir.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "gl.hpp" - -namespace dragonblocks -{ - extern glm::ivec3 face_dir[6]; -} diff --git a/src/dragonblocks/game.cpp b/src/dragonblocks/game.cpp deleted file mode 100644 index 492e632..0000000 --- a/src/dragonblocks/game.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "block_def.hpp" -#include "game.hpp" -#include "mapgen.hpp" - -using namespace dragonblocks; - -Game::Game(Mapgen *m) : mapgen(m) -{ - grass_texture.load("textures/grass.png"); - grass_side_texture.load("textures/grass_side.png"); - dirt_texture.load("textures/dirt.png"); - stone_texture.load("textures/stone.png"); - - air = new BlockDef("dragonblocks:air"); - grass = new BlockDef("dragonblocks:grass", {grass_side_texture, grass_side_texture, grass_side_texture, grass_side_texture, dirt_texture, grass_texture}); - dirt = new BlockDef("dragonblocks:dirt", dirt_texture); - stone = new BlockDef("dragonblocks:stone", stone_texture); - - mapgen->air_def = air; - mapgen->grass_def = grass; - mapgen->dirt_def = dirt; - mapgen->stone_def = stone; -} diff --git a/src/dragonblocks/game.hpp b/src/dragonblocks/game.hpp deleted file mode 100644 index 1168482..0000000 --- a/src/dragonblocks/game.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "texture.hpp" - -namespace dragonblocks -{ - class BlockDef; - class Mapgen; - - class Game - { - public: - BlockDef *air, *grass, *dirt, *stone; - Mapgen *mapgen; - Texture grass_texture, grass_side_texture, dirt_texture, stone_texture; - - Game(Mapgen *); - }; -} diff --git a/src/dragonblocks/gl.hpp b/src/dragonblocks/gl.hpp deleted file mode 100644 index dcfe0bc..0000000 --- a/src/dragonblocks/gl.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include -#include -#include -#include diff --git a/src/dragonblocks/gldebug.cpp b/src/dragonblocks/gldebug.cpp deleted file mode 100644 index f71c4c3..0000000 --- a/src/dragonblocks/gldebug.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include "gldebug.hpp" -#include "log.hpp" - -using namespace std; -using namespace dragonblocks; - -GLenum dragonblocks::checkGLError(const char *file, int line) -{ - GLenum errorCode; - if ((errorCode = glGetError()) != GL_NO_ERROR) - { - string error; - switch (errorCode) - { - case GL_INVALID_ENUM: error = "INVALID_ENUM"; break; - case GL_INVALID_VALUE: error = "INVALID_VALUE"; break; - case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break; - case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break; - case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break; - case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break; - case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break; - } - log(string("OpenGL Error: ") + error + " | " + file + " (" + to_string(line) + ")"); - } - return errorCode; -} diff --git a/src/dragonblocks/gldebug.hpp b/src/dragonblocks/gldebug.hpp deleted file mode 100644 index bc56bb6..0000000 --- a/src/dragonblocks/gldebug.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "gl.hpp" - -#define CHECKERR dragonblocks::checkGLError(__FILE__, __LINE__); - -namespace dragonblocks -{ - GLenum checkGLError(const char *file, int line); -} diff --git a/src/dragonblocks/input_handler.cpp b/src/dragonblocks/input_handler.cpp deleted file mode 100644 index 6ac64c3..0000000 --- a/src/dragonblocks/input_handler.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "camera.hpp" -#include "input_handler.hpp" -#include "window.hpp" - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -void InputHandler::processInput(double dtime) -{ - processMouseInput(dtime); - processKeyInput(dtime); -} - -void InputHandler::listenFor(int key) -{ - listened_keys.insert(key); -} - -void InputHandler::dontListenFor(int key) -{ - listened_keys.erase(key); -} - -void InputHandler::addMouseHandler(void (*callback)(double, double, double)) -{ - mouse_handlers.insert(callback); -} - -void InputHandler::removeMouseHandler(void (*callback)(double, double, double)) -{ - mouse_handlers.erase(callback); -} - -void InputHandler::addKeyHandler(void (*callback)(double, set)) -{ - key_handlers.insert(callback); -} - -void InputHandler::removeKeyHandler(void (*callback)(double, set)) -{ - key_handlers.erase(callback); -} - -InputHandler::InputHandler(Window *w) : window(w) -{ -} - -void InputHandler::processMouseInput(double dtime) -{ - vec2 cursor_delta = vec2(mouse_sensitivity * dtime) * (vec2)window->getCursorDelta(); - double x, y; - x = cursor_delta.x; - y = cursor_delta.y; - if (x != 0 && y != 0) { - for (auto it = mouse_handlers.begin(); it != mouse_handlers.end(); it++) { - (**it)(dtime, x, y); - } - } -} - -void InputHandler::processKeyInput(double dtime) -{ - set keysDown; - for (auto it = listened_keys.begin(); it != listened_keys.end(); it++) { - int key = *it; - if (window->wasKeyDown(key)) { - keysDown.insert(key); - } - } - if (keysDown.begin() != keysDown.end()) { - for (auto it = key_handlers.begin(); it != key_handlers.end(); it++) { - (**it)(dtime, keysDown); - } - } -} diff --git a/src/dragonblocks/input_handler.hpp b/src/dragonblocks/input_handler.hpp deleted file mode 100644 index bf4d4e9..0000000 --- a/src/dragonblocks/input_handler.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include "gl.hpp" - -namespace dragonblocks -{ - class Camera; - class Window; - - class InputHandler - { - public: - void processInput(double); - void listenFor(int); - void dontListenFor(int); - void addMouseHandler(void (*)(double, double, double)); - void removeMouseHandler(void (*)(double, double, double)); - void addKeyHandler(void (*)(double, std::set)); - void removeKeyHandler(void (*)(double, std::set)); - - double mouse_sensitivity; - - InputHandler(Window *); - - private: - void processMouseInput(double); - void processKeyInput(double); - - Window *window; - std::set listened_keys; - std::set mouse_handlers; - std::set)> key_handlers; - }; -} diff --git a/src/dragonblocks/log.cpp b/src/dragonblocks/log.cpp deleted file mode 100644 index 6a17fee..0000000 --- a/src/dragonblocks/log.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include "core.hpp" -#include "log.hpp" - -using namespace std; -using namespace dragonblocks; - -void dragonblocks::log(const string &l) -{ - string gt; - switch (gametype) { - case Gametype::CLIENT: - gt = "Client"; - break; - } - cout << "[" << gt << "] " << l << endl; -} diff --git a/src/dragonblocks/log.hpp b/src/dragonblocks/log.hpp deleted file mode 100644 index c40c3ed..0000000 --- a/src/dragonblocks/log.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -namespace dragonblocks -{ - void log(const std::string &); -} diff --git a/src/dragonblocks/map.cpp b/src/dragonblocks/map.cpp deleted file mode 100644 index 8b338d9..0000000 --- a/src/dragonblocks/map.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include "map.hpp" -#include "mapgen.hpp" - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -ivec3 Map::getChunkPos(const vec3 &p) -{ - return floor(p / (float)DRAGONBLOCKS_CHUNK_SIZE); -} - -ivec3 Map::getBlockPos(const ivec3 &p) -{ - 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 * DRAGONBLOCKS_MAP_SIZE + (uint16_t)p.z * DRAGONBLOCKS_MAP_SIZE * DRAGONBLOCKS_MAP_SIZE; -} - -const Block *Map::getBlock(const glm::ivec3 &p) -{ - - Chunk *chunk = getChunk(Map::getChunkPos(p)); - if (chunk) - return chunk->getBlock(Map::getBlockPos(p)); - return nullptr; -} - -void Map::setBlock(const glm::ivec3 &p, BlockDef *def) -{ - Chunk *chunk = getChunk(Map::getChunkPos(p)); - if (chunk) - chunk->setBlock(Map::getBlockPos(p), def); -} - -void Map::createChunk(const glm::ivec3 &p, const Chunk::Data &data) -{ - uint64_t poshash = Map::getChunkPosHash(p); - - if (chunks[poshash]) - return; - - chunks[poshash] = new Chunk(this, p, data, mesh_gen_mgr, scene); -} - -void Map::createChunk(const glm::ivec3 &p) -{ - if (! chunks[Map::getChunkPosHash(p)]) - createChunk(p, mapgen->generate(p)); -} - -Chunk *Map::getChunk(const glm::ivec3 &p) -{ - return chunks[Map::getChunkPosHash(p)]; -} - -void Map::clear() -{ - for (auto it = chunks.begin(); it != chunks.end(); it++) - delete it->second; - chunks.clear(); -} - -Map::Map(Mapgen *m, MeshGenMgr *mg, Scene *s) : mapgen(m), mesh_gen_mgr(mg), scene(s) -{ -} - -Map::~Map() -{ - clear(); -} diff --git a/src/dragonblocks/map.hpp b/src/dragonblocks/map.hpp deleted file mode 100644 index e7b9f7e..0000000 --- a/src/dragonblocks/map.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include "chunk.hpp" -#include "gl.hpp" - -#define DRAGONBLOCKS_MAP_SIZE 1000 - -namespace dragonblocks -{ - class BlockDef; - class Block; - class Mapgen; - class MeshGenMgr; - class Scene; - - class Map - { - public: - static glm::ivec3 getChunkPos(const glm::vec3 &); - static glm::ivec3 getBlockPos(const glm::ivec3 &); - static uint16_t getChunkPosHash(const glm::ivec3 &); - - const Block *getBlock(const glm::ivec3 &); - const Block *getBlockRelativePos(Chunk *, const glm::ivec3 &); - void setBlock(const glm::ivec3 &, BlockDef *); - void createChunk(const glm::ivec3 &, const Chunk::Data &); - void createChunk(const glm::ivec3 &); - Chunk *getChunk(const glm::ivec3 &); - void clear(); - - Map(Mapgen *, MeshGenMgr *, Scene *); - ~Map(); - - private: - std::map chunks; - Mapgen *mapgen; - MeshGenMgr *mesh_gen_mgr; - Scene *scene; - }; -} diff --git a/src/dragonblocks/mapgen.cpp b/src/dragonblocks/mapgen.cpp deleted file mode 100644 index a5b4d07..0000000 --- a/src/dragonblocks/mapgen.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include "mapgen.hpp" - -using namespace glm; -using namespace dragonblocks; - -Chunk::Data Mapgen::generate(const ivec3 &chunkp) const -{ - Chunk::Data data; - vec3 minp = chunkp * ivec3(DRAGONBLOCKS_CHUNK_SIZE); - vec3 maxp = minp + vec3(DRAGONBLOCKS_CHUNK_SIZE); - int minx = minp.x, miny = minp.y, minz = minp.z, maxx = maxp.x, maxy = maxp.y, maxz = maxp.z; - for (int x = minx; x < maxx; x++) { - int rx = x - minx; - for (int z = minz; z < maxz; z++) { - int rz = z - minz; - int grass_layer = grass_layer_middle + grass_layer_range * perlin(vec2((float)x / 128, (float)z / 128)); - for (int y = miny; y < maxy; y++) { - int ry = y - miny; - BlockDef *blockdef; - if (y < grass_layer - 4) - blockdef = stone_def; - else if (y < grass_layer - 1) - blockdef = dirt_def; - else if (y < grass_layer) - blockdef = grass_def; - else - blockdef = air_def; - data.blocks[rx][ry][rz] = blockdef; - } - } - } - return data; -} diff --git a/src/dragonblocks/mapgen.hpp b/src/dragonblocks/mapgen.hpp deleted file mode 100644 index 261cd2f..0000000 --- a/src/dragonblocks/mapgen.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "chunk.hpp" -#include "gl.hpp" - -namespace dragonblocks -{ - class BlockDef; - - class Mapgen - { - public: - float grass_layer_middle = 0, grass_layer_range = 64; - BlockDef *air_def, *stone_def, *dirt_def, *grass_def; - - Chunk::Data generate(const glm::ivec3 &) const; - }; -}; diff --git a/src/dragonblocks/mesh.cpp b/src/dragonblocks/mesh.cpp deleted file mode 100644 index e8741ac..0000000 --- a/src/dragonblocks/mesh.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include -#include -#include "FrustumCull.h" -#include "gldebug.hpp" -#include "mesh.hpp" -#include "scene.hpp" -#include "shader_program.hpp" - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -double Mesh::Animation::grow_time = 0.25; // s -double Mesh::Animation::flyin_time = 0.4; // s -double Mesh::Animation::flyin_offset = 20; // m -double Mesh::Animation::rotate_speed = 1; // turns/s - -mat4 Mesh::Animation::getModelMatrix(double dtime, vec3 pos, vec3 size, vec3 rotation_axis, float rotation_angle) -{ - mat4 trans = mat4(1.0); - - if (type == Mesh::Animation::Type::NONE) - goto finish; - - if (expires) { - time_left -= dtime; - if (time_left < 0) { - type = Mesh::Animation::Type::NONE; - if (on_finish) { - (*on_finish)(extra_data); - } - goto finish; - } - } - - switch (type) { - case Mesh::Animation::Type::FLYIN: - pos.y -= Mesh::Animation::flyin_offset * time_left / Mesh::Animation::flyin_time; - break; - - case Mesh::Animation::Type::GROW: - size *= 1 - time_left / Mesh::Animation::grow_time; - break; - - case Mesh::Animation::Type::ROTATE: - rotation_angle += glfwGetTime() * Mesh::Animation::rotate_speed * pi() * 2; - } - - finish: - - trans = translate(trans, pos); - trans = rotate(trans, rotation_angle, rotation_axis); - trans = scale(trans, size); - - return trans; -} - -Mesh::Animation::Animation(Mesh::Animation::Type t, void (*o)(void *), void *e) : type(t), on_finish(o), extra_data(e) -{ - switch(type) { - case Mesh::Animation::Type::FLYIN: - expires = true; - time_left = Mesh::Animation::flyin_time; - break; - - case Mesh::Animation::Type::GROW: - expires = true; - time_left = Mesh::Animation::grow_time; - break; - - case Mesh::Animation::Type::ROTATE: - expires = false; - break; - } -} - -void Mesh::render(double dtime, ShaderProgram *shader_program, Frustum *frustum) -{ - rendering = true; - - if (do_delete) { - delete this; - return; - } else if (prepare_death) { - do_delete = true; - } - - if (! configured) { - configure(); - } - - shader_program->use(); CHECKERR - - mat4 model_matrix = animation.getModelMatrix(dtime, pos, size, rotation_axis, rotation_angle); CHECKERR - - if (! frustum->IsBoxVisible(model_matrix * vec4(minp, 1.0), model_matrix * vec4(maxp, 1.0))) - return; - - shader_program->set("model", model_matrix); CHECKERR - - glBindVertexArray(VAO); CHECKERR - for (int i = 0; i < textures.size(); i++) { - textures[i].bind(); CHECKERR - glDrawArrays(GL_TRIANGLES, i * vertices_per_texture, vertices_per_texture); CHECKERR - } - glBindVertexArray(0); CHECKERR - glBindTexture(GL_TEXTURE_2D, 0); CHECKERR - - rendering = false; -} - -bool Mesh::isRendering() -{ - return rendering; -} - -void Mesh::die() -{ - prepare_death = true; -} - -Mesh::Mesh(Scene *s, const GLvoid *v, GLsizei vs): pos(0), size(1), rotation_axis(0, 1, 0), scene(s), vertices_size(vs) -{ - if (! v || ! vs) - throw runtime_error("Invalid Mesh configuration"); - vertices = malloc(vs); - memcpy(vertices, v, vs); - scene->add(this); -} - -Mesh::~Mesh() -{ - scene->remove(this); - if (VAO) { - glDeleteVertexArrays(1, &VAO); CHECKERR - } - if (VBO) { - glDeleteBuffers(1, &VAO); CHECKERR - } -} - -void Mesh::configure() -{ - 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; - configured = true; -} diff --git a/src/dragonblocks/mesh.hpp b/src/dragonblocks/mesh.hpp deleted file mode 100644 index 4dafcc9..0000000 --- a/src/dragonblocks/mesh.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include "gl.hpp" -#include "texture.hpp" - -class Frustum; - -namespace dragonblocks -{ - class Scene; - class ShaderProgram; - - class Mesh - { - public: - class Animation - { - public: - static double grow_time; - static double flyin_time; - static double flyin_offset; - static double rotate_speed; - - enum Type - { - NONE, - FLYIN, - GROW, - ROTATE - }; - - glm::mat4 getModelMatrix(double, glm::vec3, glm::vec3, glm::vec3, float); - - Animation() = default; - Animation(Type, void (*)(void *) = nullptr, void * = nullptr); - Animation(const Animation &) = default; - - private: - Type type = Type::NONE; - double time_left; - void (*on_finish)(void *); - void *extra_data; - bool expires; - }; - - int vertices_per_texture; - glm::vec3 pos, size, rotation_axis; - glm::vec3 minp, maxp; - float rotation_angle = 0; - std::vector textures; - Animation animation; - - void render(double dtime, ShaderProgram *, Frustum *); - bool isRendering(); - void die(); - - Mesh(Scene *, const GLvoid *, GLsizei); - ~Mesh(); - - private: - GLuint VAO = 0, VBO = 0; - Scene *scene; - GLvoid *vertices = NULL; - GLsizeiptr vertices_size; - bool configured = false; - bool rendering = false; - bool prepare_death = false; - bool do_delete = false; - - void configure(); - }; -} diff --git a/src/dragonblocks/mesh_gen_mgr.cpp b/src/dragonblocks/mesh_gen_mgr.cpp deleted file mode 100644 index 7d0c0b6..0000000 --- a/src/dragonblocks/mesh_gen_mgr.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#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 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); -} diff --git a/src/dragonblocks/mesh_gen_mgr.hpp b/src/dragonblocks/mesh_gen_mgr.hpp deleted file mode 100644 index 57b6192..0000000 --- a/src/dragonblocks/mesh_gen_mgr.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -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 queued_jobs; - std::queue active_jobs; - std::thread mesh_gen_thread; - }; -} diff --git a/src/dragonblocks/player.cpp b/src/dragonblocks/player.cpp deleted file mode 100644 index b007d79..0000000 --- a/src/dragonblocks/player.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include "camera.hpp" -#include "input_handler.hpp" -#include "map.hpp" -#include "player.hpp" - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -Player* Player::localplayer = nullptr; - -Player *Player::createLocalplayer(Camera *c, InputHandler *i, Map *m) -{ - if (localplayer) - throw runtime_error("Localplayer already exists"); - return localplayer = new Player(c, i, m); -} - -void Player::staticMouseHandler(double dtime, double x, double y) -{ - localplayer->mouseHandler(dtime, x, y); -} - -void Player::staticKeyHandler(double dtime, set keys) -{ - localplayer->keyHandler(dtime, keys); -} - -void Player::mouseHandler(double dtime, double x, double y) -{ - yaw += x; - pitch -= y; - pitch = clamp(pitch, -89.0, 89.0); - camera->update(yaw, pitch); -} - -void Player::keyHandler(double dtime, set keys) -{ - vec3 vel = vec3(speed * dtime); - vec3 front = camera->front(), right = camera->right(), up = camera->up(); - if (! pitch_move) { - front = normalize(vec3(front.x, 0, front.z)); - up = normalize(vec3(0, up.y, 0)); - } - if (keys.find(GLFW_KEY_W) != keys.end()) { - pos += vel * front; - } else if (keys.find(GLFW_KEY_S) != keys.end()) { - pos -= vel * front; - } - if (keys.find(GLFW_KEY_D) != keys.end()) { - pos += vel * right; - } else if (keys.find(GLFW_KEY_A) != keys.end()) { - pos -= vel * right; - } - if (keys.find(GLFW_KEY_SPACE) != keys.end()) { - pos += vel * up; - } else if (keys.find(GLFW_KEY_LEFT_SHIFT) != keys.end()) { - pos -= vel * up; - } - camera->pos = pos; - loadChunks(); -} - -void Player::loadChunks() -{ - ivec3 chunkp = Map::getChunkPos(pos); - for (int x = chunkp.x - 1; x <= chunkp.x + 1; x++) { - for (int y = chunkp.y - 1; y < chunkp.y + 1; y++) { - for (int z = chunkp.z - 1; z <= chunkp.z + 1; z++) { - map->createChunk(ivec3(x, y, z)); - } - } - } -} - -Player::Player(Camera *c, InputHandler *i, Map *m) : camera(c), input_handler(i), map(m) -{ - input_handler->listenFor(GLFW_KEY_W); - input_handler->listenFor(GLFW_KEY_A); - input_handler->listenFor(GLFW_KEY_S); - input_handler->listenFor(GLFW_KEY_D); - input_handler->listenFor(GLFW_KEY_SPACE); - input_handler->listenFor(GLFW_KEY_LEFT_SHIFT); - - input_handler->addMouseHandler(Player::staticMouseHandler); - input_handler->addKeyHandler(Player::staticKeyHandler); -} diff --git a/src/dragonblocks/player.hpp b/src/dragonblocks/player.hpp deleted file mode 100644 index 81bd5e6..0000000 --- a/src/dragonblocks/player.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include "gl.hpp" - -namespace dragonblocks -{ - class Camera; - class InputHandler; - class Map; - - class Player - { - public: - static Player *createLocalplayer(Camera *, InputHandler *, Map *); - - glm::vec3 pos; - bool pitch_move; - double yaw, pitch; - double speed; - - private: - static Player *localplayer; - - static void staticMouseHandler(double, double, double); - static void staticKeyHandler(double, std::set); - - Camera *camera; - InputHandler *input_handler; - Map *map; - - void mouseHandler(double, double, double); - void keyHandler(double, std::set); - void loadChunks(); - - Player(Camera *, InputHandler *, Map *); - }; -} diff --git a/src/dragonblocks/render_engine.cpp b/src/dragonblocks/render_engine.cpp deleted file mode 100644 index fb23d35..0000000 --- a/src/dragonblocks/render_engine.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include "FrustumCull.h" -#include "camera.hpp" -#include "gldebug.hpp" -#include "input_handler.hpp" -#include "mesh_gen_mgr.hpp" -#include "render_engine.hpp" -#include "scene.hpp" -#include "shader_program.hpp" -#include "window.hpp" - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -void RenderEngine::render() -{ - double dtime = glfwGetTime() - last_time; - last_time = glfwGetTime(); - - input_handler->processInput(dtime); - - glEnable(GL_DEPTH_TEST); CHECKERR - glEnable(GL_CULL_FACE); CHECKERR - glCullFace(GL_BACK); CHECKERR - glFrontFace(GL_CW); CHECKERR - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); CHECKERR - - updateViewMatrix(); CHECKERR - - Frustum frustum(projection_matrix * view_matrix); - - scene->render(dtime, shader_program, &frustum); - - window->swapBuffers(); CHECKERR - glfwPollEvents(); CHECKERR -} - -bool RenderEngine::running() -{ - return ! window->shouldClose(); -} - -void RenderEngine::updateProjectionMatrix() -{ - dvec2 bounds = window->getSize(); - projection_matrix = perspective(radians(fov), bounds.x / bounds.y, 0.01, render_distance); - shader_program->set("projection", projection_matrix); CHECKERR -} - -void RenderEngine::updateViewMatrix() -{ - view_matrix = camera->getViewMatrix(); - shader_program->set("view", view_matrix); CHECKERR -} - -void RenderEngine::setSky(vec3 sky) -{ - glClearColor(sky.r, sky.g, sky.b, 1.0); CHECKERR - shader_program->set("sky", sky); CHECKERR -} - -void RenderEngine::setRenderDistance(double d) -{ - render_distance = d; - updateProjectionMatrix(); -} - -void RenderEngine::setFov(double f) -{ - fov = f; - updateProjectionMatrix(); -} - -void RenderEngine::startMeshGenMgr() -{ - mesh_gen_mgr->start(); -} - -RenderEngine::RenderEngine() -{ - if (! glfwInit()) - throw runtime_error("Failed to initialize GLFW"); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - window = Window::create(this); - camera = new Camera; - input_handler = new InputHandler(window); - mesh_gen_mgr = new MeshGenMgr; - scene = new Scene; - - GLenum glew_init_err = glewInit(); - if (glew_init_err != GLEW_OK) - throw runtime_error("Failed to initialize GLEW"); - - shader_program = new ShaderProgram("shaders"); - - setSky(vec3(1.0, 1.0, 1.0)); - setRenderDistance(16); - setFov(45); - - last_time = glfwGetTime(); -} - -RenderEngine::~RenderEngine() -{ - delete window; - delete camera; - delete input_handler; - delete mesh_gen_mgr; - delete scene; - delete shader_program; -} diff --git a/src/dragonblocks/render_engine.hpp b/src/dragonblocks/render_engine.hpp deleted file mode 100644 index c1732c6..0000000 --- a/src/dragonblocks/render_engine.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "gl.hpp" - -namespace dragonblocks -{ - class Camera; - class InputHandler; - class MeshGenMgr; - class ShaderProgram; - class Scene; - class Window; - - class RenderEngine - { - public: - Camera *camera; - InputHandler *input_handler; - MeshGenMgr *mesh_gen_mgr; - Scene *scene; - ShaderProgram *shader_program; - Window *window; - - void render(); - bool running(); - void updateViewMatrix(); - void updateProjectionMatrix(); - void setSky(glm::vec3); - void setRenderDistance(double); - void setFov(double); - void startMeshGenMgr(); - - - RenderEngine(); - ~RenderEngine(); - - private: - glm::mat4 view_matrix, projection_matrix; - double last_time; - double render_distance; - double fov; - }; -} diff --git a/src/dragonblocks/scene.cpp b/src/dragonblocks/scene.cpp deleted file mode 100644 index 2f74bb2..0000000 --- a/src/dragonblocks/scene.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "mesh.hpp" -#include "scene.hpp" - -using namespace std; -using namespace dragonblocks; - -void Scene::add(Mesh *m) -{ - meshes.insert(m); -} - -void Scene::remove(Mesh *m) -{ - meshes.erase(m); -} - -void Scene::render(double dtime, ShaderProgram *shader_program, Frustum *frustum) -{ - auto renderlist = meshes; - for (auto it = renderlist.begin(); it != renderlist.end(); it++) { - Mesh *mesh = *it; - mesh->render(dtime, shader_program, frustum); - } -} - -void Scene::clear() -{ - meshes.clear(); -} - -Scene::~Scene() -{ - clear(); -} diff --git a/src/dragonblocks/scene.hpp b/src/dragonblocks/scene.hpp deleted file mode 100644 index fc0f62d..0000000 --- a/src/dragonblocks/scene.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -class Frustum; - -namespace dragonblocks -{ - class Mesh; - class ShaderProgram; - - class Scene { - public: - void add(Mesh *); - void remove(Mesh *); - void render(double, ShaderProgram *, Frustum *); - void clear(); - void run(); - - ~Scene(); - - private: - std::set meshes; - }; -} diff --git a/src/dragonblocks/shader_program.cpp b/src/dragonblocks/shader_program.cpp deleted file mode 100644 index 812a1ed..0000000 --- a/src/dragonblocks/shader_program.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include -#include -#include -#include -#include "shader_program.hpp" - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -map ShaderProgram::shadertypes = { - {"vertex", GL_VERTEX_SHADER}, - {"fragment", GL_FRAGMENT_SHADER}, -}; - -ShaderProgram::ShaderProgram(const string &global_path) -{ - int success; - char buffer[1024] = {}; - vector shaders; - - id = glCreateProgram(); - - for (auto it = ShaderProgram::shadertypes.begin(); it != ShaderProgram::shadertypes.end(); it++) { - const char *c_code; - GLuint shader; - string path, code; - ifstream file; - stringstream stream; - - path = global_path + "/" + it->first + ".glsl"; - file.exceptions(ifstream::failbit | ifstream::badbit); - file.open(path); - stream << file.rdbuf(); - code = stream.str(); - c_code = code.c_str(); - - shader = glCreateShader(it->second); - shaders.push_back(shader); - glShaderSource(shader, 1, &c_code, NULL); - glCompileShader(shader); - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (! success) { - glGetShaderInfoLog(shader, 1024, NULL, buffer); - throw runtime_error("Failed to compile " + it->first + " shader: " + buffer); - } - glAttachShader(id, shader); - } - - glLinkProgram(id); - glGetProgramiv(id, GL_LINK_STATUS, &success); - if (! success) { - glGetProgramInfoLog(id, 1024, NULL, buffer); - throw runtime_error(string("Failed to link shader program: ") + buffer); - } - - for (auto it = shaders.begin(); it != shaders.end(); it++) { - glDeleteShader(*it); - } -} - -void ShaderProgram::use() const -{ - glUseProgram(id); -} - -void ShaderProgram::set(const string &name, bool value) -{ - use(); - glUniform1i(glGetUniformLocation(id, name.c_str()), (int) value); -} - -void ShaderProgram::set(const string &name, int value) -{ - use(); - glUniform1i(glGetUniformLocation(id, name.c_str()), value); -} - -void ShaderProgram::set(const string &name, float value) -{ - use(); - glUniform1f(glGetUniformLocation(id, name.c_str()), value); -} - -void ShaderProgram::set(const string &name, mat4 value) -{ - use(); - glUniformMatrix4fv(glGetUniformLocation(id, name.c_str()), 1, GL_FALSE, value_ptr(value)); -} - -void ShaderProgram::set(const string &name, vec3 value) -{ - use(); - glUniform3f(glGetUniformLocation(id, name.c_str()), value.x, value.y, value.z); -} - -ShaderProgram::~ShaderProgram() -{ - glDeleteProgram(id); -} diff --git a/src/dragonblocks/shader_program.hpp b/src/dragonblocks/shader_program.hpp deleted file mode 100644 index 0496c19..0000000 --- a/src/dragonblocks/shader_program.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include -#include "gl.hpp" - -namespace dragonblocks -{ - class ShaderProgram - { - public: - static std::map shadertypes; - - void use() const; - void set(const std::string &, bool); - void set(const std::string &, int); - void set(const std::string &, float); - void set(const std::string &, glm::mat4); - void set(const std::string &, glm::vec3); - - ShaderProgram(const std::string &); - ~ShaderProgram(); - - private: - GLuint id; - }; -} diff --git a/src/dragonblocks/texture.cpp b/src/dragonblocks/texture.cpp deleted file mode 100644 index ab0b4b1..0000000 --- a/src/dragonblocks/texture.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -#include "gldebug.hpp" -#include "log.hpp" -#include "texture.hpp" - -using namespace std; -using namespace dragonblocks; - -bool Texture::mipmap; -bool Texture::bilinear_filter; -GLenum Texture::min_filter, Texture::mag_filter; - -void Texture::initArgs() -{ - min_filter = mag_filter = bilinear_filter ? GL_LINEAR : GL_NEAREST; - if (mipmap) { - if (min_filter == GL_NEAREST) { - min_filter = GL_NEAREST_MIPMAP_NEAREST; - } else { - min_filter = GL_LINEAR_MIPMAP_NEAREST; - } - } - stbi_set_flip_vertically_on_load(true); -} - -void Texture::bind() const -{ - glBindTexture(GL_TEXTURE_2D, id); CHECKERR -} - -void Texture::load(const string &path) -{ - int width, height, nrChannels; - 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); CHECKERR - bind(); - 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); CHECKERR - stbi_image_free(data); - glBindTexture(GL_TEXTURE_2D, 0); CHECKERR - log("Loaded texture " + path); -} - diff --git a/src/dragonblocks/texture.hpp b/src/dragonblocks/texture.hpp deleted file mode 100644 index eb9e0c2..0000000 --- a/src/dragonblocks/texture.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include "gl.hpp" - -namespace dragonblocks -{ - class Texture - { - public: - static bool mipmap; - static bool bilinear_filter; - - static void initArgs(); - - void bind() const; - void load(const std::string &); - Texture() = default; - Texture(const Texture &) = default; - - private: - static GLenum min_filter, mag_filter; - - GLuint id; - }; -} diff --git a/src/dragonblocks/window.cpp b/src/dragonblocks/window.cpp deleted file mode 100644 index 9bb3541..0000000 --- a/src/dragonblocks/window.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include "render_engine.hpp" -#include "window.hpp" - -using namespace std; -using namespace glm; -using namespace dragonblocks; - -Window *Window::singleton = nullptr; - -Window *Window::create(RenderEngine *r) -{ - if (singleton) - throw runtime_error("Window already exists"); - return singleton = new Window(r); -} - -void Window::windowPosCallback(GLFWwindow *id, int x, int y) -{ - singleton->posInput(x, y); -} - -void Window::framebufferSizeCallback(GLFWwindow *id, int width, int height) -{ - glViewport(0, 0, width, height); - singleton->render_engine->updateProjectionMatrix(); - singleton->sizeInput(width, height); -} - -void Window::cursorPosCallback(GLFWwindow *id, double x, double y) -{ - singleton->cursorInput(x, y); -} - -void Window::setTitle(const string &title) -{ - glfwSetWindowTitle(id, title.c_str()); -} - -void Window::setSize(int width, int height) -{ - glfwSetWindowSize(id, width, height); -} - -void Window::setPos(int x, int y) -{ - glfwSetWindowPos(id, x, y); -} - -void Window::toggleFullscreen() -{ - fullscreen = ! fullscreen; - - if (fullscreen) { - GLFWmonitor *monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode *vidmode = glfwGetVideoMode(monitor); - glfwSetWindowMonitor(id, monitor, 0, 0, vidmode->width, vidmode->height, 0); - } - else - glfwSetWindowMonitor(id, nullptr, nfs_x, nfs_y, nfs_width, nfs_height, 0); -} - -void Window::close() -{ - glfwDestroyWindow(id); -} - -void Window::swapBuffers() -{ - glfwSwapBuffers(id); -} - -bool Window::shouldClose() const -{ - return glfwWindowShouldClose(id); -} - -bool Window::wasKeyDown(int key) const -{ - return glfwGetKey(id, key) == GLFW_PRESS; -} - -void Window::makeContextCurrent() const -{ - glfwMakeContextCurrent(id); -} - -ivec2 Window::getSize() const -{ - return ivec2(width, height); -} - -ivec2 Window::getCursorPos() const -{ - return ivec2(cursor_x, cursor_y); -} - -ivec2 Window::getCursorDelta() -{ - ivec2 delta(cursor_delta_x, cursor_delta_y); - cursor_delta_x = cursor_delta_y = 0; - return delta; -} - -void Window::posInput(int x, int y) -{ - if (! fullscreen) { - nfs_x = x; - nfs_y = y; - } -} - -void Window::sizeInput(int w, int h) -{ - width = w; - height = h; - if (! fullscreen) { - nfs_width = width; - nfs_height = height; - } -} - -void Window::cursorInput(int x, int y) -{ - int lx = cursor_x; - int ly = cursor_y; - cursor_delta_x = x - lx; - cursor_delta_y = y - ly; - cursor_x = x; - cursor_y = y; -} - -Window::~Window() -{ - close(); -} - -Window::Window(RenderEngine *r) : render_engine(r) -{ - fullscreen = false; - width = nfs_width = 100; - height = nfs_height = 100; - cursor_x = cursor_y = cursor_delta_x = cursor_delta_y = 0; - id = glfwCreateWindow(width, height, "libdragonblocks.so", NULL, NULL); - if (! id) { - glfwTerminate(); - throw runtime_error("Failed to create GLFW window"); - } - makeContextCurrent(); - glfwSetInputMode(id, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - glfwSetWindowPosCallback(id, Window::windowPosCallback); - glfwSetFramebufferSizeCallback(id, Window::framebufferSizeCallback); - glfwSetCursorPosCallback(id, Window::cursorPosCallback); -} - - diff --git a/src/dragonblocks/window.hpp b/src/dragonblocks/window.hpp deleted file mode 100644 index 1ca300a..0000000 --- a/src/dragonblocks/window.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include "gl.hpp" - -namespace dragonblocks -{ - class RenderEngine; - - class Window - { - public: - static Window *create(RenderEngine *); - static void windowPosCallback(GLFWwindow *, int, int); - static void framebufferSizeCallback(GLFWwindow *, int, int); - static void cursorPosCallback(GLFWwindow *, double, double); - - void setTitle(const std::string &); - void setPos(int, int); - void setSize(int, int); - void toggleFullscreen(); - void close(); - void swapBuffers(); - bool shouldClose() const; - bool wasKeyDown(int) const; - void makeContextCurrent() const; - glm::ivec2 getSize() const; - glm::ivec2 getCursorPos() const; - glm::ivec2 getCursorDelta(); - - ~Window(); - - private: - static Window *singleton; - - RenderEngine *render_engine; - GLFWwindow *id; - bool fullscreen; - int width, height; - int nfs_width, nfs_height, nfs_x, nfs_y; - int cursor_x, cursor_y, cursor_delta_x, cursor_delta_y; - - void posInput(int, int); - void sizeInput(int, int); - void cursorInput(int, int); - - Window(RenderEngine *); - }; -} - diff --git a/src/dragonblocks/world.cpp b/src/dragonblocks/world.cpp deleted file mode 100644 index 22f48a1..0000000 --- a/src/dragonblocks/world.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "world.hpp" diff --git a/src/dragonblocks/world.hpp b/src/dragonblocks/world.hpp deleted file mode 100644 index 33091e9..0000000 --- a/src/dragonblocks/world.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "map.hpp" - -namespace dragonblocks -{ - class World - { - public: - Map map; - }; -} diff --git a/src/dragonblockslauncher/CMakeLists.txt b/src/dragonblockslauncher/CMakeLists.txt deleted file mode 100644 index 0a0098c..0000000 --- a/src/dragonblockslauncher/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 3.0) - -add_executable(dragonblockslauncher - launcher.cpp - main.cpp -) - -target_link_libraries(dragonblockslauncher dl) - -target_include_directories(dragonblockslauncher PUBLIC - "${PROJECT_SOURCE_DIR}/lib/" - "${PROJECT_SOURCE_DIR}/src/" -) diff --git a/src/dragonblockslauncher/launcher.cpp b/src/dragonblockslauncher/launcher.cpp deleted file mode 100644 index 1a44919..0000000 --- a/src/dragonblockslauncher/launcher.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include "dragonblockslauncher/launcher.hpp" - -using namespace dragonblockslauncher; - -void dragonblockslauncher::log(std::string message) -{ - std::cout << "[Launcher] " << message << std::endl; -} - -void dragonblockslauncher::fail(std::string error, std::string details) -{ - std::cerr - << "Unable to launch dragonblocks: " << error << std::endl - << "Details: " << details << std::endl; - abort(); -} - -void dragonblockslauncher::launchDragonblocks(std::string gametype) -{ - void* handle; - std::string filename; - std::string start_function_name; - void (*start_function)(); - - filename = "./libdragonblocks.so"; - - log("Opening dynamic library at " + filename); - - handle = dlmopen(LM_ID_BASE, filename.c_str(), RTLD_NOW | RTLD_GLOBAL); - - if (!handle) - fail("Failed to load " + filename, dlerror()); - - if (gametype != "server" && gametype != "client" && gametype != "mainmenu") - fail("Trying to start dragonblocks with unknown gametype", "gameype = " + gametype); - - start_function_name = "_dragonblocks_start_" + gametype; - - log("Obtaining start function pointer"); - - start_function = (void (*)())dlsym(handle, start_function_name.c_str()); - - if (!start_function) - fail("Failed to obtain dragonblocks start function pointer", dlerror()); - - log("Launching dragonblocks"); - - (*start_function)(); -} diff --git a/src/dragonblockslauncher/launcher.hpp b/src/dragonblockslauncher/launcher.hpp deleted file mode 100644 index d1fcab1..0000000 --- a/src/dragonblockslauncher/launcher.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -namespace dragonblockslauncher -{ - void log(std::string); - void fail(std::string, std::string); - void launchDragonblocks(std::string); -} diff --git a/src/dragonblockslauncher/main.cpp b/src/dragonblockslauncher/main.cpp deleted file mode 100644 index b260649..0000000 --- a/src/dragonblockslauncher/main.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "dragonblockslauncher/launcher.hpp" - -int main(int argc, char *argv[]) -{ - dragonblockslauncher::launchDragonblocks("client"); -} diff --git a/src/entity.cpp b/src/entity.cpp new file mode 100644 index 0000000..0c634fa --- /dev/null +++ b/src/entity.cpp @@ -0,0 +1,53 @@ +#include "entity.hpp" + +using namespace glm; +using namespace dragonblocks; + +void IEntity::setPos(vec3 p) +{ +} + +vec3 IEntity::getPos() +{ + return vec3(0); +} + +void IEntity::setSize(vec3 s) +{ +} + +vec3 IEntity::getSize() +{ + return vec3(0); +} + +void IEntity::setRotationAxis(vec3 r) +{ +} + +vec3 IEntity::getRotationAxis() +{ + return vec3(0); +} + +void IEntity::setRotationAngle(double r) +{ +} + +double IEntity::getRotationAngle() +{ + return 0.0; +} + +void IEntity::setVisible(bool v) +{ +} + +bool IEntity::isVisible() +{ + return false; +} + +IEntity::IEntity(Map *m) : map(m) +{ +} diff --git a/src/entity.hpp b/src/entity.hpp new file mode 100644 index 0000000..e727374 --- /dev/null +++ b/src/entity.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "async_mgr.hpp" +#include "gl.hpp" +#include "tile_def.hpp" + +namespace dragonblocks +{ + class Map; + + class IEntity + { + public: + /*double vertical_speed; + double vertical_acceleration; + double horizontal_speed; + double horizontal_max_speed; + double horizontal_acceleration; + glm::vec3 horizontal_move_dir; + glm::vec3 vertical_move_dir; + */ + double speed; + + virtual void setPos(glm::vec3); + virtual glm::vec3 getPos(); + virtual void setSize(glm::vec3); + virtual glm::vec3 getSize(); + virtual void setRotationAxis(glm::vec3); + virtual glm::vec3 getRotationAxis(); + virtual void setRotationAngle(double); + virtual double getRotationAngle(); + virtual void setVisible(bool); + virtual bool isVisible(); + + protected: + Map *map; + + IEntity(Map *); + }; +} diff --git a/src/face_dir.cpp b/src/face_dir.cpp new file mode 100644 index 0000000..677623b --- /dev/null +++ b/src/face_dir.cpp @@ -0,0 +1,12 @@ +#include "face_dir.hpp" + +using namespace glm; + +ivec3 dragonblocks::face_dir[6] = { + {+0, +0, -1}, + {+0, +0, +1}, + {-1, +0, +0}, + {+1, +0, +0}, + {+0, -1, +0}, + {+0, +1, +0}, +}; diff --git a/src/face_dir.hpp b/src/face_dir.hpp new file mode 100644 index 0000000..32034ef --- /dev/null +++ b/src/face_dir.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "gl.hpp" + +namespace dragonblocks +{ + extern glm::ivec3 face_dir[6]; +} diff --git a/src/game.cpp b/src/game.cpp new file mode 100644 index 0000000..651f223 --- /dev/null +++ b/src/game.cpp @@ -0,0 +1,24 @@ +#include "block_def.hpp" +#include "game.hpp" +#include "mapgen.hpp" +#include "tile_def.hpp" + +using namespace dragonblocks; + +Game::Game(Mapgen *m) : mapgen(m) +{ + grass_texture.load("textures/grass.png"); + grass_side_texture.load("textures/grass_side.png"); + dirt_texture.load("textures/dirt.png"); + stone_texture.load("textures/stone.png"); + + air = new BlockDef("dragonblocks:air"); + grass = new BlockDef("dragonblocks:grass", TileDef({grass_side_texture, grass_side_texture, grass_side_texture, grass_side_texture, dirt_texture, grass_texture})); + dirt = new BlockDef("dragonblocks:dirt", dirt_texture); + stone = new BlockDef("dragonblocks:stone", stone_texture); + + mapgen->air_def = air; + mapgen->grass_def = grass; + mapgen->dirt_def = dirt; + mapgen->stone_def = stone; +} diff --git a/src/game.hpp b/src/game.hpp new file mode 100644 index 0000000..1168482 --- /dev/null +++ b/src/game.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "texture.hpp" + +namespace dragonblocks +{ + class BlockDef; + class Mapgen; + + class Game + { + public: + BlockDef *air, *grass, *dirt, *stone; + Mapgen *mapgen; + Texture grass_texture, grass_side_texture, dirt_texture, stone_texture; + + Game(Mapgen *); + }; +} diff --git a/src/gl.cpp b/src/gl.cpp new file mode 100644 index 0000000..7dc542c --- /dev/null +++ b/src/gl.cpp @@ -0,0 +1,27 @@ +#include +#include +#include "gl.hpp" + +using namespace std; +using namespace dragonblocks; + +GLenum dragonblocks::checkGLError(const char *file, int line) +{ + GLenum errorCode; + if ((errorCode = glGetError()) != GL_NO_ERROR) + { + string error; + switch (errorCode) + { + case GL_INVALID_ENUM: error = "INVALID_ENUM"; break; + case GL_INVALID_VALUE: error = "INVALID_VALUE"; break; + case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break; + case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break; + case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break; + case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break; + case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break; + } + cout << "OpenGL Error: " << error << " | " << file << " (" << line << ")" << endl; + } + return errorCode; +} diff --git a/src/gl.hpp b/src/gl.hpp new file mode 100644 index 0000000..3f2e59d --- /dev/null +++ b/src/gl.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include + +//#define CHECKERR dragonblocks::checkGLError(__FILE__, __LINE__); +#define CHECKERR + +namespace dragonblocks +{ + GLenum checkGLError(const char *file, int line); +} diff --git a/src/input_handler.cpp b/src/input_handler.cpp new file mode 100644 index 0000000..418706e --- /dev/null +++ b/src/input_handler.cpp @@ -0,0 +1,58 @@ +#include "camera.hpp" +#include "input_handler.hpp" +#include "window.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +void InputHandler::processInput(double dtime) +{ + cursor_delta = vec2(mouse_sensitivity * dtime) * (vec2)window->getCursorDelta(); + was_down.clear(); + for (auto it = is_down.begin(); it != is_down.end(); it++) { + int key = *it; + if (! window->isKeyDown(key)) { + was_down.insert(key); + } + } + is_down.clear(); + for (auto it = listened_keys.begin(); it != listened_keys.end(); it++) { + int key = *it; + if (window->isKeyDown(key)) { + is_down.insert(key); + } + } +} + +void InputHandler::listenFor(int key) +{ + listened_keys.insert(key); +} + +void InputHandler::dontListenFor(int key) +{ + listened_keys.erase(key); +} + +bool InputHandler::isKeyDown(int key) +{ + return is_down.find(key) != is_down.end(); +} + +bool InputHandler::wasKeyDown(int key) +{ + return was_down.find(key) != was_down.end(); +} + +vec2 InputHandler::getCursorDelta() +{ + return cursor_delta; +} + +void InputHandler::setWindow(Window *w) +{ + if (! window) { + window = w; + } +} diff --git a/src/input_handler.hpp b/src/input_handler.hpp new file mode 100644 index 0000000..23939d9 --- /dev/null +++ b/src/input_handler.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "gl.hpp" + +namespace dragonblocks +{ + class Camera; + class Window; + + class InputHandler + { + public: + double mouse_sensitivity; + + void processInput(double); + void listenFor(int); + void dontListenFor(int); + bool isKeyDown(int); + bool wasKeyDown(int); + glm::vec2 getCursorDelta(); + void setWindow(Window *); + + private: + Window *window; + std::set listened_keys; + std::set is_down; + std::set was_down; + glm::vec2 cursor_delta; + }; +} diff --git a/src/launcher/main.c b/src/launcher/main.c new file mode 100644 index 0000000..c5fdf67 --- /dev/null +++ b/src/launcher/main.c @@ -0,0 +1,53 @@ +#include +#include +#include +#define __USE_GNU +#include + +void launch_dragonblocks(const char *gametype) +{ + void* handle; + const char *filename; + char *start_function_name; + void (*start_function)(); + + filename = "./libdragonblocks.so"; + + printf("Opening %s\n", filename); + + handle = dlmopen(LM_ID_BASE, filename, RTLD_NOW | RTLD_GLOBAL); + + if (! handle) { + printf("Failed to load %s\n\tDetails: %s\n", filename, dlerror()); + abort(); + } + + if (strcmp(gametype, "client")) { // && strcmp(gametype, "server") && strcmp(gametype, "menu") + printf("Trying to start dragonblocks with unknown gametype (\"%s\")\n", gametype); + abort(); + } + + start_function_name = malloc(strlen("_dragonblocks_start_") + strlen(gametype) + 1); + strcpy(start_function_name, "_dragonblocks_start_"); + strcat(start_function_name, gametype); + + printf("Obtaing pointer to start function\n"); + + start_function = (void (*)())dlsym(handle, start_function_name); + + free(start_function_name); + + if (! start_function) { + printf("Failed to obtain dragonblocks start function pointer\n\tDetails: %s\n", dlerror()); + abort(); + } + + printf("Starting dragonblocks\n"); + + (*start_function)(); +} + +int main(int argc, char *argv[]) +{ + launch_dragonblocks("client"); +} diff --git a/src/local_entity.cpp b/src/local_entity.cpp new file mode 100644 index 0000000..a69593d --- /dev/null +++ b/src/local_entity.cpp @@ -0,0 +1,71 @@ +#include "animations.hpp" +#include "box_vertices.hpp" +#include "local_entity.hpp" +#include "mesh.hpp" + +using namespace glm; +using namespace dragonblocks; + +void LocalEntity::setPos(vec3 p) +{ + mesh->pos = p; +} + +vec3 LocalEntity::getPos() +{ + return mesh->pos; +} + +void LocalEntity::setSize(vec3 s) +{ + mesh->minp = -(s / 2.0f); + mesh->maxp = +(s / 2.0f); + mesh->size = s; +} + +vec3 LocalEntity::getSize() +{ + return mesh->size; +} + +void LocalEntity::setRotationAxis(vec3 r) +{ + mesh->rotation_axis = r; +} + +vec3 LocalEntity::getRotationAxis() +{ + return mesh->rotation_axis; +} + +void LocalEntity::setRotationAngle(double r) +{ + mesh->rotation_angle = r; +} + +double LocalEntity::getRotationAngle() +{ + return mesh->rotation_angle; +} + +void LocalEntity::setVisible(bool v) +{ + mesh->visible = v; +} + +bool LocalEntity::isVisible() +{ + return mesh->visible; +} + +LocalEntity::LocalEntity(Map *m, Scene *s, const TileDef &t, ShaderProgram *sh) : IEntity(m), tile_def(t) +{ + mesh = new Mesh(s, sh, &box_vertices[0][0][0], 6 * 6 * 5); + mesh->textures = tile_def.tiles; + mesh->vertices_per_texture = 6; +} + +LocalEntity::~LocalEntity() +{ + mesh->die(); +} diff --git a/src/local_entity.hpp b/src/local_entity.hpp new file mode 100644 index 0000000..1248bc1 --- /dev/null +++ b/src/local_entity.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "async_mgr.hpp" +#include "entity.hpp" +#include "gl.hpp" +#include "tile_def.hpp" + +namespace dragonblocks +{ + class Map; + class Mesh; + class Scene; + class ShaderProgram; + + class LocalEntity : public IEntity + { + public: + void setPos(glm::vec3); + glm::vec3 getPos(); + void setSize(glm::vec3); + glm::vec3 getSize(); + void setRotationAxis(glm::vec3); + glm::vec3 getRotationAxis(); + void setRotationAngle(double); + double getRotationAngle(); + void setVisible(bool); + bool isVisible(); + void step(double); + + LocalEntity(Map *, Scene *, const TileDef &, ShaderProgram *); + ~LocalEntity(); + + protected: + TileDef tile_def; + Mesh *mesh; + }; +} diff --git a/src/local_player.cpp b/src/local_player.cpp new file mode 100644 index 0000000..c0f4a86 --- /dev/null +++ b/src/local_player.cpp @@ -0,0 +1,75 @@ +#include +#include "camera.hpp" +#include "input_handler.hpp" +#include "local_player.hpp" +#include "map.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +void LocalPlayer::step(double dtime) +{ + // Cursor input + vec2 cd = input_handler->getCursorDelta(); + yaw += cd.x; + pitch -= cd.y; + pitch = clamp(pitch, -89.0, 89.0); + + // Key input + vec3 pos = getPos(); + vec3 vel = vec3(speed * dtime); + vec3 front = camera->front(), right = camera->right(), up = camera->up(); + if (! pitch_move) { + front = normalize(vec3(front.x, 0, front.z)); + up = normalize(vec3(0, up.y, 0)); + } + if (input_handler->isKeyDown(GLFW_KEY_W)) { + pos += vel * front; + } else if (input_handler->isKeyDown(GLFW_KEY_S)) { + pos -= vel * front; + } + if (input_handler->isKeyDown(GLFW_KEY_D)) { + pos += vel * right; + } else if (input_handler->isKeyDown(GLFW_KEY_A)) { + pos -= vel * right; + } + if (input_handler->isKeyDown(GLFW_KEY_SPACE)) { + pos += vel * up; + } else if (input_handler->isKeyDown(GLFW_KEY_LEFT_SHIFT)) { + pos -= vel * up; + } + + if (input_handler->wasKeyDown(GLFW_KEY_C)) { + camera->toggleMode(); + } + + camera->update(yaw, pitch, pos); + setPos(pos); + setVisible(camera->thirdPerson()); + loadChunks(); +} + +void LocalPlayer::loadChunks() +{ + int dist = 4; + ivec3 chunkp = Map::getChunkPos(getPos()); + for (int x = chunkp.x - dist; x <= chunkp.x + dist; x++) { + for (int y = chunkp.y - dist; y < chunkp.y + dist; y++) { + for (int z = chunkp.z - dist; z <= chunkp.z + dist; z++) { + map->createChunk(ivec3(x, y, z)); + } + } + } +} + +LocalPlayer::LocalPlayer(Map *m, Scene *s, const TileDef &t, ShaderProgram *sh, Camera *c, InputHandler *i) : LocalEntity(m, s, t, sh), camera(c), input_handler(i) +{ + input_handler->listenFor(GLFW_KEY_W); + input_handler->listenFor(GLFW_KEY_A); + input_handler->listenFor(GLFW_KEY_S); + input_handler->listenFor(GLFW_KEY_D); + input_handler->listenFor(GLFW_KEY_SPACE); + input_handler->listenFor(GLFW_KEY_LEFT_SHIFT); + input_handler->listenFor(GLFW_KEY_C); +} diff --git a/src/local_player.hpp b/src/local_player.hpp new file mode 100644 index 0000000..8a061cb --- /dev/null +++ b/src/local_player.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include "local_entity.hpp" +#include "gl.hpp" + +namespace dragonblocks +{ + class Camera; + class InputHandler; + class Map; + class Scene; + class ShaderProgram; + + class LocalPlayer : public LocalEntity + { + public: + bool pitch_move; + double yaw, pitch; + + void step(double); + + LocalPlayer(Map *, Scene *, const TileDef &, ShaderProgram *, Camera *, InputHandler *); + + private: + static void staticMouseHandler(double, double, double); + static void staticKeyHandler(double, std::set); + + Camera *camera; + InputHandler *input_handler; + + void keyHandler(double, std::set); + void loadChunks(); + }; +} diff --git a/src/map.cpp b/src/map.cpp new file mode 100644 index 0000000..351cd31 --- /dev/null +++ b/src/map.cpp @@ -0,0 +1,75 @@ +#include +#include "map.hpp" +#include "mapgen.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +ivec3 Map::getChunkPos(const vec3 &p) +{ + return floor(p / (float)DRAGONBLOCKS_CHUNK_SIZE); +} + +ivec3 Map::getBlockPos(const ivec3 &p) +{ + 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 * DRAGONBLOCKS_MAP_SIZE + (uint16_t)p.z * DRAGONBLOCKS_MAP_SIZE * DRAGONBLOCKS_MAP_SIZE; +} + +const Block *Map::getBlock(const glm::ivec3 &p) +{ + + Chunk *chunk = getChunk(Map::getChunkPos(p)); + if (chunk) + return chunk->getBlock(Map::getBlockPos(p)); + return nullptr; +} + +void Map::setBlock(const glm::ivec3 &p, BlockDef *def) +{ + Chunk *chunk = getChunk(Map::getChunkPos(p)); + if (chunk) + chunk->setBlock(Map::getBlockPos(p), def); +} + +void Map::createChunk(const glm::ivec3 &p, const Chunk::Data &data) +{ + uint64_t poshash = Map::getChunkPosHash(p); + + if (chunks[poshash]) + return; + + chunks[poshash] = new Chunk(this, p, data, async_mgr, scene, shader_program); +} + +void Map::createChunk(const glm::ivec3 &p) +{ + if (! chunks[Map::getChunkPosHash(p)]) + createChunk(p, mapgen->generate(p)); +} + +Chunk *Map::getChunk(const glm::ivec3 &p) +{ + return chunks[Map::getChunkPosHash(p)]; +} + +void Map::clear() +{ + for (auto it = chunks.begin(); it != chunks.end(); it++) + delete it->second; + chunks.clear(); +} + +Map::Map(Mapgen *m, AsyncMgr *a, Scene *s, ShaderProgram *sh) : mapgen(m), async_mgr(a), scene(s), shader_program(sh) +{ +} + +Map::~Map() +{ + clear(); +} diff --git a/src/map.hpp b/src/map.hpp new file mode 100644 index 0000000..0bd941c --- /dev/null +++ b/src/map.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include "chunk.hpp" +#include "gl.hpp" + +#define DRAGONBLOCKS_MAP_SIZE 1000 + +namespace dragonblocks +{ + class AsyncMgr; + class BlockDef; + class Block; + class Mapgen; + class Scene; + class ShaderProgram; + + class Map + { + public: + static glm::ivec3 getChunkPos(const glm::vec3 &); + static glm::ivec3 getBlockPos(const glm::ivec3 &); + static uint16_t getChunkPosHash(const glm::ivec3 &); + + const Block *getBlock(const glm::ivec3 &); + const Block *getBlockRelativePos(Chunk *, const glm::ivec3 &); + void setBlock(const glm::ivec3 &, BlockDef *); + void createChunk(const glm::ivec3 &, const Chunk::Data &); + void createChunk(const glm::ivec3 &); + Chunk *getChunk(const glm::ivec3 &); + void clear(); + + Map(Mapgen *, AsyncMgr *, Scene *, ShaderProgram *); + ~Map(); + + private: + std::map chunks; + Mapgen *mapgen; + AsyncMgr *async_mgr; + Scene *scene; + ShaderProgram *shader_program; + }; +} diff --git a/src/mapgen.cpp b/src/mapgen.cpp new file mode 100644 index 0000000..5cad82c --- /dev/null +++ b/src/mapgen.cpp @@ -0,0 +1,35 @@ +#include +#include +#include "mapgen.hpp" + +using namespace glm; +using namespace dragonblocks; + +Chunk::Data Mapgen::generate(const ivec3 &chunkp) const +{ + Chunk::Data data; + vec3 minp = chunkp * ivec3(DRAGONBLOCKS_CHUNK_SIZE); + vec3 maxp = minp + vec3(DRAGONBLOCKS_CHUNK_SIZE); + int minx = minp.x, miny = minp.y, minz = minp.z, maxx = maxp.x, maxy = maxp.y, maxz = maxp.z; + for (int x = minx; x < maxx; x++) { + int rx = x - minx; + for (int z = minz; z < maxz; z++) { + int rz = z - minz; + int grass_layer = grass_layer_middle + grass_layer_range * perlin(vec2((float)x / 64, (float)z / 64)); + for (int y = miny; y < maxy; y++) { + int ry = y - miny; + BlockDef *blockdef; + if (y < grass_layer - 4) + blockdef = stone_def; + else if (y < grass_layer - 1) + blockdef = dirt_def; + else if (y < grass_layer) + blockdef = grass_def; + else + blockdef = air_def; + data.blocks[rx][ry][rz] = blockdef; + } + } + } + return data; +} diff --git a/src/mapgen.hpp b/src/mapgen.hpp new file mode 100644 index 0000000..8c44d63 --- /dev/null +++ b/src/mapgen.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "chunk.hpp" +#include "gl.hpp" + +namespace dragonblocks +{ + class BlockDef; + + class Mapgen + { + public: + float grass_layer_middle = 0, grass_layer_range = 32; + BlockDef *air_def, *stone_def, *dirt_def, *grass_def; + + Chunk::Data generate(const glm::ivec3 &) const; + }; +}; diff --git a/src/mesh.cpp b/src/mesh.cpp new file mode 100644 index 0000000..cb01438 --- /dev/null +++ b/src/mesh.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include "FrustumCull.h" +#include "mesh.hpp" +#include "scene.hpp" +#include "shader_program.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +bool Mesh::IAnimation::expired(double dtime) +{ + if (expires) { + time_left -= dtime; + if (time_left < 0) { + if (on_finish) { + (*on_finish)(extra_data); + } + return true; + } + } + return false; +} + +vec3 Mesh::IAnimation::getPos(vec3 p) +{ + return p; +} + +vec3 Mesh::IAnimation::getSize(vec3 s) +{ + return s; +} + +vec3 Mesh::IAnimation::getRotationAxis(vec3 r) +{ + return r; +} + +float Mesh::IAnimation::getRotationAngle(float r) +{ + return r; +} + +Mesh::IAnimation::IAnimation(double t, void (*o)(void *), void *e) : time_left(t), on_finish(o), extra_data(e) +{ + expires = true; +} + +void Mesh::render(double dtime, Frustum *frustum, mat4 projection_matrix, mat4 view_matrix, vec3 sky) +{ + rendering = true; + + if (do_delete) { + delete this; + return; + } else if (prepare_death) { + do_delete = true; + } + + if (! configured) { + configure(); + } + + shader_program->use(); CHECKERR + + mat4 model_matrix = identity(); + + vec3 n_pos = pos, n_size = size, n_rotation_axis = rotation_axis; + float n_rotation_angle = rotation_angle; + + if (animation) { + if (animation->expired(dtime)) { + delete animation; + animation = nullptr; + } else { + n_pos = animation->getPos(n_pos); + n_size = animation->getSize(n_size); + n_rotation_axis = animation->getRotationAxis(n_rotation_axis); + n_rotation_angle = animation->getRotationAngle(n_rotation_angle); + } + } + + model_matrix = translate(model_matrix, n_pos); + model_matrix = rotate(model_matrix, n_rotation_angle, n_rotation_axis); + model_matrix = scale(model_matrix, n_size); + + if (! visible || ! frustum->IsBoxVisible(model_matrix * vec4(minp - vec3(1.0), 1.0), model_matrix * vec4(maxp + vec3(1.0), 1.0))) + return; + + shader_program->set("model", model_matrix); CHECKERR + shader_program->set("view", view_matrix); CHECKERR + shader_program->set("projection", projection_matrix); CHECKERR + shader_program->set("sky", sky); CHECKERR + + glBindVertexArray(VAO); CHECKERR + for (int i = 0; i < textures.size(); i++) { + textures[i].bind(); CHECKERR + glDrawArrays(GL_TRIANGLES, i * vertices_per_texture, vertices_per_texture); CHECKERR + } + glBindVertexArray(0); CHECKERR + glBindTexture(GL_TEXTURE_2D, 0); CHECKERR + + rendering = false; +} + +bool Mesh::isRendering() +{ + return rendering; +} + +void Mesh::die() +{ + prepare_death = true; +} + +Mesh::Mesh(Scene *s, ShaderProgram *sh, const GLfloat *v, GLsizei vs): pos(0), size(1), rotation_axis(0, 1, 0), scene(s), shader_program(sh), vertices_size(vs * sizeof(GLfloat)) +{ + if (! v || ! vs) + throw runtime_error("Invalid Mesh configuration"); + vertices = malloc(vertices_size); + memcpy(vertices, v, vertices_size); + scene->add(this); +} + +Mesh::~Mesh() +{ + scene->remove(this); + if (VAO) { + glDeleteVertexArrays(1, &VAO); CHECKERR + } + if (VBO) { + glDeleteBuffers(1, &VAO); CHECKERR + } + if (animation) { + delete animation; + } +} + +void Mesh::configure() +{ + 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; + configured = true; +} diff --git a/src/mesh.hpp b/src/mesh.hpp new file mode 100644 index 0000000..14e64d0 --- /dev/null +++ b/src/mesh.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include +#include "gl.hpp" +#include "texture.hpp" + +class Frustum; + +namespace dragonblocks +{ + class Scene; + class ShaderProgram; + + class Mesh + { + public: + class IAnimation + { + public: + bool expired(double); + virtual glm::vec3 getPos(glm::vec3); + virtual glm::vec3 getSize(glm::vec3); + virtual glm::vec3 getRotationAxis(glm::vec3); + virtual float getRotationAngle(float); + + protected: + bool expires = false; + double time_left; + void (*on_finish)(void *); + void *extra_data; + + IAnimation() = default; + IAnimation(double, void (*)(void *), void *); + }; + + int vertices_per_texture; + glm::vec3 pos, size, rotation_axis; + glm::vec3 minp, maxp; + float rotation_angle = 0; + std::vector textures; + IAnimation *animation = nullptr; + bool visible = true; + + void render(double dtime, Frustum *, glm::mat4, glm::mat4, glm::vec3); + bool isRendering(); + void die(); + + Mesh(Scene *, ShaderProgram *, const GLfloat *, GLsizei); + + private: + GLuint VAO = 0, VBO = 0; + Scene *scene; + ShaderProgram *shader_program; + GLvoid *vertices = NULL; + GLsizeiptr vertices_size; + bool configured = false; + bool rendering = false; + bool prepare_death = false; + bool do_delete = false; + + void configure(); + + ~Mesh(); + }; +} diff --git a/src/render_engine.cpp b/src/render_engine.cpp new file mode 100644 index 0000000..eeebd0c --- /dev/null +++ b/src/render_engine.cpp @@ -0,0 +1,71 @@ +#include +#include +#include "FrustumCull.h" +#include "camera.hpp" +#include "input_handler.hpp" +#include "render_engine.hpp" +#include "scene.hpp" +#include "shader_program.hpp" +#include "window.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +void RenderEngine::render(double dtime) +{ + glClearColor(sky.r, sky.g, sky.b, 1.0); CHECKERR + + /* + glEnable(GL_CULL_FACE); CHECKERR + glCullFace(GL_BACK); CHECKERR + glFrontFace(GL_CW); CHECKERR + */ + + glEnable(GL_DEPTH_TEST); CHECKERR + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); CHECKERR + + + dvec2 window_size = window->getSize(); + mat4 projection_matrix = perspective(radians(fov), window_size.x / window_size.y, 0.01, render_distance); + + mat4 view_matrix = camera->getViewMatrix(); + + Frustum frustum(projection_matrix * view_matrix); + + scene->render(dtime, &frustum, projection_matrix, view_matrix, sky); + + window->swapBuffers(); CHECKERR + glfwPollEvents(); CHECKERR +} + +bool RenderEngine::running() +{ + return ! window->shouldClose(); +} + +RenderEngine::RenderEngine() +{ + if (! glfwInit()) { + throw runtime_error("Failed to initialize GLFW"); + } + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + window = Window::create(this); + camera = new Camera; + scene = new Scene; + + GLenum glew_init_err = glewInit(); + if (glew_init_err != GLEW_OK) { + throw runtime_error("Failed to initialize GLEW"); + } +} + +RenderEngine::~RenderEngine() +{ + delete window; + delete camera; + delete scene; +} diff --git a/src/render_engine.hpp b/src/render_engine.hpp new file mode 100644 index 0000000..8181f22 --- /dev/null +++ b/src/render_engine.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "gl.hpp" + +namespace dragonblocks +{ + class Camera; + class InputHandler; + class Scene; + class Window; + + class RenderEngine + { + public: + Camera *camera; + Scene *scene; + Window *window; + double render_distance = 16; + double fov = 45; + glm::vec3 sky; + + void render(double); + bool running(); + + RenderEngine(); + ~RenderEngine(); + }; +} diff --git a/src/scene.cpp b/src/scene.cpp new file mode 100644 index 0000000..1152d9e --- /dev/null +++ b/src/scene.cpp @@ -0,0 +1,35 @@ +#include "mesh.hpp" +#include "scene.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +void Scene::add(Mesh *m) +{ + meshes.insert(m); +} + +void Scene::remove(Mesh *m) +{ + meshes.erase(m); +} + +void Scene::render(double dtime, Frustum *frustum, mat4 projection_matrix, mat4 view_matrix, vec3 sky) +{ + auto renderlist = meshes; + for (auto it = renderlist.begin(); it != renderlist.end(); it++) { + Mesh *mesh = *it; + mesh->render(dtime, frustum, projection_matrix, view_matrix, sky); + } +} + +void Scene::clear() +{ + meshes.clear(); +} + +Scene::~Scene() +{ + clear(); +} diff --git a/src/scene.hpp b/src/scene.hpp new file mode 100644 index 0000000..86e0a4f --- /dev/null +++ b/src/scene.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "gl.hpp" + +class Frustum; + +namespace dragonblocks +{ + class Mesh; + class ShaderProgram; + + class Scene { + public: + void add(Mesh *); + void remove(Mesh *); + void render(double, Frustum *, glm::mat4, glm::mat4, glm::vec3); + void clear(); + void run(); + + ~Scene(); + + private: + std::set meshes; + }; +} diff --git a/src/shader_program.cpp b/src/shader_program.cpp new file mode 100644 index 0000000..812a1ed --- /dev/null +++ b/src/shader_program.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include "shader_program.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +map ShaderProgram::shadertypes = { + {"vertex", GL_VERTEX_SHADER}, + {"fragment", GL_FRAGMENT_SHADER}, +}; + +ShaderProgram::ShaderProgram(const string &global_path) +{ + int success; + char buffer[1024] = {}; + vector shaders; + + id = glCreateProgram(); + + for (auto it = ShaderProgram::shadertypes.begin(); it != ShaderProgram::shadertypes.end(); it++) { + const char *c_code; + GLuint shader; + string path, code; + ifstream file; + stringstream stream; + + path = global_path + "/" + it->first + ".glsl"; + file.exceptions(ifstream::failbit | ifstream::badbit); + file.open(path); + stream << file.rdbuf(); + code = stream.str(); + c_code = code.c_str(); + + shader = glCreateShader(it->second); + shaders.push_back(shader); + glShaderSource(shader, 1, &c_code, NULL); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (! success) { + glGetShaderInfoLog(shader, 1024, NULL, buffer); + throw runtime_error("Failed to compile " + it->first + " shader: " + buffer); + } + glAttachShader(id, shader); + } + + glLinkProgram(id); + glGetProgramiv(id, GL_LINK_STATUS, &success); + if (! success) { + glGetProgramInfoLog(id, 1024, NULL, buffer); + throw runtime_error(string("Failed to link shader program: ") + buffer); + } + + for (auto it = shaders.begin(); it != shaders.end(); it++) { + glDeleteShader(*it); + } +} + +void ShaderProgram::use() const +{ + glUseProgram(id); +} + +void ShaderProgram::set(const string &name, bool value) +{ + use(); + glUniform1i(glGetUniformLocation(id, name.c_str()), (int) value); +} + +void ShaderProgram::set(const string &name, int value) +{ + use(); + glUniform1i(glGetUniformLocation(id, name.c_str()), value); +} + +void ShaderProgram::set(const string &name, float value) +{ + use(); + glUniform1f(glGetUniformLocation(id, name.c_str()), value); +} + +void ShaderProgram::set(const string &name, mat4 value) +{ + use(); + glUniformMatrix4fv(glGetUniformLocation(id, name.c_str()), 1, GL_FALSE, value_ptr(value)); +} + +void ShaderProgram::set(const string &name, vec3 value) +{ + use(); + glUniform3f(glGetUniformLocation(id, name.c_str()), value.x, value.y, value.z); +} + +ShaderProgram::~ShaderProgram() +{ + glDeleteProgram(id); +} diff --git a/src/shader_program.hpp b/src/shader_program.hpp new file mode 100644 index 0000000..0496c19 --- /dev/null +++ b/src/shader_program.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include "gl.hpp" + +namespace dragonblocks +{ + class ShaderProgram + { + public: + static std::map shadertypes; + + void use() const; + void set(const std::string &, bool); + void set(const std::string &, int); + void set(const std::string &, float); + void set(const std::string &, glm::mat4); + void set(const std::string &, glm::vec3); + + ShaderProgram(const std::string &); + ~ShaderProgram(); + + private: + GLuint id; + }; +} diff --git a/src/texture.cpp b/src/texture.cpp new file mode 100644 index 0000000..a595411 --- /dev/null +++ b/src/texture.cpp @@ -0,0 +1,51 @@ +#include +#include +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#include "texture.hpp" + +using namespace std; +using namespace dragonblocks; + +bool Texture::mipmap; +bool Texture::bilinear_filter; +GLenum Texture::min_filter, Texture::mag_filter; + +void Texture::initArgs() +{ + min_filter = mag_filter = bilinear_filter ? GL_LINEAR : GL_NEAREST; + if (mipmap) { + if (min_filter == GL_NEAREST) { + min_filter = GL_NEAREST_MIPMAP_NEAREST; + } else { + min_filter = GL_LINEAR_MIPMAP_NEAREST; + } + } + stbi_set_flip_vertically_on_load(true); +} + +void Texture::bind() const +{ + glBindTexture(GL_TEXTURE_2D, id); CHECKERR +} + +void Texture::load(const string &path) +{ + int width, height, nrChannels; + 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); CHECKERR + bind(); + 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); CHECKERR + stbi_image_free(data); + glBindTexture(GL_TEXTURE_2D, 0); CHECKERR + cout << "Loaded texture " << path << endl; +} + diff --git a/src/texture.hpp b/src/texture.hpp new file mode 100644 index 0000000..eb9e0c2 --- /dev/null +++ b/src/texture.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "gl.hpp" + +namespace dragonblocks +{ + class Texture + { + public: + static bool mipmap; + static bool bilinear_filter; + + static void initArgs(); + + void bind() const; + void load(const std::string &); + Texture() = default; + Texture(const Texture &) = default; + + private: + static GLenum min_filter, mag_filter; + + GLuint id; + }; +} diff --git a/src/tile_def.cpp b/src/tile_def.cpp new file mode 100644 index 0000000..a4c77d7 --- /dev/null +++ b/src/tile_def.cpp @@ -0,0 +1,30 @@ +#include "tile_def.hpp" + +using namespace std; +using namespace dragonblocks; + +Texture TileDef::get(int i) const +{ + return tiles[i]; +} + +int TileDef::size() const +{ + return tiles.size(); +} + +TileDef::TileDef(const vector &t) : tiles(t) +{ + int s = size(); + for (int i = 0; s < 6; i += s) { + for (int j = 0; j < i && j + i < 6; j++) { + tiles[i + j] = tiles[j]; + } + } +} + +TileDef::TileDef(const Texture &t) : TileDef({t, t, t, t, t, t}) +{ +} + + diff --git a/src/tile_def.hpp b/src/tile_def.hpp new file mode 100644 index 0000000..dd5c7e0 --- /dev/null +++ b/src/tile_def.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include "texture.hpp" + +namespace dragonblocks +{ + class TileDef + { + public: + std::vector tiles; + + Texture get(int) const; + int size() const; + + TileDef() = default; + TileDef(const Texture &); + TileDef(const std::vector &); + }; +} diff --git a/src/window.cpp b/src/window.cpp new file mode 100644 index 0000000..7729453 --- /dev/null +++ b/src/window.cpp @@ -0,0 +1,156 @@ +#include +#include "render_engine.hpp" +#include "window.hpp" + +using namespace std; +using namespace glm; +using namespace dragonblocks; + +Window *Window::singleton = nullptr; + +Window *Window::create(RenderEngine *r) +{ + if (singleton) { + throw runtime_error("Window already exists"); + } + return singleton = new Window(r); +} + +void Window::windowPosCallback(GLFWwindow *id, int x, int y) +{ + singleton->posInput(x, y); +} + +void Window::framebufferSizeCallback(GLFWwindow *id, int width, int height) +{ + glViewport(0, 0, width, height); + singleton->sizeInput(width, height); +} + +void Window::cursorPosCallback(GLFWwindow *id, double x, double y) +{ + singleton->cursorInput(x, y); +} + +void Window::setTitle(const string &title) +{ + glfwSetWindowTitle(id, title.c_str()); +} + +void Window::setSize(int width, int height) +{ + glfwSetWindowSize(id, width, height); +} + +void Window::setPos(int x, int y) +{ + glfwSetWindowPos(id, x, y); +} + +void Window::toggleFullscreen() +{ + fullscreen = ! fullscreen; + + if (fullscreen) { + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode *vidmode = glfwGetVideoMode(monitor); + glfwSetWindowMonitor(id, monitor, 0, 0, vidmode->width, vidmode->height, 0); + } + else + glfwSetWindowMonitor(id, nullptr, nfs_x, nfs_y, nfs_width, nfs_height, 0); +} + +void Window::close() +{ + glfwDestroyWindow(id); +} + +void Window::swapBuffers() +{ + glfwSwapBuffers(id); +} + +bool Window::shouldClose() const +{ + return glfwWindowShouldClose(id); +} + +bool Window::isKeyDown(int key) const +{ + return glfwGetKey(id, key) == GLFW_PRESS; +} + +void Window::makeContextCurrent() const +{ + glfwMakeContextCurrent(id); +} + +ivec2 Window::getSize() const +{ + return ivec2(width, height); +} + +ivec2 Window::getCursorPos() const +{ + return ivec2(cursor_x, cursor_y); +} + +ivec2 Window::getCursorDelta() +{ + ivec2 delta(cursor_delta_x, cursor_delta_y); + cursor_delta_x = cursor_delta_y = 0; + return delta; +} + +void Window::posInput(int x, int y) +{ + if (! fullscreen) { + nfs_x = x; + nfs_y = y; + } +} + +void Window::sizeInput(int w, int h) +{ + width = w; + height = h; + if (! fullscreen) { + nfs_width = width; + nfs_height = height; + } +} + +void Window::cursorInput(int x, int y) +{ + int lx = cursor_x; + int ly = cursor_y; + cursor_delta_x = x - lx; + cursor_delta_y = y - ly; + cursor_x = x; + cursor_y = y; +} + +Window::~Window() +{ + close(); +} + +Window::Window(RenderEngine *r) : render_engine(r) +{ + fullscreen = false; + width = nfs_width = 100; + height = nfs_height = 100; + cursor_x = cursor_y = cursor_delta_x = cursor_delta_y = 0; + id = glfwCreateWindow(width, height, "libdragonblocks.so", NULL, NULL); + if (! id) { + glfwTerminate(); + throw runtime_error("Failed to create GLFW window"); + } + makeContextCurrent(); + glfwSetInputMode(id, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + glfwSetWindowPosCallback(id, Window::windowPosCallback); + glfwSetFramebufferSizeCallback(id, Window::framebufferSizeCallback); + glfwSetCursorPosCallback(id, Window::cursorPosCallback); +} + + diff --git a/src/window.hpp b/src/window.hpp new file mode 100644 index 0000000..e3b0f36 --- /dev/null +++ b/src/window.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include +#include "gl.hpp" + +namespace dragonblocks +{ + class RenderEngine; + + class Window + { + public: + static Window *create(RenderEngine *); + static void windowPosCallback(GLFWwindow *, int, int); + static void framebufferSizeCallback(GLFWwindow *, int, int); + static void cursorPosCallback(GLFWwindow *, double, double); + + void setTitle(const std::string &); + void setPos(int, int); + void setSize(int, int); + void toggleFullscreen(); + void close(); + void swapBuffers(); + bool shouldClose() const; + bool isKeyDown(int) const; + void makeContextCurrent() const; + glm::ivec2 getSize() const; + glm::ivec2 getCursorPos() const; + glm::ivec2 getCursorDelta(); + + ~Window(); + + private: + static Window *singleton; + + RenderEngine *render_engine; + GLFWwindow *id; + bool fullscreen; + int width, height; + int nfs_width, nfs_height, nfs_x, nfs_y; + int cursor_x, cursor_y, cursor_delta_x, cursor_delta_y; + + void posInput(int, int); + void sizeInput(int, int); + void cursorInput(int, int); + + Window(RenderEngine *); + }; +} + diff --git a/textures/leaves.png b/textures/leaves.png deleted file mode 100644 index 02b6cf0..0000000 Binary files a/textures/leaves.png and /dev/null differ