diff --git a/src/content/Content.cpp b/src/content/Content.cpp index c74395a3..7021d5f8 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -1,9 +1,11 @@ #include "Content.h" #include +#include #include "../voxels/Block.h" +using glm::vec3; using std::vector; using std::string; using std::unordered_map; @@ -22,6 +24,24 @@ Content* ContentBuilder::build() { for (const string& name : blockIds) { Block* def = blockDefs[name]; def->id = blockDefsIndices.size(); + def->rt.emissive = *((uint32_t*)def->emission); + + // build hitbox grid 3d for raycasts + const AABB& hitbox = def->hitbox; + for (uint gy = 0; gy < BLOCK_AABB_GRID; gy++) { + for (uint gz = 0; gz < BLOCK_AABB_GRID; gz++) { + for (uint gx = 0; gx < BLOCK_AABB_GRID; gx++) { + float x = gx / float(BLOCK_AABB_GRID); + float y = gy / float(BLOCK_AABB_GRID); + float z = gz / float(BLOCK_AABB_GRID); + bool flag = hitbox.inside({x, y, z}); + if (!flag) + def->rt.solid = false; + def->rt.hitboxGrid[gy][gz][gx] = flag; + } + } + } + blockDefsIndices.push_back(def); if (groups->find(def->drawGroup) == groups->end()) { groups->insert(def->drawGroup); diff --git a/src/definitions.cpp b/src/definitions.cpp index 1484b3e6..17576baf 100644 --- a/src/definitions.cpp +++ b/src/definitions.cpp @@ -1,11 +1,15 @@ #include "definitions.h" +#include + #include "content/Content.h" #include "window/Window.h" #include "window/Events.h" #include "window/input.h" #include "voxels/Block.h" +using glm::vec3; + // All in-game definitions (blocks, items, etc..) void setup_definitions(ContentBuilder* builder) { Block* block = new Block("core:air", "air"); @@ -70,7 +74,7 @@ void setup_definitions(ContentBuilder* builder) { block->lightPassing = true; block->obstacle = false; block->model = BlockModel::xsprite; - block->hitboxScale = 0.5f; + block->hitbox.scale(vec3(0.7f), vec3(0.5f, 0.0f, 0.5f)); builder->add(block); block = new Block("base:flower", "flower"); @@ -78,6 +82,7 @@ void setup_definitions(ContentBuilder* builder) { block->lightPassing = true; block->obstacle = false; block->model = BlockModel::xsprite; + block->hitbox.scale(vec3(0.7f)); builder->add(block); block = new Block("base:brick", "brick"); diff --git a/src/engine.cpp b/src/engine.cpp index db46ccd5..844a0ba5 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -36,7 +36,9 @@ using gui::GUI; Engine::Engine(EngineSettings& settings, EnginePaths* paths, Content* content) : settings(settings), content(content), paths(paths) { - Window::initialize(settings.display); + if (Window::initialize(settings.display)){ + throw initialize_error("could not initialize window"); + } Shader::preprocessor->setLibFolder(paths->getResources()/path("shaders/lib")); assets = new Assets(); diff --git a/src/frontend/world_render.cpp b/src/frontend/world_render.cpp index 42c4a804..7a802677 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/world_render.cpp @@ -31,6 +31,7 @@ #include "graphics/Skybox.h" using glm::vec3; +using glm::vec4; using std::string; using std::shared_ptr; @@ -168,13 +169,11 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) linesShader->use(); linesShader->uniformMatrix("u_projview", camera->getProjView()); lineBatch->lineWidth(2.0f); - if (block->model == BlockModel::block){ - lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, - 1.008f,1.008f,1.008f, 0,0,0,0.5f); - } else if (block->model == BlockModel::xsprite){ - lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f, - 0.805f,0.705f,0.805f, 0,0,0,0.5f); - } + + const AABB& hitbox = block->hitbox; + const vec3 center = pos + hitbox.center(); + const vec3 size = hitbox.size(); + lineBatch->box(center, size, vec4(0.0f, 0.0f, 0.0f, 0.5f)); lineBatch->render(); } skybox->unbind(); diff --git a/src/graphics/LineBatch.h b/src/graphics/LineBatch.h index 58d7de3a..8e37cf61 100644 --- a/src/graphics/LineBatch.h +++ b/src/graphics/LineBatch.h @@ -2,6 +2,7 @@ #define GRAPHICS_LINEBATCH_H_ #include +#include class Mesh; @@ -19,6 +20,11 @@ public: void box(float x, float y, float z, float w, float h, float d, float r, float g, float b, float a); + inline void box(glm::vec3 xyz, glm::vec3 whd, glm::vec4 rgba) { + return box(xyz.x, xyz.y, xyz.z, whd.x, whd.y, whd.z, + rgba.r, rgba.g, rgba.b, rgba.a); + } + void render(); void lineWidth(float width); }; diff --git a/src/maths/aabb.h b/src/maths/aabb.h new file mode 100644 index 00000000..7f790b59 --- /dev/null +++ b/src/maths/aabb.h @@ -0,0 +1,59 @@ +#ifndef MATHS_AABB_H_ +#define MATHS_AABB_H_ + +#include + +// Axis Aligned Bounding Box +struct AABB { + glm::vec3 a {0.0f}; + glm::vec3 b {1.0f}; + + /* Get AABB point with minimal x,y,z */ + inline glm::vec3 min() const { + return glm::min(a, b); + } + + /* Get AABB point with minimal x,y,z */ + inline glm::vec3 max() const { + return glm::max(a, b); + } + + /* Get AABB dimensions: width, height, depth */ + inline glm::vec3 size() const { + return glm::vec3( + fabs(b.x - a.x), + fabs(b.y - a.y), + fabs(b.z - a.z) + ); + } + + inline glm::vec3 center() const { + return (a + b) * 0.5f; + } + + /* Multiply AABB size from center */ + inline void scale(const glm::vec3 mul) { + glm::vec3 center = (a + b) * 0.5f; + a = (a - center) * mul + center; + b = (b - center) * mul + center; + } + + /* Multiply AABB size from given origin */ + inline void scale(const glm::vec3 mul, const glm::vec3 orig) { + glm::vec3 beg = min(); + glm::vec3 end = max(); + glm::vec3 center = glm::mix(beg, end, orig); + a = (a - center) * mul + center; + b = (b - center) * mul + center; + } + + /* Check if given point is inside */ + inline bool inside(const glm::vec3 pos) const { + const glm::vec3 p = min(); + const glm::vec3 s = size(); + return !(pos.x < p.x || pos.y < p.y || pos.z < p.z || + pos.x >= p.x+s.x || pos.y >= p.y+s.y || pos.z >= p.z+s.z); + } +}; + +#endif // MATHS_AABB_H_ \ No newline at end of file diff --git a/src/voxels/Block.h b/src/voxels/Block.h index 42505f8c..1b1b1e39 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -3,6 +3,8 @@ #include +#include "../maths/aabb.h" + #define FACE_MX 0 #define FACE_PX 1 #define FACE_MY 2 @@ -10,6 +12,8 @@ #define FACE_MZ 4 #define FACE_PZ 5 +#define BLOCK_AABB_GRID 16 + enum class BlockModel { none, block, xsprite }; @@ -29,7 +33,13 @@ public: bool selectable = true; bool breakable = true; bool rotatable = false; - float hitboxScale = 1; + AABB hitbox; + + struct { + bool solid = true; + bool emissive = false; + bool hitboxGrid[BLOCK_AABB_GRID][BLOCK_AABB_GRID][BLOCK_AABB_GRID]; + } rt; Block(std::string name, std::string texture); }; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index c8a7d6d0..c53bbb49 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -200,20 +200,41 @@ voxel* Chunks::rayCast(vec3 start, while (t <= maxDist){ voxel* voxel = get(ix, iy, iz); - if (voxel == nullptr || contentIds->getBlockDef(voxel->id)->selectable){ + const Block* def = nullptr; + if (voxel == nullptr || (def = contentIds->getBlockDef(voxel->id))->selectable){ end.x = px + t * dx; end.y = py + t * dy; end.z = pz + t * dz; + + // TODO: replace this dumb solution with something better + if (def && !def->rt.solid) { + const AABB& box = def->hitbox; + const int subs = BLOCK_AABB_GRID; + iend = vec3(ix, iy, iz); + end -= iend; + for (int i = 0; i < subs; i++) { + end.x += dx / float(subs); + end.y += dy / float(subs); + end.z += dz / float(subs); + if (box.inside(end)) { + norm.x = norm.y = norm.z = 0.0f; + if (steppedIndex == 0) norm.x = -stepx; + if (steppedIndex == 1) norm.y = -stepy; + if (steppedIndex == 2) norm.z = -stepz; + return voxel; + } + } + } else { + iend.x = ix; + iend.y = iy; + iend.z = iz; - iend.x = ix; - iend.y = iy; - iend.z = iz; - - norm.x = norm.y = norm.z = 0.0f; - if (steppedIndex == 0) norm.x = -stepx; - if (steppedIndex == 1) norm.y = -stepy; - if (steppedIndex == 2) norm.z = -stepz; - return voxel; + norm.x = norm.y = norm.z = 0.0f; + if (steppedIndex == 0) norm.x = -stepx; + if (steppedIndex == 1) norm.y = -stepy; + if (steppedIndex == 2) norm.z = -stepz; + return voxel; + } } if (txMax < tyMax) { if (txMax < tzMax) { diff --git a/src/window/Window.cpp b/src/window/Window.cpp index ad221942..2a68d5a9 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -87,7 +87,8 @@ int Window::initialize(DisplaySettings& settings){ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); + glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); glfwWindowHint(GLFW_SAMPLES, settings.samples);