add more reason to physics simulation substeps

This commit is contained in:
MihailRis 2026-03-11 22:08:40 +03:00
parent 794ce07bd5
commit 4b4f2439c0
5 changed files with 119 additions and 114 deletions

View file

@ -80,7 +80,7 @@ entityid_t Entities::spawn(
entities[id] = entity;
uids[entity] = id;
registry->emplace<EntityId>(entity, static_cast<entityid_t>(id), def);
registry->emplace<EntityId>(entity, id, def);
const auto& tsf = registry->emplace<Transform>(
entity,
position,
@ -92,7 +92,7 @@ entityid_t Entities::spawn(
auto& body = registry->emplace<Rigidbody>(
entity,
true,
Hitbox {def.bodyType, position, def.hitbox * 0.5f},
Hitbox {id, def.bodyType, position, def.hitbox * 0.5f},
std::vector<Sensor> {}
);
body.initialize(def, id, *this);
@ -280,6 +280,7 @@ void Entities::updateSensors(
void Entities::preparePhysics(float delta) {
auto& physics = *level.physics;
auto& hitboxes = physics.getHitboxesWriteable();
auto& solidHitboxes = physics.getSolidHitboxesWriteable();
if (sensorsTickClock.update(delta)) {
@ -301,11 +302,16 @@ void Entities::preparePhysics(float delta) {
}
}
hitboxes.clear();
solidHitboxes.clear();
auto view = registry->view<EntityId, Rigidbody>();
for (auto [entity, eid, rigidbody] : view.each()) {
if (!eid.def.solid || eid.destroyFlag || !rigidbody.enabled) {
if (eid.destroyFlag || !rigidbody.enabled) {
continue;
}
hitboxes.emplace_back(&rigidbody.hitbox);
if (!eid.def.solid) {
continue;
}
solidHitboxes.emplace_back(&rigidbody.hitbox);
@ -318,43 +324,31 @@ void Entities::updatePhysics(float delta) {
auto view = registry->view<EntityId, Transform, Rigidbody>();
auto physics = level.physics.get();
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;
int substeps = std::max<int>(std::min<int>(delta * 1000, 200), 8);
physics->step(*level.chunks, delta, substeps);
float vel = glm::length(prevVel);
int substeps = static_cast<int>(delta * (vel + 2.0f) * 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;
if (util::is_nan_or_inf(hitbox.position)) {
logger.error()
<< "physics simulation produced nan or inf (entity "
<< eid.def.name << "#" << eid.uid << ")";
hitbox.position = transform.pos;
} else {
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 (auto [entity, eid, transform, rigidbody] : view.each()) {
if (!rigidbody.enabled ||
rigidbody.hitbox.type == BodyType::STATIC) {
continue;
}
auto& hitbox = rigidbody.hitbox;
hitbox.scale = transform.size;
if (util::is_nan_or_inf(hitbox.position)) {
logger.error()
<< "physics simulation produced nan or inf (entity "
<< eid.def.name << "#" << eid.uid << ")";
hitbox.position = transform.pos;
} else {
transform.setPos(hitbox.position);
}
if (hitbox.grounded && !hitbox.prevGrounded) {
scripting::on_entity_grounded(
*get(eid.uid), glm::length(hitbox.prevVelocity - hitbox.velocity)
);
}
if (!hitbox.grounded && hitbox.prevGrounded) {
scripting::on_entity_fall(*get(eid.uid));
}
}
}