add entities raycast

This commit is contained in:
MihailRis 2024-07-14 10:50:06 +03:00
parent 638a0d9850
commit c17f3fec54
8 changed files with 90 additions and 15 deletions

View File

@ -19,6 +19,7 @@ inline const std::string ENGINE_VERSION_STRING = "0.22";
inline constexpr blockid_t BLOCK_AIR = 0;
inline constexpr itemid_t ITEM_EMPTY = 0;
inline constexpr entityid_t ENTITY_NONE = 0;
inline constexpr int CHUNK_W = 16;
inline constexpr int CHUNK_H = 256;

View File

@ -12,6 +12,7 @@
#include "../logic/scripting/scripting.hpp"
#include "../objects/Player.hpp"
#include "../objects/Entities.hpp"
#include "../objects/EntityDef.hpp"
#include "../physics/Hitbox.hpp"
#include "../util/stringutil.hpp"
#include "../voxels/Block.hpp"
@ -60,24 +61,24 @@ std::shared_ptr<UINode> create_debug_panel(
fpsMin = fps;
fpsMax = fps;
});
panel->add(create_label([](){ return L"fps: "+fpsString;}));
panel->add(create_label([]() { return L"fps: "+fpsString;}));
panel->add(create_label([](){
panel->add(create_label([]() {
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
}));
panel->add(create_label([](){
panel->add(create_label([]() {
int drawCalls = Mesh::drawCalls;
Mesh::drawCalls = 0;
return L"draw-calls: " + std::to_wstring(drawCalls);
}));
panel->add(create_label([](){
panel->add(create_label([]() {
return L"speakers: " + std::to_wstring(audio::count_speakers())+
L" streams: " + std::to_wstring(audio::count_streams());
}));
panel->add(create_label([](){
panel->add(create_label([]() {
return L"lua-stack: " + std::to_wstring(scripting::get_values_on_stack());
}));
panel->add(create_label([=](){
panel->add(create_label([=]() {
auto& settings = engine->getSettings();
bool culling = settings.graphics.frustumCulling.get();
return L"frustum-culling: "+std::wstring(culling ? L"on" : L"off");
@ -90,7 +91,7 @@ std::shared_ptr<UINode> create_debug_panel(
return L"entities: "+std::to_wstring(level->entities->size())+L" next: "+
std::to_wstring(level->entities->peekNextID());
}));
panel->add(create_label([=](){
panel->add(create_label([=]() {
const auto& vox = player->selection.vox;
std::wstringstream stream;
stream << "r:" << vox.state.rotation << " s:"
@ -103,6 +104,17 @@ std::shared_ptr<UINode> create_debug_panel(
L" "+stream.str();
}
}));
panel->add(create_label([=]() {
const auto& selection = player->selection;
if (selection.entity == ENTITY_NONE) {
return std::wstring {L"entity: -"};
} else if (auto entity = level->entities->get(selection.entity)) {
return L"entity: "+util::str2wstr_utf8(entity->getDef().name)+
L" uid: "+std::to_wstring(entity->getUID());
} else {
return std::wstring {L"entity: error (invalid UID)"};
}
}));
panel->add(create_label([=](){
auto* indices = level->content->getIndices();
if (auto def = indices->blocks.get(player->selection.vox.id)) {

View File

@ -264,8 +264,7 @@ void PlayerController::postUpdate(float delta, bool input, bool pause) {
if (input) {
updateInteraction();
} else {
player->selection.vox.id = BLOCK_VOID;
player->selection.vox.state.rotation = 0;
player->selection = {};
}
}
@ -365,13 +364,25 @@ voxel* PlayerController::updateSelection(float maxDistance) {
maxDistance,
end, norm, iend
);
if (vox == nullptr) {
if (vox) {
maxDistance = glm::distance(camera->position, end);
}
selection.entity = ENTITY_NONE;
selection.actualPosition = iend;
if (auto result = level->entities->rayCast(
camera->position, camera->front, maxDistance, player->getEntity())) {
selection.entity = result->entity;
selection.hitPosition = camera->position + camera->front * result->distance;
selection.position = selection.hitPosition;
selection.actualPosition = selection.position;
selection.normal = result->normal;
}
if (vox == nullptr || selection.entity) {
selection.vox = {BLOCK_VOID, {}};
return nullptr;
}
blockstate selectedState = vox->state;
selection.vox = *vox;
selection.actualPosition = iend;
if (selectedState.segment) {
selection.position = chunks->seekOrigin(
iend, indices->blocks.get(selection.vox.id), selectedState

View File

@ -4,6 +4,7 @@
#include "../data/dynamic_util.hpp"
#include "../assets/Assets.hpp"
#include "../world/Level.hpp"
#include "../maths/rays.hpp"
#include "../content/Content.hpp"
#include "../physics/Hitbox.hpp"
#include "../physics/PhysicsSolver.hpp"
@ -185,6 +186,37 @@ void Entities::loadEntity(const dynamic::Map_sptr& map, Entity entity) {
}
}
std::optional<Entities::RaycastResult> Entities::rayCast(
glm::vec3 start, glm::vec3 dir, float maxDistance, entityid_t ignore
) {
Ray ray(start, dir);
auto view = registry.view<EntityId, Transform, Rigidbody>();
entityid_t foundUID = 0;
glm::ivec3 foundNormal;
for (auto [entity, eid, transform, body] : view.each()) {
if (eid.uid == ignore) {
continue;
}
auto& hitbox = body.hitbox;
glm::ivec3 normal;
double distance;
if (ray.intersectAABB(
glm::vec3(), hitbox.getAABB(), maxDistance, normal, distance) > RayRelation::None) {
foundUID = eid.uid;
foundNormal = normal;
maxDistance = static_cast<float>(distance);
}
}
if (foundUID) {
return Entities::RaycastResult {foundUID, foundNormal, maxDistance};
} else {
return std::nullopt;
}
}
void Entities::loadEntities(dynamic::Map_sptr root) {
auto list = root->list("data");
for (size_t i = 0; i < list->size(); i++) {

View File

@ -160,6 +160,12 @@ class Entities {
void preparePhysics();
public:
struct RaycastResult {
entityid_t entity;
glm::ivec3 normal;
float distance;
};
Entities(Level* level);
void clean();
@ -184,6 +190,16 @@ public:
return std::nullopt;
}
/// @brief Entities raycast. No blocks check included, use combined with
/// Chunks.rayCast
/// @param start Ray start
/// @param dir Ray direction normalized vector
/// @param maxDistance Max ray length
/// @param ignore Ignored entity ID
/// @return An optional structure containing entity, normal and distance
std::optional<RaycastResult> rayCast(
glm::vec3 start, glm::vec3 dir, float maxDistance, entityid_t ignore=-1);
void loadEntities(dynamic::Map_sptr map);
void loadEntity(const dynamic::Map_sptr& map);
void loadEntity(const dynamic::Map_sptr& map, Entity entity);

View File

@ -60,6 +60,7 @@ Hitbox* Player::getHitbox() {
return nullptr;
}
#include "EntityDef.hpp"
void Player::updateInput(PlayerInput& input, float delta) {
auto hitbox = getHitbox();
if (hitbox == nullptr) {

View File

@ -33,12 +33,13 @@ struct PlayerInput {
bool flight : 1;
};
struct BlockSelection {
voxel vox {0, {}};
struct CursorSelection {
voxel vox {BLOCK_VOID, {}};
glm::ivec3 position {};
glm::ivec3 actualPosition {};
glm::ivec3 normal {};
glm::vec3 hitPosition;
entityid_t entity = ENTITY_NONE;
};
class Player : public Object, public Serializable {
@ -56,7 +57,7 @@ public:
std::shared_ptr<Camera> currentCamera;
bool debug = false;
glm::vec3 cam {};
BlockSelection selection {};
CursorSelection selection {};
Player(Level* level, glm::vec3 position, float speed,
std::shared_ptr<Inventory> inv, entityid_t eid);

View File

@ -461,7 +461,8 @@ voxel* Chunks::rayCast(
box.b += offset;
scalar_t boxDistance;
glm::ivec3 boxNorm;
if (ray.intersectAABB(iend, box, maxDist, boxNorm, boxDistance) > RayRelation::None && boxDistance < distance) {
if (ray.intersectAABB(iend, box, maxDist, boxNorm, boxDistance) > RayRelation::None &&
boxDistance < distance) {
hit = true;
distance = boxDistance;
norm = boxNorm;