mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-14 07:21:51 +00:00
Merge pull request #1037 from cutekitek/physics-broadphase
Some checks are pending
Some checks are pending
Оптимизация физического движка
This commit is contained in:
commit
2e2233a489
2 changed files with 119 additions and 18 deletions
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
inline constexpr float E = 0.03f;
|
inline constexpr float E = 0.03f;
|
||||||
inline constexpr float MAX_FIX = 0.1f;
|
inline constexpr float MAX_FIX = 0.1f;
|
||||||
|
inline constexpr int MAX_NEARBY_REBUILDS = 4;
|
||||||
|
|
||||||
static debug::Logger logger("physics-solver");
|
static debug::Logger logger("physics-solver");
|
||||||
|
|
||||||
|
|
@ -141,12 +142,15 @@ static void calc_collision(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsSolver::calcCollisionNegY(
|
bool PhysicsSolver::calcCollisionNegY(
|
||||||
Hitbox& hitbox, const glm::vec3& half, float dt
|
Hitbox& hitbox,
|
||||||
|
const glm::vec3& half,
|
||||||
|
float dt,
|
||||||
|
const std::vector<Hitbox*>& solids
|
||||||
) {
|
) {
|
||||||
auto& pos = hitbox.position;
|
auto& pos = hitbox.position;
|
||||||
auto& vel = hitbox.velocity;
|
auto& vel = hitbox.velocity;
|
||||||
|
|
||||||
for (auto box : solidHitboxes) {
|
for (auto box : solids) {
|
||||||
if (glm::distance2(box->position, pos) < E) {
|
if (glm::distance2(box->position, pos) < E) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -215,23 +219,24 @@ void PhysicsSolver::calcCollisions(
|
||||||
glm::vec3& pos,
|
glm::vec3& pos,
|
||||||
const glm::vec3& half,
|
const glm::vec3& half,
|
||||||
float stepHeight,
|
float stepHeight,
|
||||||
float dt
|
float dt,
|
||||||
|
const std::vector<Hitbox*>& solids
|
||||||
) {
|
) {
|
||||||
stepHeight = calc_step_height(chunks, pos, half, stepHeight);
|
stepHeight = calc_step_height(chunks, pos, half, stepHeight);
|
||||||
|
|
||||||
auto prevPos = pos;
|
auto prevPos = pos;
|
||||||
|
|
||||||
calc_collision<0, 1, 2, -1>(hitbox, chunks, solidHitboxes, half, stepHeight);
|
calc_collision<0, 1, 2, -1>(hitbox, chunks, solids, half, stepHeight);
|
||||||
calc_collision<0, 1, 2, 1>(hitbox, chunks, solidHitboxes, half, stepHeight);
|
calc_collision<0, 1, 2, 1>(hitbox, chunks, solids, half, stepHeight);
|
||||||
|
|
||||||
float xpos = pos.x;
|
float xpos = pos.x;
|
||||||
pos.x = prevPos.x;
|
pos.x = prevPos.x;
|
||||||
|
|
||||||
calc_collision<2, 1, 0, -1>(hitbox, chunks, solidHitboxes, half, stepHeight);
|
calc_collision<2, 1, 0, -1>(hitbox, chunks, solids, half, stepHeight);
|
||||||
calc_collision<2, 1, 0, 1>(hitbox, chunks, solidHitboxes, half, stepHeight);
|
calc_collision<2, 1, 0, 1>(hitbox, chunks, solids, half, stepHeight);
|
||||||
pos.x = xpos;
|
pos.x = xpos;
|
||||||
|
|
||||||
if (calcCollisionNegY(hitbox, half, dt)) {
|
if (calcCollisionNegY(hitbox, half, dt, solids)) {
|
||||||
hitbox.grounded = true;
|
hitbox.grounded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,7 +260,7 @@ void PhysicsSolver::calcCollisions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto box : solidHitboxes) {
|
for (auto box : solids) {
|
||||||
if (glm::distance2(box->position, pos) < E) {
|
if (glm::distance2(box->position, pos) < E) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -297,7 +302,7 @@ void PhysicsSolver::calcCollisions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto box : solidHitboxes) {
|
for (auto box : solids) {
|
||||||
if (glm::distance2(box->position, pos) < E) {
|
if (glm::distance2(box->position, pos) < E) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +319,11 @@ void PhysicsSolver::calcCollisions(
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSolver::calcSubstep(
|
void PhysicsSolver::calcSubstep(
|
||||||
Hitbox& hitbox, glm::vec3& vel, glm::vec3& pos, float dt
|
Hitbox& hitbox,
|
||||||
|
glm::vec3& vel,
|
||||||
|
glm::vec3& pos,
|
||||||
|
float dt,
|
||||||
|
const std::vector<Hitbox*>& solids
|
||||||
) {
|
) {
|
||||||
auto initpos = pos;
|
auto initpos = pos;
|
||||||
auto half = hitbox.getHalfSize();
|
auto half = hitbox.getHalfSize();
|
||||||
|
|
@ -328,7 +337,8 @@ void PhysicsSolver::calcSubstep(
|
||||||
half,
|
half,
|
||||||
(hitbox.prevGrounded && gravityScale > 0.0f) ? hitbox.stepHeight
|
(hitbox.prevGrounded && gravityScale > 0.0f) ? hitbox.stepHeight
|
||||||
: 0.0f,
|
: 0.0f,
|
||||||
dt
|
dt,
|
||||||
|
solids
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +369,7 @@ void PhysicsSolver::calcSubstep(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto box : solidHitboxes) {
|
for (auto box : solids) {
|
||||||
if (glm::distance2(box->position, pos) < E) {
|
if (glm::distance2(box->position, pos) < E) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -376,6 +386,58 @@ void PhysicsSolver::calcSubstep(
|
||||||
hitbox.grounded = true;
|
hitbox.grounded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float calc_move_budget(
|
||||||
|
const Hitbox& hitbox, const glm::vec3& gravity, float time
|
||||||
|
) {
|
||||||
|
float speed = glm::length(hitbox.velocity) * 1.25f +
|
||||||
|
glm::length(gravity) * glm::abs(hitbox.gravityScale) * time;
|
||||||
|
return speed * time + 0.05f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static glm::vec3 calc_extents(const Hitbox& hitbox) {
|
||||||
|
return glm::max(hitbox.halfsize, hitbox.getHalfSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSolver::findNearbySolids(float time) {
|
||||||
|
size_t count = hitboxes.size();
|
||||||
|
nearbySolids.resize(count);
|
||||||
|
nearbyOrigins.resize(count);
|
||||||
|
nearbyBudgets.resize(count);
|
||||||
|
solidBudgets.resize(solidHitboxes.size());
|
||||||
|
|
||||||
|
float maxSolidHalfY = 0.0f;
|
||||||
|
for (size_t j = 0; j < solidHitboxes.size(); j++) {
|
||||||
|
const auto& box = *solidHitboxes[j];
|
||||||
|
solidBudgets[j] = calc_move_budget(box, gravity, time);
|
||||||
|
maxSolidHalfY = glm::max(maxSolidHalfY, calc_extents(box).y);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
const auto& hitbox = *hitboxes[i];
|
||||||
|
auto& solids = nearbySolids[i];
|
||||||
|
solids.clear();
|
||||||
|
nearbyOrigins[i] = hitbox.position;
|
||||||
|
nearbyBudgets[i] = calc_move_budget(hitbox, gravity, time);
|
||||||
|
|
||||||
|
auto ext = calc_extents(hitbox);
|
||||||
|
|
||||||
|
glm::vec3 reach(
|
||||||
|
0.5f,
|
||||||
|
hitbox.stepHeight * 2.0f + E * 8.0f + ext.y * 0.5f +
|
||||||
|
maxSolidHalfY + 0.5f + MAX_FIX * 2.0f,
|
||||||
|
0.5f
|
||||||
|
);
|
||||||
|
reach += ext + nearbyBudgets[i];
|
||||||
|
for (size_t j = 0; j < solidHitboxes.size(); j++) {
|
||||||
|
const auto& box = *solidHitboxes[j];
|
||||||
|
auto limit = reach + calc_extents(box) + solidBudgets[j];
|
||||||
|
auto diff = glm::abs(box.position - hitbox.position);
|
||||||
|
if (diff.x <= limit.x && diff.y <= limit.y && diff.z <= limit.z) {
|
||||||
|
solids.push_back(solidHitboxes[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicsSolver::step(
|
void PhysicsSolver::step(
|
||||||
const GlobalChunks& chunks, float delta, uint substeps
|
const GlobalChunks& chunks, float delta, uint substeps
|
||||||
) {
|
) {
|
||||||
|
|
@ -387,11 +449,32 @@ void PhysicsSolver::step(
|
||||||
}
|
}
|
||||||
|
|
||||||
float dt = delta / static_cast<float>(substeps);
|
float dt = delta / static_cast<float>(substeps);
|
||||||
|
findNearbySolids(delta);
|
||||||
|
|
||||||
|
int rebuildsLeft = MAX_NEARBY_REBUILDS;
|
||||||
for (uint i = 0; i < substeps; i++) {
|
for (uint i = 0; i < substeps; i++) {
|
||||||
for (auto hitbox : hitboxes) {
|
for (size_t j = 0; j < hitboxes.size(); j++) {
|
||||||
|
auto hitbox = hitboxes[j];
|
||||||
glm::vec3& pos = hitbox->position;
|
glm::vec3& pos = hitbox->position;
|
||||||
hitbox->prevPosition = hitbox->position;
|
hitbox->prevPosition = hitbox->position;
|
||||||
calcSubstep(*hitbox, hitbox->velocity, pos, dt);
|
calcSubstep(
|
||||||
|
*hitbox,
|
||||||
|
hitbox->velocity,
|
||||||
|
pos,
|
||||||
|
dt,
|
||||||
|
rebuildsLeft >= 0 ? nearbySolids[j] : solidHitboxes
|
||||||
|
);
|
||||||
|
if (rebuildsLeft < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto moved = glm::abs(pos - nearbyOrigins[j]);
|
||||||
|
if (glm::max(moved.x, glm::max(moved.y, moved.z)) >
|
||||||
|
nearbyBudgets[j]) {
|
||||||
|
if (--rebuildsLeft >= 0) {
|
||||||
|
findNearbySolids(dt * static_cast<float>(substeps - i));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,12 @@ private:
|
||||||
std::vector<Sensor*> sensors;
|
std::vector<Sensor*> sensors;
|
||||||
std::vector<Hitbox*> solidHitboxes;
|
std::vector<Hitbox*> solidHitboxes;
|
||||||
std::vector<Hitbox*> hitboxes;
|
std::vector<Hitbox*> hitboxes;
|
||||||
|
std::vector<std::vector<Hitbox*>> nearbySolids;
|
||||||
|
std::vector<glm::vec3> nearbyOrigins;
|
||||||
|
std::vector<float> nearbyBudgets;
|
||||||
|
std::vector<float> solidBudgets;
|
||||||
|
|
||||||
|
void findNearbySolids(float time);
|
||||||
|
|
||||||
void calcCollisions(
|
void calcCollisions(
|
||||||
Hitbox& hitbox,
|
Hitbox& hitbox,
|
||||||
|
|
@ -45,12 +51,24 @@ private:
|
||||||
glm::vec3& pos,
|
glm::vec3& pos,
|
||||||
const glm::vec3& half,
|
const glm::vec3& half,
|
||||||
float stepHeight,
|
float stepHeight,
|
||||||
float dt
|
float dt,
|
||||||
|
const std::vector<Hitbox*>& solids
|
||||||
);
|
);
|
||||||
|
|
||||||
void calcSubstep(Hitbox& hitbox, glm::vec3& vel, glm::vec3& pos, float dt);
|
void calcSubstep(
|
||||||
|
Hitbox& hitbox,
|
||||||
|
glm::vec3& vel,
|
||||||
|
glm::vec3& pos,
|
||||||
|
float dt,
|
||||||
|
const std::vector<Hitbox*>& solids
|
||||||
|
);
|
||||||
|
|
||||||
bool calcCollisionNegY(Hitbox& hitbox, const glm::vec3& half, float dt);
|
bool calcCollisionNegY(
|
||||||
|
Hitbox& hitbox,
|
||||||
|
const glm::vec3& half,
|
||||||
|
float dt,
|
||||||
|
const std::vector<Hitbox*>& solids
|
||||||
|
);
|
||||||
|
|
||||||
void updateSensors(Hitbox& hitbox);
|
void updateSensors(Hitbox& hitbox);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue