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 all commits
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 @@ dpGrid::dpGrid(int numCells, int cellSize) {
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 @@ void dpGrid::Add(dpEntity* entity) {
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]
cellX = std::clamp(cellX, 0, NUM_CELLS - 1);
cellZ = std::clamp(cellZ, 0, NUM_CELLS - 1);

//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 @@ void dpGrid::Move(dpEntity* entity, float x, float z) {
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]
cellX = std::clamp(cellX, 0, NUM_CELLS - 1);
cellZ = std::clamp(cellZ, 0, NUM_CELLS - 1);

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;
oldCellX = std::clamp(oldCellX, 0, NUM_CELLS - 1);
oldCellZ = std::clamp(oldCellZ, 0, NUM_CELLS - 1);

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]
oldCellX = std::clamp(oldCellX, 0, NUM_CELLS - 1);
oldCellZ = std::clamp(oldCellZ, 0, NUM_CELLS - 1);

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::Delete(dpEntity* entity) {
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 @@ void dpGrid::Update(float deltaTime) {

//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 @@ void dpGrid::HandleCell(int x, int z, float deltaTime) {
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