Merge pull request #160 from InfiniteCoder01/MultipleHitboxes
Multiple Hitboxes
This commit is contained in:
commit
38e05f3514
@ -87,6 +87,12 @@ Content* ContentBuilder::build() {
|
|||||||
AABB aabb = hitbox;
|
AABB aabb = hitbox;
|
||||||
def->rotations.variants[i].transform(aabb);
|
def->rotations.variants[i].transform(aabb);
|
||||||
def->rt.hitboxes[i] = aabb;
|
def->rt.hitboxes[i] = aabb;
|
||||||
|
|
||||||
|
def->rt.modelBoxes[i].reserve(def->modelBoxes.size());
|
||||||
|
for (AABB aabb : def->modelBoxes) {
|
||||||
|
def->rotations.variants[i].transform(aabb);
|
||||||
|
def->rt.modelBoxes[i].push_back(aabb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -151,6 +151,15 @@ void ContentLoader::loadBlock(Block& def, std::string name, fs::path file) {
|
|||||||
aabb.a = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2));
|
aabb.a = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2));
|
||||||
aabb.b = glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5));
|
aabb.b = glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5));
|
||||||
aabb.b += aabb.a;
|
aabb.b += aabb.a;
|
||||||
|
def.hitboxExplicit = true;
|
||||||
|
} else if (def.modelBoxes.empty()) {
|
||||||
|
def.hitboxExplicit = true;
|
||||||
|
} else {
|
||||||
|
def.hitbox = def.modelBoxes[0];
|
||||||
|
for (const auto& box : def.modelBoxes) {
|
||||||
|
def.hitbox.a = glm::min(def.hitbox.a, box.a);
|
||||||
|
def.hitbox.b = glm::max(def.hitbox.b, box.b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// block light emission [r, g, b] where r,g,b in range [0..15]
|
// block light emission [r, g, b] where r,g,b in range [0..15]
|
||||||
|
|||||||
@ -190,20 +190,30 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible
|
|||||||
const vec3 pos = PlayerController::selectedBlockPosition;
|
const vec3 pos = PlayerController::selectedBlockPosition;
|
||||||
const vec3 point = PlayerController::selectedPointPosition;
|
const vec3 point = PlayerController::selectedPointPosition;
|
||||||
const vec3 norm = PlayerController::selectedBlockNormal;
|
const vec3 norm = PlayerController::selectedBlockNormal;
|
||||||
AABB hitbox = block->hitbox;
|
|
||||||
|
std::vector<AABB> hitboxes;
|
||||||
|
if (!block->hitboxExplicit) {
|
||||||
|
hitboxes = block->modelBoxes;
|
||||||
|
} else {
|
||||||
|
hitboxes = { block->hitbox };
|
||||||
|
}
|
||||||
if (block->rotatable) {
|
if (block->rotatable) {
|
||||||
auto states = PlayerController::selectedBlockStates;
|
auto states = PlayerController::selectedBlockStates;
|
||||||
|
for (auto& hitbox: hitboxes) {
|
||||||
block->rotations.variants[states].transform(hitbox);
|
block->rotations.variants[states].transform(hitbox);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const vec3 center = pos + hitbox.center();
|
|
||||||
const vec3 size = hitbox.size();
|
|
||||||
linesShader->use();
|
linesShader->use();
|
||||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||||
lineBatch->lineWidth(2.0f);
|
lineBatch->lineWidth(2.0f);
|
||||||
|
for (auto& hitbox: hitboxes) {
|
||||||
|
const vec3 center = pos + hitbox.center();
|
||||||
|
const vec3 size = hitbox.size();
|
||||||
lineBatch->box(center, size + vec3(0.02), vec4(0.f, 0.f, 0.f, 0.5f));
|
lineBatch->box(center, size + vec3(0.02), vec4(0.f, 0.f, 0.f, 0.5f));
|
||||||
if (level->player->debug)
|
if (level->player->debug)
|
||||||
lineBatch->line(point, point+norm*0.5f, vec4(1.0f, 0.0f, 1.0f, 1.0f));
|
lineBatch->line(point, point+norm*0.5f, vec4(1.0f, 0.0f, 1.0f, 1.0f));
|
||||||
|
}
|
||||||
lineBatch->render();
|
lineBatch->render();
|
||||||
}
|
}
|
||||||
skybox->unbind();
|
skybox->unbind();
|
||||||
|
|||||||
@ -94,6 +94,7 @@ public:
|
|||||||
bool grounded = false;
|
bool grounded = false;
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
AABB hitbox;
|
AABB hitbox;
|
||||||
|
bool hitboxExplicit = false;
|
||||||
BlockRotProfile rotations;
|
BlockRotProfile rotations;
|
||||||
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
||||||
std::string scriptName = name.substr(name.find(':')+1);
|
std::string scriptName = name.substr(name.find(':')+1);
|
||||||
@ -105,6 +106,7 @@ public:
|
|||||||
bool solid = true;
|
bool solid = true;
|
||||||
bool emissive = false;
|
bool emissive = false;
|
||||||
AABB hitboxes[BlockRotProfile::MAX_COUNT];
|
AABB hitboxes[BlockRotProfile::MAX_COUNT];
|
||||||
|
std::vector<AABB> modelBoxes[BlockRotProfile::MAX_COUNT];
|
||||||
block_funcs_set funcsset {};
|
block_funcs_set funcsset {};
|
||||||
itemid_t pickingItem = 0;
|
itemid_t pickingItem = 0;
|
||||||
} rt;
|
} rt;
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
Chunks::Chunks(int w, int d,
|
Chunks::Chunks(int w, int d,
|
||||||
int ox, int oz,
|
int ox, int oz,
|
||||||
@ -52,7 +53,7 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){
|
|||||||
int ix = floor(x);
|
int ix = floor(x);
|
||||||
int iy = floor(y);
|
int iy = floor(y);
|
||||||
int iz = floor(z);
|
int iz = floor(z);
|
||||||
voxel* v = get(ix,iy,iz);
|
voxel* v = get(ix, iy, iz);
|
||||||
if (v == nullptr)
|
if (v == nullptr)
|
||||||
return &contentIds->getBlockDef(0)->hitbox;
|
return &contentIds->getBlockDef(0)->hitbox;
|
||||||
const Block* def = contentIds->getBlockDef(v->id);
|
const Block* def = contentIds->getBlockDef(v->id);
|
||||||
@ -62,10 +63,17 @@ const AABB* Chunks::isObstacleAt(float x, float y, float z){
|
|||||||
: def->hitbox;
|
: def->hitbox;
|
||||||
if (def->rt.solid) {
|
if (def->rt.solid) {
|
||||||
return &hitbox;
|
return &hitbox;
|
||||||
} else {
|
} else if (def->hitboxExplicit) {
|
||||||
if (hitbox.contains({x - ix, y - iy, z - iz}))
|
if (hitbox.contains({x - ix, y - iy, z - iz}))
|
||||||
return &hitbox;
|
return &hitbox;
|
||||||
return nullptr;
|
} else {
|
||||||
|
const auto& boxes = def->rotatable
|
||||||
|
? def->rt.modelBoxes[v->rotation()]
|
||||||
|
: def->modelBoxes;
|
||||||
|
for (const auto& hitbox : boxes) {
|
||||||
|
if (hitbox.contains({x - ix, y - iy, z - iz}))
|
||||||
|
return &hitbox;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -239,16 +247,28 @@ voxel* Chunks::rayCast(glm::vec3 start,
|
|||||||
iend.z = iz;
|
iend.z = iz;
|
||||||
|
|
||||||
if (!def->rt.solid) {
|
if (!def->rt.solid) {
|
||||||
const AABB& box = def->rotatable
|
std::vector<AABB> hitboxes;
|
||||||
|
if (def->hitboxExplicit) {
|
||||||
|
hitboxes = {
|
||||||
|
def->rotatable
|
||||||
? def->rt.hitboxes[voxel->rotation()]
|
? def->rt.hitboxes[voxel->rotation()]
|
||||||
: def->hitbox;
|
: def->hitbox
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
hitboxes = def->rotatable
|
||||||
|
? def->rt.modelBoxes[voxel->rotation()]
|
||||||
|
: def->modelBoxes;
|
||||||
|
}
|
||||||
|
|
||||||
scalar_t distance;
|
scalar_t distance;
|
||||||
Ray ray(start, dir);
|
Ray ray(start, dir);
|
||||||
if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None){
|
|
||||||
|
for (const auto& box : hitboxes) {
|
||||||
|
if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None) {
|
||||||
end = start + (dir * glm::vec3(distance));
|
end = start + (dir * glm::vec3(distance));
|
||||||
return voxel;
|
return voxel;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
iend.x = ix;
|
iend.x = ix;
|
||||||
iend.y = iy;
|
iend.y = iy;
|
||||||
@ -337,15 +357,28 @@ glm::vec3 Chunks::rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDis
|
|||||||
const Block* def = contentIds->getBlockDef(voxel->id);
|
const Block* def = contentIds->getBlockDef(voxel->id);
|
||||||
if (def->obstacle) {
|
if (def->obstacle) {
|
||||||
if (!def->rt.solid) {
|
if (!def->rt.solid) {
|
||||||
const AABB& box = def->rotatable
|
std::vector<AABB> hitboxes;
|
||||||
|
if (def->hitboxExplicit) {
|
||||||
|
hitboxes = {
|
||||||
|
def->rotatable
|
||||||
? def->rt.hitboxes[voxel->rotation()]
|
? def->rt.hitboxes[voxel->rotation()]
|
||||||
: def->hitbox;
|
: def->hitbox
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
hitboxes = def->rotatable
|
||||||
|
? def->rt.modelBoxes[voxel->rotation()]
|
||||||
|
: def->modelBoxes;
|
||||||
|
}
|
||||||
|
|
||||||
scalar_t distance;
|
scalar_t distance;
|
||||||
glm::ivec3 norm;
|
glm::ivec3 norm;
|
||||||
Ray ray(start, dir);
|
Ray ray(start, dir);
|
||||||
|
|
||||||
|
for (const auto& box : hitboxes) {
|
||||||
// norm is dummy now, can be inefficient
|
// norm is dummy now, can be inefficient
|
||||||
if (ray.intersectAABB(glm::ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) {
|
if (ray.intersectAABB(glm::ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) {
|
||||||
return start + (dir * glm::vec3(distance));
|
return start + (dir * glm::vec3(distance));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user