Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Use vector instead of forward_list for dpGrid for ~50% physics loop speed improvement #1447

Merged
merged 4 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dPhysics/dpEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void dpEntity::CheckCollision(dpEntity* other) {
return;
}

bool wasFound = (m_CurrentlyCollidingObjects.find(other->GetObjectID()) != m_CurrentlyCollidingObjects.end());
bool wasFound = m_CurrentlyCollidingObjects.contains(other->GetObjectID());

bool isColliding = m_CollisionShape->IsColliding(other->GetShape());

Expand Down
80 changes: 38 additions & 42 deletions dPhysics/dpGrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,14 @@
CELL_SIZE = cellSize;
m_DeleteGrid = true;

//fill x
for (int i = 0; i < NUM_CELLS; i++) {
m_Cells.push_back(std::vector<std::forward_list<dpEntity*>>());
}

//fill z
for (int i = 0; i < NUM_CELLS; i++) {
for (int i = 0; i < NUM_CELLS; i++) {
m_Cells[i].push_back(std::forward_list<dpEntity*>());
}
}
m_Cells.resize(NUM_CELLS, std::vector<std::vector<dpEntity*>>(NUM_CELLS));
}

dpGrid::~dpGrid() {
if (!this->m_DeleteGrid) return;
for (auto& x : m_Cells) { //x
for (auto& y : x) { //y
for (auto en : y) {
for (auto& z : x) { //y
for (auto en : z) {
if (!en) continue;
delete en;
en = nullptr;
Expand All @@ -39,13 +29,12 @@
int cellX = (int)std::round(entity->m_Position.x) / dpGrid::CELL_SIZE + NUM_CELLS / 2;
int cellZ = (int)std::round(entity->m_Position.z) / dpGrid::CELL_SIZE + NUM_CELLS / 2;

if (cellX < 0) cellX = 0;
if (cellZ < 0) cellZ = 0;
if (cellX >= NUM_CELLS) cellX = NUM_CELLS - 1;
if (cellZ >= NUM_CELLS) cellZ = NUM_CELLS - 1;
// Clamp values to the range [0, NUM_CELLS - 1]
std::clamp(cellX, 0, NUM_CELLS - 1);

Check failure on line 33 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]
std::clamp(cellZ, 0, NUM_CELLS - 1);

Check failure on line 34 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]

//Add to cell:
m_Cells[cellX][cellZ].push_front(entity);
m_Cells[cellX][cellZ].push_back(entity);

//To verify that the object isn't gargantuan:
if (entity->GetScale() >= CELL_SIZE * 2 || entity->GetIsGargantuan())
Expand All @@ -59,39 +48,46 @@
int cellX = (int)std::round(x) / dpGrid::CELL_SIZE + NUM_CELLS / 2;
int cellZ = (int)std::round(z) / dpGrid::CELL_SIZE + NUM_CELLS / 2;

if (cellX < 0) cellX = 0;
if (cellZ < 0) cellZ = 0;
if (cellX >= NUM_CELLS) cellX = NUM_CELLS - 1;
if (cellZ >= NUM_CELLS) cellZ = NUM_CELLS - 1;
// Clamp values to the range [0, NUM_CELLS - 1]
std::clamp(cellX, 0, NUM_CELLS - 1);

Check failure on line 52 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]
std::clamp(cellZ, 0, NUM_CELLS - 1);

Check failure on line 53 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]

if (oldCellX < 0) oldCellX = 0;
if (oldCellZ < 0) oldCellZ = 0;
if (oldCellX >= NUM_CELLS) oldCellX = NUM_CELLS - 1;
if (oldCellZ >= NUM_CELLS) oldCellZ = NUM_CELLS - 1;
std::clamp(oldCellX, 0, NUM_CELLS - 1);

Check failure on line 55 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]
std::clamp(oldCellZ, 0, NUM_CELLS - 1);

Check failure on line 56 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]

if (oldCellX == cellX && oldCellZ == cellZ) return;

//Remove from perv cell:
m_Cells[oldCellX][oldCellZ].remove(entity);
//Remove from prev cell:
auto& cell = m_Cells[oldCellX][oldCellZ];

