rebuild the repulsion force grid every n frames

This commit is contained in:
2026-02-18 23:12:02 +01:00
parent 1dad350f7d
commit 55ff0f3490
5 changed files with 47 additions and 17 deletions

View File

@ -123,15 +123,15 @@ auto MassSpringSystem::CalculateSpringForces() -> void {
}
}
auto MassSpringSystem::CalculateRepulsionForces() -> void {
auto MassSpringSystem::BuildGrid() -> void {
const float INV_CELL = 1.0f / REPULSION_RANGE;
const int n = masses.size();
// Collect pointers
std::vector<Mass *> massVec;
massVec.reserve(n);
mass_vec.clear();
mass_vec.reserve(n);
for (auto &[state, mass] : masses) {
massVec.push_back(&mass);
mass_vec.push_back(&mass);
}
// Assign each particle a cell index
@ -145,21 +145,38 @@ auto MassSpringSystem::CalculateRepulsionForces() -> void {
};
// Sort particles by cell
std::vector<int> indices(n);
indices.clear();
indices.resize(n);
std::iota(indices.begin(), indices.end(), 0);
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
return cellID(massVec[a]->position) < cellID(massVec[b]->position);
return cellID(mass_vec[a]->position) < cellID(mass_vec[b]->position);
});
// Build cell start/end table
std::vector<int64_t> cellIDs(n);
cell_ids.clear();
cell_ids.resize(n);
for (int i = 0; i < n; ++i) {
cellIDs[i] = cellID(massVec[indices[i]]->position);
cell_ids[i] = cellID(mass_vec[indices[i]]->position);
}
}
auto MassSpringSystem::CalculateRepulsionForces() -> void {
const float INV_CELL = 1.0f / REPULSION_RANGE;
const int n = masses.size();
if (last_build >= REPULSION_GRID_REFRESH ||
masses.size() != last_masses_count ||
springs.size() != last_springs_count) {
BuildGrid();
last_build = 0;
last_masses_count = masses.size();
last_springs_count = springs.size();
}
last_build++;
#pragma omp parallel for
for (int i = 0; i < n; ++i) {
Mass *mass = massVec[indices[i]];
Mass *mass = mass_vec[indices[i]];
int cx = (int)std::floor(mass->position.x * INV_CELL);
int cy = (int)std::floor(mass->position.y * INV_CELL);
int cz = (int)std::floor(mass->position.z * INV_CELL);
@ -174,11 +191,11 @@ auto MassSpringSystem::CalculateRepulsionForces() -> void {
(int64_t)((cz + dz) & 0xFFFFF);
// Binary search for this neighbor cell in sorted array
auto lo = std::lower_bound(cellIDs.begin(), cellIDs.end(), nid);
auto hi = std::upper_bound(cellIDs.begin(), cellIDs.end(), nid);
auto lo = std::lower_bound(cell_ids.begin(), cell_ids.end(), nid);
auto hi = std::upper_bound(cell_ids.begin(), cell_ids.end(), nid);
for (auto it = lo; it != hi; ++it) {
Mass *m = massVec[indices[it - cellIDs.begin()]];
Mass *m = mass_vec[indices[it - cell_ids.begin()]];
if (m == mass) {
continue;
}