mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-12 14:31:50 +00:00
feat: third-person camera now checks solid entities
This commit is contained in:
parent
15bbf55e29
commit
fc57e98a96
3 changed files with 29 additions and 9 deletions
|
|
@ -44,7 +44,9 @@ namespace {
|
||||||
const float CROUCH_SHIFT_Y = -0.2f;
|
const float CROUCH_SHIFT_Y = -0.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraControl::CameraControl(Player& player, const CameraSettings& settings)
|
CameraControl::CameraControl(
|
||||||
|
Player& player, const CameraSettings& settings
|
||||||
|
)
|
||||||
: player(player),
|
: player(player),
|
||||||
camera(player.fpCamera),
|
camera(player.fpCamera),
|
||||||
settings(settings),
|
settings(settings),
|
||||||
|
|
@ -195,18 +197,30 @@ void CameraControl::update(
|
||||||
|
|
||||||
refreshPosition();
|
refreshPosition();
|
||||||
|
|
||||||
|
auto castRay = [](Player& player, Camera& camera, const glm::vec3& front)
|
||||||
|
-> glm::vec3 {
|
||||||
|
auto blockEnd = player.chunks->rayCastToObstacle(camera.position, front, 3.0f);
|
||||||
|
auto entityRay = player.getLevel().entities->rayCast(
|
||||||
|
camera.position, front, 3.0f, player.getEntity(), true
|
||||||
|
);
|
||||||
|
if (entityRay.has_value() &&
|
||||||
|
entityRay->distance < glm::distance(camera.position, blockEnd)) {
|
||||||
|
return (camera.position + front * entityRay->distance);
|
||||||
|
} else {
|
||||||
|
return blockEnd;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
camera->updateVectors();
|
camera->updateVectors();
|
||||||
if (player.currentCamera == spCamera) {
|
if (player.currentCamera == spCamera) {
|
||||||
spCamera->position =
|
spCamera->position =
|
||||||
chunks.rayCastToObstacle(camera->position, camera->front, 3.0f) -
|
castRay(player, *camera, camera->front) - 0.4f * camera->front;
|
||||||
0.4f * camera->front;
|
|
||||||
spCamera->dir = -camera->dir;
|
spCamera->dir = -camera->dir;
|
||||||
spCamera->front = -camera->front;
|
spCamera->front = -camera->front;
|
||||||
spCamera->right = -camera->right;
|
spCamera->right = -camera->right;
|
||||||
} else if (player.currentCamera == tpCamera) {
|
} else if (player.currentCamera == tpCamera) {
|
||||||
tpCamera->position =
|
tpCamera->position = castRay(player, *camera, camera->front * -1.0f) +
|
||||||
chunks.rayCastToObstacle(camera->position, -camera->front, 3.0f) +
|
0.4f * camera->front;
|
||||||
0.4f * camera->front;
|
|
||||||
tpCamera->dir = camera->dir;
|
tpCamera->dir = camera->dir;
|
||||||
tpCamera->front = camera->front;
|
tpCamera->front = camera->front;
|
||||||
tpCamera->right = camera->right;
|
tpCamera->right = camera->right;
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,11 @@ void Entities::loadEntity(const dv::value& map, Entity entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Entities::RaycastResult> Entities::rayCast(
|
std::optional<Entities::RaycastResult> Entities::rayCast(
|
||||||
glm::vec3 start, glm::vec3 dir, float maxDistance, entityid_t ignore
|
glm::vec3 start,
|
||||||
|
glm::vec3 dir,
|
||||||
|
float maxDistance,
|
||||||
|
entityid_t ignore,
|
||||||
|
bool solidOnly
|
||||||
) {
|
) {
|
||||||
Ray ray(start, dir);
|
Ray ray(start, dir);
|
||||||
auto view = registry->view<EntityId, Transform, Rigidbody>();
|
auto view = registry->view<EntityId, Transform, Rigidbody>();
|
||||||
|
|
@ -171,7 +175,7 @@ std::optional<Entities::RaycastResult> Entities::rayCast(
|
||||||
glm::ivec3 foundNormal;
|
glm::ivec3 foundNormal;
|
||||||
|
|
||||||
for (auto [entity, eid, transform, body] : view.each()) {
|
for (auto [entity, eid, transform, body] : view.each()) {
|
||||||
if (eid.uid == ignore || !body.enabled) {
|
if (eid.uid == ignore || !body.enabled || (solidOnly && !eid.def.solid)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto& hitbox = body.hitbox;
|
auto& hitbox = body.hitbox;
|
||||||
|
|
|
||||||
|
|
@ -88,12 +88,14 @@ public:
|
||||||
/// @param dir Ray direction normalized vector
|
/// @param dir Ray direction normalized vector
|
||||||
/// @param maxDistance Max ray length
|
/// @param maxDistance Max ray length
|
||||||
/// @param ignore Ignored entity ID
|
/// @param ignore Ignored entity ID
|
||||||
|
/// @param solidOnly If true, only entities with solid hitboxes will be checked
|
||||||
/// @return An optional structure containing entity, normal and distance
|
/// @return An optional structure containing entity, normal and distance
|
||||||
std::optional<RaycastResult> rayCast(
|
std::optional<RaycastResult> rayCast(
|
||||||
glm::vec3 start,
|
glm::vec3 start,
|
||||||
glm::vec3 dir,
|
glm::vec3 dir,
|
||||||
float maxDistance,
|
float maxDistance,
|
||||||
entityid_t ignore = -1
|
entityid_t ignore = -1,
|
||||||
|
bool solidOnly = false
|
||||||
);
|
);
|
||||||
|
|
||||||
void loadEntities(dv::value map);
|
void loadEntities(dv::value map);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue