libblock.raycast: Add argument to specify blocks to ignore during ray casting

libentity.raycast: Add argument to specify blocks to ignore during ray casting
Chunk::rayCast: Add argument to specify blocks to ignore during ray casting.

On lua side filter blocks are passed as list of strings in form of "MOD:BLOCK_NAME"
On C++ size filter blocks are std::set of blockid_t
This commit is contained in:
REDxEYE 2024-08-19 21:36:30 +03:00
parent 8ef288c189
commit 1be50c2e06
4 changed files with 56 additions and 12 deletions

View File

@ -353,13 +353,30 @@ static int l_raycast(lua::State* L) {
auto start = lua::tovec<3>(L, 1); auto start = lua::tovec<3>(L, 1);
auto dir = lua::tovec<3>(L, 2); auto dir = lua::tovec<3>(L, 2);
auto maxDistance = lua::tonumber(L, 3); auto maxDistance = lua::tonumber(L, 3);
std::set<blockid_t> filteredBlocks {};
if (lua::gettop(L) >= 5) {
if (lua::istable(L, 5)) {
int addLen = lua::objlen(L, 5);
for (int i = 0; i < addLen; i++) {
lua::rawgeti(L, i + 1, 5);
auto blockName = std::string(lua::tostring(L, -1));
Block* block = content->blocks.find(blockName);
if (block != nullptr) {
filteredBlocks.insert(block->rt.id);
}
lua::pop(L);
}
} else {
throw std::runtime_error("table expected for filter");
}
}
glm::vec3 end; glm::vec3 end;
glm::ivec3 normal; glm::ivec3 normal;
glm::ivec3 iend; glm::ivec3 iend;
if (auto voxel = level->chunks->rayCast( if (auto voxel = level->chunks->rayCast(
start, dir, maxDistance, end, normal, iend start, dir, maxDistance, end, normal, iend, filteredBlocks
)) { )) {
if (lua::gettop(L) >= 4) { if (lua::gettop(L) >= 4 && !lua::isnil(L, 4)) {
lua::pushvalue(L, 4); lua::pushvalue(L, 4);
} else { } else {
lua::createtable(L, 0, 5); lua::createtable(L, 0, 5);
@ -452,4 +469,5 @@ const luaL_Reg blocklib[] = {
{"raycast", lua::wrap<l_raycast>}, {"raycast", lua::wrap<l_raycast>},
{"compose_state", lua::wrap<l_compose_state>}, {"compose_state", lua::wrap<l_compose_state>},
{"decompose_state", lua::wrap<l_decompose_state>}, {"decompose_state", lua::wrap<l_decompose_state>},
{NULL, NULL}}; {NULL, NULL}
};

View File

@ -8,6 +8,7 @@
#include "objects/rigging.hpp" #include "objects/rigging.hpp"
#include "physics/Hitbox.hpp" #include "physics/Hitbox.hpp"
#include "voxels/Chunks.hpp" #include "voxels/Chunks.hpp"
#include "voxels/Block.hpp"
#include "window/Camera.hpp" #include "window/Camera.hpp"
using namespace scripting; using namespace scripting;
@ -118,7 +119,25 @@ static int l_raycast(lua::State* L) {
auto start = lua::tovec<3>(L, 1); auto start = lua::tovec<3>(L, 1);
auto dir = lua::tovec<3>(L, 2); auto dir = lua::tovec<3>(L, 2);
auto maxDistance = lua::tonumber(L, 3); auto maxDistance = lua::tonumber(L, 3);
auto ignore = lua::tointeger(L, 4); auto ignoreEntityId = lua::tointeger(L, 4);
std::set<blockid_t> filteredBlocks {};
if (lua::gettop(L) >= 6) {
if (lua::istable(L, 6)) {
int addLen = lua::objlen(L, 6);
for (int i = 0; i < addLen; i++) {
lua::rawgeti(L, i + 1, 6);
auto blockName = std::string(lua::tostring(L, -1));
Block* block = content->blocks.find(blockName);
if (block != nullptr) {
filteredBlocks.insert(block->rt.id);
}
lua::pop(L);
}
} else {
throw std::runtime_error("table expected for filter");
}
}
glm::vec3 end; glm::vec3 end;
glm::ivec3 normal; glm::ivec3 normal;
glm::ivec3 iend; glm::ivec3 iend;
@ -126,13 +145,14 @@ static int l_raycast(lua::State* L) {
blockid_t block = BLOCK_VOID; blockid_t block = BLOCK_VOID;
if (auto voxel = level->chunks->rayCast( if (auto voxel = level->chunks->rayCast(
start, dir, maxDistance, end, normal, iend start, dir, maxDistance, end, normal, iend, filteredBlocks
)) { )) {
maxDistance = glm::distance(start, end); maxDistance = glm::distance(start, end);
block = voxel->id; block = voxel->id;
} }
if (auto ray = level->entities->rayCast(start, dir, maxDistance, ignore)) { if (auto ray =
if (lua::gettop(L) >= 5) { level->entities->rayCast(start, dir, maxDistance, ignoreEntityId)) {
if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) {
lua::pushvalue(L, 5); lua::pushvalue(L, 5);
} else { } else {
lua::createtable(L, 0, 6); lua::createtable(L, 0, 6);
@ -157,7 +177,7 @@ static int l_raycast(lua::State* L) {
lua::setfield(L, "entity"); lua::setfield(L, "entity");
return 1; return 1;
} else if (block != BLOCK_VOID) { } else if (block != BLOCK_VOID) {
if (lua::gettop(L) >= 5) { if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) {
lua::pushvalue(L, 5); lua::pushvalue(L, 5);
} else { } else {
lua::createtable(L, 0, 5); lua::createtable(L, 0, 5);
@ -194,4 +214,5 @@ const luaL_Reg entitylib[] = {
{"get_all_in_box", lua::wrap<l_get_all_in_box>}, {"get_all_in_box", lua::wrap<l_get_all_in_box>},
{"get_all_in_radius", lua::wrap<l_get_all_in_radius>}, {"get_all_in_radius", lua::wrap<l_get_all_in_radius>},
{"raycast", lua::wrap<l_raycast>}, {"raycast", lua::wrap<l_raycast>},
{NULL, NULL}}; {NULL, NULL}
};

View File

@ -414,7 +414,8 @@ voxel* Chunks::rayCast(
float maxDist, float maxDist,
glm::vec3& end, glm::vec3& end,
glm::ivec3& norm, glm::ivec3& norm,
glm::ivec3& iend glm::ivec3& iend,
std::set<blockid_t> filter
) { ) {
float px = start.x; float px = start.x;
float py = start.y; float py = start.y;
@ -454,8 +455,10 @@ voxel* Chunks::rayCast(
if (voxel == nullptr) { if (voxel == nullptr) {
return nullptr; return nullptr;
} }
const auto& def = indices->blocks.require(voxel->id); const auto& def = indices->blocks.require(voxel->id);
if (def.selectable) { if ((filter.empty() && def.selectable) ||
(!filter.empty() && filter.find(def.rt.id) == filter.end())) {
end.x = px + t * dx; end.x = px + t * dx;
end.y = py + t * dy; end.y = py + t * dy;
end.z = pz + t * dz; end.z = pz + t * dz;

View File

@ -4,6 +4,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <memory> #include <memory>
#include <set>
#include <vector> #include <vector>
#include "typedefs.hpp" #include "typedefs.hpp"
@ -93,7 +94,8 @@ public:
float maxLength, float maxLength,
glm::vec3& end, glm::vec3& end,
glm::ivec3& norm, glm::ivec3& norm,
glm::ivec3& iend glm::ivec3& iend,
std::set<blockid_t> filter = {}
); );
glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist); glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist);