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 "Content.h"
#include <stdexcept> #include <stdexcept>
#include <glm/glm.hpp>
#include "../voxels/Block.h" #include "../voxels/Block.h"
using glm::vec3;
using std::vector; using std::vector;
using std::string; using std::string;
using std::unordered_map; using std::unordered_map;
@ -21,6 +23,24 @@ Content* ContentBuilder::build() {
for (const string& name : blockIds) { for (const string& name : blockIds) {
Block* def = blockDefs[name]; Block* def = blockDefs[name];
def->id = blockDefsIndices.size(); 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); blockDefsIndices.push_back(def);
} }
ContentIndices* indices = new ContentIndices(blockDefsIndices); ContentIndices* indices = new ContentIndices(blockDefsIndices);

View File

@ -1,11 +1,15 @@
#include "definitions.h" #include "definitions.h"
#include <glm/glm.hpp>
#include "content/Content.h" #include "content/Content.h"
#include "window/Window.h" #include "window/Window.h"
#include "window/Events.h" #include "window/Events.h"
#include "window/input.h" #include "window/input.h"
#include "voxels/Block.h" #include "voxels/Block.h"
using glm::vec3;
// All in-game definitions (blocks, items, etc..) // All in-game definitions (blocks, items, etc..)
void setup_definitions(ContentBuilder* builder) { void setup_definitions(ContentBuilder* builder) {
Block* block = new Block("core:air", "air"); Block* block = new Block("core:air", "air");
@ -71,7 +75,7 @@ void setup_definitions(ContentBuilder* builder) {
block->lightPassing = true; block->lightPassing = true;
block->obstacle = false; block->obstacle = false;
block->model = BlockModel::xsprite; block->model = BlockModel::xsprite;
block->hitboxScale = 0.7f; block->hitbox.scale(vec3(0.7f), vec3(0.5f, 0.0f, 0.5f));
builder->add(block); builder->add(block);
block = new Block("base:flower", "flower"); block = new Block("base:flower", "flower");
@ -79,6 +83,7 @@ void setup_definitions(ContentBuilder* builder) {
block->lightPassing = true; block->lightPassing = true;
block->obstacle = false; block->obstacle = false;
block->model = BlockModel::xsprite; block->model = BlockModel::xsprite;
block->hitbox.scale(vec3(0.7f));
builder->add(block); builder->add(block);
block = new Block("base:brick", "brick"); block = new Block("base:brick", "brick");

View File

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

View File

@ -2,6 +2,7 @@
#define GRAPHICS_LINEBATCH_H_ #define GRAPHICS_LINEBATCH_H_
#include <stdlib.h> #include <stdlib.h>
#include <glm/glm.hpp>
class Mesh; class Mesh;
@ -19,6 +20,11 @@ public:
void box(float x, float y, float z, float w, float h, float d, void box(float x, float y, float z, float w, float h, float d,
float r, float g, float b, float a); 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 render();
void lineWidth(float width); void lineWidth(float width);
}; };

View File

@ -5,13 +5,20 @@
// Axis Aligned Bounding Box // Axis Aligned Bounding Box
struct AABB { struct AABB {
glm::vec3 a; glm::vec3 a {0.0f};
glm::vec3 b; glm::vec3 b {1.0f};
/* Get AABB point with minimal x,y,z */
inline glm::vec3 min() const { inline glm::vec3 min() const {
return glm::min(a, b); 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 { inline glm::vec3 size() const {
return glm::vec3( return glm::vec3(
fabs(b.x - a.x), 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 { inline bool inside(const glm::vec3 pos) const {
const glm::vec3 p = min(); const glm::vec3 p = min();
const glm::vec3 s = size(); const glm::vec3 s = size();

View File

@ -3,6 +3,8 @@
#include <string> #include <string>
#include "../maths/aabb.h"
#define FACE_MX 0 #define FACE_MX 0
#define FACE_PX 1 #define FACE_PX 1
#define FACE_MY 2 #define FACE_MY 2
@ -10,6 +12,8 @@
#define FACE_MZ 4 #define FACE_MZ 4
#define FACE_PZ 5 #define FACE_PZ 5
#define BLOCK_AABB_GRID 16
enum class BlockModel { enum class BlockModel {
none, block, xsprite none, block, xsprite
}; };
@ -29,7 +33,13 @@ public:
bool selectable = true; bool selectable = true;
bool breakable = true; bool breakable = true;
bool rotatable = false; 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); 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); chunk->setModified(true);
} }
#include <iostream>
voxel* Chunks::rayCast(vec3 start, voxel* Chunks::rayCast(vec3 start,
vec3 dir, vec3 dir,
float maxDist, float maxDist,
@ -207,20 +208,16 @@ voxel* Chunks::rayCast(vec3 start,
end.z = pz + t * dz; end.z = pz + t * dz;
// TODO: replace this dumb solution with something better // TODO: replace this dumb solution with something better
if (def && def->hitboxScale < 1.0f) { if (def && !def->rt.solid) {
const float sz = def->hitboxScale; const AABB& box = def->hitbox;
const int subs = 16; const int subs = BLOCK_AABB_GRID;
iend = vec3(ix, iy, iz);
end -= iend;
for (int i = 0; i < subs; i++) { for (int i = 0; i < subs; i++) {
end.x += dx / float(subs); end.x += dx / float(subs);
end.y += dy / float(subs); end.y += dy / float(subs);
end.z += dz / float(subs); end.z += dz / float(subs);
if (end.x - ix >= 0.5f - sz * 0.5f && end.x - ix <= 0.5f + sz * 0.5f && if (box.inside(end)) {
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;
norm.x = norm.y = norm.z = 0.0f; norm.x = norm.y = norm.z = 0.0f;
if (steppedIndex == 0) norm.x = -stepx; if (steppedIndex == 0) norm.x = -stepx;
if (steppedIndex == 1) norm.y = -stepy; if (steppedIndex == 1) norm.y = -stepy;