// For speed, find the single match and swap it with the last element, then pop_back.
auto toRemove = std::find(cell.begin(), cell.end(), entity);
if (toRemove != cell.end()) {
*toRemove = cell.back();
cell.pop_back();
}

//Add to the new cell
m_Cells[cellX][cellZ].push_front(entity);
m_Cells[cellX][cellZ].push_back(entity);
}

void dpGrid::Delete(dpEntity* entity) {
if (!entity) return;
int oldCellX = (int)std::round(entity->m_Position.x) / dpGrid::CELL_SIZE + NUM_CELLS / 2;
int oldCellZ = (int)std::round(entity->m_Position.z) / dpGrid::CELL_SIZE + NUM_CELLS / 2;

if (oldCellX < 0) oldCellX = 0;
if (oldCellZ < 0) oldCellZ = 0;
if (oldCellX >= NUM_CELLS) oldCellX = NUM_CELLS - 1;
if (oldCellZ >= NUM_CELLS) oldCellZ = NUM_CELLS - 1;
// Clamp values to the range [0, NUM_CELLS - 1]
std::clamp(oldCellX, 0, NUM_CELLS - 1);

Check failure on line 80 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]
std::clamp(oldCellZ, 0, NUM_CELLS - 1);

Check failure on line 81 in dPhysics/dpGrid.cpp

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13)

ignoring return value of function declared with 'nodiscard' attribute [-Werror,-Wunused-result]

m_Cells[oldCellX][oldCellZ].remove(entity);
auto& cell = m_Cells[oldCellX][oldCellZ];
auto toRemove = std::find(cell.begin(), cell.end(), entity);
if (toRemove != cell.end()) {
*toRemove = cell.back();
cell.pop_back();
}

if (m_GargantuanObjects.find(entity->m_ObjectID) != m_GargantuanObjects.end())
m_GargantuanObjects.erase(entity->m_ObjectID);
m_GargantuanObjects.erase(entity->m_ObjectID);

if (entity) delete entity;
entity = nullptr;
Expand All @@ -100,8 +96,8 @@
void dpGrid::Update(float deltaTime) {
//Pre-update:
for (auto& x : m_Cells) { //x
for (auto& y : x) { //y
for (auto en : y) {
for (auto& z : x) { //y
for (auto en : z) {
if (!en) continue;
en->PreUpdate();
}
Expand All @@ -110,8 +106,8 @@

//Actual collision detection update:
for (int x = 0; x < NUM_CELLS; x++) {
for (int y = 0; y < NUM_CELLS; y++) {
HandleCell(x, y, deltaTime);
for (int z = 0; z < NUM_CELLS; z++) {
HandleCell(x, z, deltaTime);
}
}
}
Expand Down Expand Up @@ -157,7 +153,7 @@
HandleEntity(en, other);
}

for (auto other : m_GargantuanObjects)
HandleEntity(en, other.second);
for (auto& [id, entity] : m_GargantuanObjects)
HandleEntity(en, entity);
}
}
10 changes: 5 additions & 5 deletions dPhysics/dpGrid.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#pragma once
#include <vector>
#include <list>
#include <forward_list>
#include <map>
#include <vector>

#include "dCommonVars.h"

class dpEntity;
Expand Down Expand Up @@ -30,15 +29,16 @@ class dpGrid {
*/
void SetDeleteGrid(bool value) { this->m_DeleteGrid = value; };

std::vector<std::vector<std::forward_list<dpEntity*>>> GetCells() { return this->m_Cells; };
// Intentional copy since this is only used when we delete this class to re-create it.
std::vector<std::vector<std::vector<dpEntity*>>> GetCells() { return this->m_Cells; };

private:
void HandleEntity(dpEntity* entity, dpEntity* other);
void HandleCell(int x, int z, float deltaTime);

private:
//cells on X, cells on Y for that X, then another vector that contains the entities within that cell.
std::vector<std::vector<std::forward_list<dpEntity*>>> m_Cells;
std::vector<std::vector<std::vector<dpEntity*>>> m_Cells;
std::map<LWOOBJID, dpEntity*> m_GargantuanObjects;
bool m_DeleteGrid = true;
};
Loading