2021-12-05 17:54:36 +00:00
|
|
|
#include "dpWorld.h"
|
|
|
|
#include "dpEntity.h"
|
|
|
|
#include "dpGrid.h"
|
|
|
|
#include "DetourCommon.h"
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "Game.h"
|
2023-10-21 23:31:55 +00:00
|
|
|
#include "Logger.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
#include "dConfig.h"
|
|
|
|
|
2024-01-19 21:12:05 +00:00
|
|
|
#include "dNavMesh.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
dpGrid* m_Grid = nullptr;
|
|
|
|
dNavMesh* m_NavMesh = nullptr;
|
|
|
|
int32_t phys_sp_tilesize = 205;
|
|
|
|
int32_t phys_sp_tilecount = 12;
|
|
|
|
|
|
|
|
uint32_t m_ZoneID = 0;
|
|
|
|
|
|
|
|
std::vector<dpEntity*> m_StaticEntities;
|
|
|
|
std::vector<dpEntity*> m_DynamicEntites;
|
|
|
|
bool phys_spatial_partitioning = true;
|
|
|
|
};
|
|
|
|
|
2022-12-04 22:25:58 +00:00
|
|
|
void dpWorld::Initialize(unsigned int zoneID, bool generateNewNavMesh) {
|
2024-01-05 00:21:03 +00:00
|
|
|
const auto physSpTilecount = Game::config->GetValue("phys_sp_tilecount");
|
2024-02-10 11:05:25 +00:00
|
|
|
if (!physSpTilecount.empty()) {
|
|
|
|
phys_sp_tilecount = GeneralUtils::TryParse<int32_t>(physSpTilecount).value_or(phys_sp_tilecount);
|
|
|
|
}
|
|
|
|
|
2024-01-05 00:21:03 +00:00
|
|
|
const auto physSpTilesize = Game::config->GetValue("phys_sp_tilesize");
|
2024-02-10 11:05:25 +00:00
|
|
|
if (!physSpTilesize.empty()) {
|
|
|
|
phys_sp_tilesize = GeneralUtils::TryParse<int32_t>(physSpTilesize).value_or(phys_sp_tilesize);
|
|
|
|
}
|
|
|
|
|
2024-01-05 00:21:03 +00:00
|
|
|
const auto physSpatialPartitioning = Game::config->GetValue("phys_spatial_partitioning");
|
|
|
|
if (!physSpatialPartitioning.empty()) phys_spatial_partitioning = physSpatialPartitioning == "1";
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-07-25 02:26:51 +00:00
|
|
|
//If spatial partitioning is enabled, then we need to create the m_Grid.
|
2021-12-05 17:54:36 +00:00
|
|
|
//if m_Grid exists, then the old method will be used.
|
|
|
|
//SP will NOT be used unless it is added to ShouldUseSP();
|
2024-01-05 00:21:03 +00:00
|
|
|
if (ShouldUseSP(zoneID)) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Grid = new dpGrid(phys_sp_tilecount, phys_sp_tilesize);
|
|
|
|
}
|
|
|
|
|
2022-12-04 22:25:58 +00:00
|
|
|
if (generateNewNavMesh) m_NavMesh = new dNavMesh(zoneID);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-10-21 23:31:55 +00:00
|
|
|
LOG("Physics world initialized!");
|
2022-12-04 22:25:58 +00:00
|
|
|
m_ZoneID = zoneID;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dpWorld::Reload() {
|
|
|
|
if (m_Grid) {
|
|
|
|
m_Grid->SetDeleteGrid(false);
|
|
|
|
auto oldGridCells = m_Grid->GetCells();
|
|
|
|
delete m_Grid;
|
|
|
|
m_Grid = nullptr;
|
|
|
|
|
|
|
|
Initialize(m_ZoneID, false);
|
|
|
|
for (auto column : oldGridCells) {
|
|
|
|
for (auto row : column) {
|
|
|
|
for (auto entity : row) {
|
|
|
|
AddEntity(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-21 23:31:55 +00:00
|
|
|
LOG("Successfully reloaded physics world!");
|
2022-12-04 22:25:58 +00:00
|
|
|
} else {
|
2023-10-21 23:31:55 +00:00
|
|
|
LOG("No physics world to reload!");
|
2022-12-04 22:25:58 +00:00
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2024-01-19 21:12:05 +00:00
|
|
|
void dpWorld::Shutdown() {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Grid) {
|
2022-12-04 22:25:58 +00:00
|
|
|
// Triple check this is true
|
|
|
|
m_Grid->SetDeleteGrid(true);
|
2021-12-05 17:54:36 +00:00
|
|
|
delete m_Grid;
|
|
|
|
m_Grid = nullptr;
|
|
|
|
}
|
|
|
|
|
2022-08-04 13:54:14 +00:00
|
|
|
if (m_NavMesh) {
|
|
|
|
delete m_NavMesh;
|
|
|
|
m_NavMesh = nullptr;
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2024-01-19 21:12:05 +00:00
|
|
|
bool dpWorld::IsLoaded() {
|
2024-02-06 14:53:51 +00:00
|
|
|
return m_NavMesh->IsNavmeshLoaded();
|
2024-01-19 21:12:05 +00:00
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
void dpWorld::StepWorld(float deltaTime) {
|
2022-07-25 02:26:51 +00:00
|
|
|
if (m_Grid) {
|
|
|
|
m_Grid->Update(deltaTime);
|
|
|
|
return;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Pre update:
|
|
|
|
for (auto entity : m_StaticEntities) {
|
|
|
|
if (!entity || entity->GetSleeping()) continue;
|
|
|
|
entity->PreUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
//Do actual update:
|
|
|
|
for (auto entity : m_DynamicEntites) {
|
|
|
|
if (!entity || entity->GetSleeping()) continue;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
entity->Update(deltaTime);
|
|
|
|
|
|
|
|
for (auto other : m_StaticEntities) {
|
|
|
|
if (!other || other->GetSleeping() || entity->GetObjectID() == other->GetObjectID()) continue;
|
|
|
|
|
|
|
|
other->CheckCollision(entity); //swap "other" and "entity" if you want dyn objs to handle collisions.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-19 21:12:05 +00:00
|
|
|
dNavMesh* dpWorld::GetNavMesh() {
|
|
|
|
return m_NavMesh;
|
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
void dpWorld::AddEntity(dpEntity* entity) {
|
|
|
|
if (m_Grid) entity->SetGrid(m_Grid); //This sorts this entity into the right cell
|
|
|
|
else { //old method, slow
|
|
|
|
if (entity->GetIsStatic()) m_StaticEntities.push_back(entity);
|
|
|
|
else m_DynamicEntites.push_back(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void dpWorld::RemoveEntity(dpEntity* entity) {
|
|
|
|
if (!entity) return;
|
|
|
|
|
|
|
|
if (m_Grid) {
|
|
|
|
m_Grid->Delete(entity);
|
|
|
|
} else {
|
|
|
|
if (entity->GetIsStatic()) {
|
|
|
|
for (size_t i = 0; i < m_StaticEntities.size(); ++i) {
|
|
|
|
if (m_StaticEntities[i] == entity) {
|
|
|
|
delete m_StaticEntities[i];
|
|
|
|
m_StaticEntities[i] = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (size_t i = 0; i < m_DynamicEntites.size(); ++i) {
|
|
|
|
if (m_DynamicEntites[i] == entity) {
|
|
|
|
delete m_DynamicEntites[i];
|
|
|
|
m_DynamicEntites[i] = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-19 21:12:05 +00:00
|
|
|
bool dpWorld::ShouldUseSP(uint32_t zoneID) {
|
2024-01-05 00:21:03 +00:00
|
|
|
if (!phys_spatial_partitioning) return false;
|
|
|
|
|
2022-08-02 05:30:19 +00:00
|
|
|
// TODO: Add to this list as needed.
|
|
|
|
// Only large maps should be added as tiling likely makes little difference on small maps.
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
switch (zoneID) {
|
2022-12-04 22:25:58 +00:00
|
|
|
case 1100: // Avant Gardens
|
|
|
|
case 1200: // Nimbus Station
|
|
|
|
case 1300: // Gnarled Forest
|
|
|
|
case 1400: // Forbidden Valley
|
|
|
|
case 1800: // Crux Prime
|
|
|
|
case 1900: // Nexus Tower
|
|
|
|
case 2000: // Ninjago
|
|
|
|
return true;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|