AABB block hitboxes

This commit is contained in:
MihailRis 2023-11-29 16:36:00 +03:00
parent cad1f6a669
commit 91a6426efe
7 changed files with 86 additions and 17 deletions

View File

@ -1,9 +1,11 @@
#include "Content.h"
#include <stdexcept>
#include <glm/glm.hpp>
#include "../voxels/Block.h"
using glm::vec3;
using std::vector;
using std::string;
using std::unordered_map;
@ -21,6 +23,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);
}
ContentIndices* indices = new ContentIndices(blockDefsIndices);

View File

@ -1,11 +1,15 @@
#include "definitions.h"
#include <glm/glm.hpp>
#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");
@ -71,7 +75,7 @@ void setup_definitions(ContentBuilder* builder) {
block->lightPassing = true;
block->obstacle = false;
block->model = BlockModel::xsprite;
block->hitboxScale = 0.7f;
block->hitbox.scale(vec3(0.7f), vec3(0.5f, 0.0f, 0.5f));
builder->add(block);
block = new Block("base:flower", "flower");
@ -79,6 +83,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");

View File

@ -31,6 +31,7 @@
#include "graphics/Skybox.h"
using glm::vec3;
using glm::vec4;
using std::string;
using std::shared_ptr;
@ -168,9 +169,11 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
linesShader->use();
linesShader->uniformMatrix("u_projview", camera->getProjView());
lineBatch->lineWidth(2.0f);
float size = block->hitboxScale;
lineBatch->box(pos.x+0.5f, pos.y+size*0.5f, pos.z+0.5f,
size, size, size, 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();

View File

@ -2,6 +2,7 @@
#define GRAPHICS_LINEBATCH_H_
#include <stdlib.h>
#include <glm/glm.hpp>
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);
};

View File

@ -5,13 +5,20 @@
// Axis Aligned Bounding Box
struct AABB {
glm::vec3 a;
glm::vec3 b;
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),
@ -20,6 +27,27 @@ struct AABB {
);
}
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();

View File

@ -3,6 +3,8 @@
#include <string>
#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);
};

View File

@ -159,6 +159,7 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){
chunk->setModified(true);
}
#include <iostream>
voxel* Chunks::rayCast(vec3 start,
vec3 dir,
float maxDist,
@ -207,20 +208,16 @@ voxel* Chunks::rayCast(vec3 start,
end.z = pz + t * dz;
// TODO: replace this dumb solution with something better
if (def && def->hitboxScale < 1.0f) {
const float sz = def->hitboxScale;
const int subs = 16;
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 (end.x - ix >= 0.5f - sz * 0.5f && end.x - ix <= 0.5f + sz * 0.5f &&
end.y - iy >= 0.0f && end.y - iy <= sz &&
end.z - iz >= 0.5f - sz * 0.5f && end.z - iz <= 0.5f + sz * 0.5f) {
iend.x = ix;
iend.y = iy;
iend.z = iz;
if (box.inside(end)) {
norm.x = norm.y = norm.z = 0.0f;
if (steppedIndex == 0) norm.x = -stepx;
if (steppedIndex == 1) norm.y = -stepy;