diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index e707d1637..35ea961ec 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -229,8 +229,8 @@ PlayerController::PlayerController( } void PlayerController::onFootstep(const Hitbox& hitbox) { - auto pos = hitbox.position; - auto half = hitbox.halfsize; + const auto& pos = hitbox.position; + const auto& half = hitbox.getHalfSize(); for (int offsetZ = -1; offsetZ <= 1; offsetZ++) { for (int offsetX = -1; offsetX <= 1; offsetX++) { diff --git a/src/logic/scripting/lua/libs/lib__transform.cpp b/src/logic/scripting/lua/libs/lib__transform.cpp index 7cf7bed62..16662daaa 100644 --- a/src/logic/scripting/lua/libs/lib__transform.cpp +++ b/src/logic/scripting/lua/libs/lib__transform.cpp @@ -31,7 +31,7 @@ static int l_set_pos(lua::State* L) { auto vec = lua::tovec3(L, 2); check_valid(vec); entity->getTransform().setPos(vec); - entity->getRigidbody().hitbox.position = vec; + entity->getRigidbody().hitbox.setPos(vec); } return 0; } diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index 53b606da8..de1e9796d 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -316,30 +316,36 @@ void Entities::updatePhysics(float delta) { auto view = registry->view(); auto physics = level.physics.get(); - for (auto [entity, eid, transform, rigidbody] : view.each()) { - if (!rigidbody.enabled || rigidbody.hitbox.type == BodyType::STATIC) { - continue; - } - auto& hitbox = rigidbody.hitbox; - auto prevVel = hitbox.velocity; - bool grounded = hitbox.grounded; - float vel = glm::length(prevVel); - int substeps = static_cast(delta * vel * 20); - substeps = std::min(100, std::max(2, substeps)); - physics->step(*level.chunks, hitbox, delta, substeps, eid.uid); - hitbox.friction = glm::abs(hitbox.gravityScale <= 1e-7f) - ? 8.0f - : (!grounded ? 2.0f : 10.0f); - hitbox.scale = transform.size; - transform.setPos(hitbox.position); - if (hitbox.grounded && !grounded) { - scripting::on_entity_grounded( - *get(eid.uid), glm::length(prevVel - hitbox.velocity) - ); - } - if (!hitbox.grounded && grounded) { - scripting::on_entity_fall(*get(eid.uid)); + for (int solid = false; solid <= true; solid++) { + for (auto [entity, eid, transform, rigidbody] : view.each()) { + if (!rigidbody.enabled || rigidbody.hitbox.type == BodyType::STATIC) { + continue; + } + if (eid.def.solid == solid) { + continue; + } + auto& hitbox = rigidbody.hitbox; + auto prevVel = hitbox.velocity; + bool grounded = hitbox.grounded; + + float vel = glm::length(prevVel); + int substeps = static_cast(delta * vel * 20); + substeps = std::min(100, std::max(2, substeps)); + physics->step(*level.chunks, hitbox, delta, substeps, eid.uid); + hitbox.friction = glm::abs(hitbox.gravityScale <= 1e-7f) + ? 8.0f + : (!grounded ? 2.0f : 10.0f); + hitbox.scale = transform.size; + transform.setPos(hitbox.position); + if (hitbox.grounded && !grounded) { + scripting::on_entity_grounded( + *get(eid.uid), glm::length(prevVel - hitbox.velocity) + ); + } + if (!hitbox.grounded && grounded) { + scripting::on_entity_fall(*get(eid.uid)); + } } } } diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index a63341d49..b77a07fdd 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -114,7 +114,7 @@ void Player::teleport(glm::vec3 position) { this->position = position; if (auto entity = level.entities->get(eid)) { - entity->getRigidbody().hitbox.position = position; + entity->getRigidbody().hitbox.setPos(position); entity->getTransform().setPos(position); entity->setInterpolatedPosition(position); } diff --git a/src/physics/Hitbox.cpp b/src/physics/Hitbox.cpp index adf078418..a72bdd939 100644 --- a/src/physics/Hitbox.cpp +++ b/src/physics/Hitbox.cpp @@ -6,5 +6,6 @@ Hitbox::Hitbox(BodyType type, glm::vec3 position, glm::vec3 halfsize) : type(type), position(position), halfsize(halfsize), - velocity(0.0f,0.0f,0.0f) + velocity(0.0f,0.0f,0.0f), + prevPosition(position) {} diff --git a/src/physics/Hitbox.hpp b/src/physics/Hitbox.hpp index 870e24725..799367b50 100644 --- a/src/physics/Hitbox.hpp +++ b/src/physics/Hitbox.hpp @@ -1,5 +1,7 @@ #pragma once +#define GLM_ENABLE_EXPERIMENTAL + #include "maths/aabb.hpp" #include "typedefs.hpp" #include "util/EnumMetadata.hpp" @@ -8,6 +10,7 @@ #include #include #include +#include enum class SensorType { AABB, @@ -62,6 +65,13 @@ struct Hitbox { bool crouching = false; float stepHeight = 0.5f; glm::vec3 groundVelocity {}; + + // garbage tbh + glm::vec3 prevPosition {}; + int substeps = 1; + float delta = 0.0f; + + static inline constexpr float TELEPORT_THRESOLD_SQR = 0.5f; Hitbox(BodyType type, glm::vec3 position, glm::vec3 halfsize); @@ -72,4 +82,11 @@ struct Hitbox { glm::vec3 getHalfSize() const { return halfsize * scale; } + + void setPos(const glm::vec3& vec) { + position = vec; + if (glm::distance2(position, prevPosition) >= TELEPORT_THRESOLD_SQR) { + prevPosition = vec; + } + } }; diff --git a/src/physics/PhysicsSolver.cpp b/src/physics/PhysicsSolver.cpp index 225a9ecbb..ee47f0a8b 100644 --- a/src/physics/PhysicsSolver.cpp +++ b/src/physics/PhysicsSolver.cpp @@ -208,7 +208,7 @@ static bool calc_collision_neg_y( if (pos.y < newy && glm::abs(pos.y - newy) < 0.5f) { pos.y = newy; } - groundVelocty = box->velocity; + groundVelocty = (box->position - box->prevPosition) / box->delta; if (vel.y < 0.0f) { vel.y = 0.0f; return true; @@ -362,8 +362,14 @@ void PhysicsSolver::calcSubstep( glm::vec3& vel, glm::vec3& pos, bool prevGrounded, - float dt + float dt, + int substeps ) { + if (hitbox.grounded) { + pos.x += hitbox.groundVelocity.x * dt * substeps; + pos.z += hitbox.groundVelocity.z * dt * substeps; + } + auto initpos = pos; auto half = hitbox.getHalfSize(); float gravityScale = hitbox.gravityScale; @@ -434,6 +440,10 @@ void PhysicsSolver::step( uint substeps, entityid_t entity ) { + hitbox.prevPosition = hitbox.position; + hitbox.substeps = substeps; + hitbox.delta = delta; + float dt = delta / static_cast(substeps); float linearDamping = hitbox.linearDamping * hitbox.friction; @@ -443,12 +453,7 @@ void PhysicsSolver::step( bool prevGrounded = hitbox.grounded; hitbox.grounded = false; for (uint i = 0; i < substeps; i++) { - calcSubstep(chunks, hitbox, vel, pos, prevGrounded, dt); - } - - if (prevGrounded && !hitbox.grounded) { - vel += hitbox.groundVelocity; - hitbox.groundVelocity = {}; + calcSubstep(chunks, hitbox, vel, pos, prevGrounded, dt, substeps); } vel.x /= 1.0f + delta * linearDamping; @@ -456,6 +461,11 @@ void PhysicsSolver::step( if (hitbox.verticalDamping > 0.0f) { vel.y /= 1.0f + delta * linearDamping * hitbox.verticalDamping; } + if (prevGrounded && !hitbox.grounded) { + auto appliedVelocity = hitbox.groundVelocity; + vel += appliedVelocity; + hitbox.groundVelocity = {}; + } AABB aabb; aabb.a = pos - hitbox.getHalfSize(); diff --git a/src/physics/PhysicsSolver.hpp b/src/physics/PhysicsSolver.hpp index 052cf58e3..888c239d3 100644 --- a/src/physics/PhysicsSolver.hpp +++ b/src/physics/PhysicsSolver.hpp @@ -53,6 +53,7 @@ private: glm::vec3& vel, glm::vec3& pos, bool prevGrounded, - float dt + float dt, + int substeps ); };