summaryrefslogtreecommitdiffstats
path: root/src/collision
diff options
context:
space:
mode:
Diffstat (limited to 'src/collision')
-rw-r--r--src/collision/ColBox.h12
-rw-r--r--src/collision/ColModel.cpp19
-rw-r--r--src/collision/ColModel.h12
-rw-r--r--src/collision/ColSphere.cpp16
-rw-r--r--src/collision/ColSphere.h12
-rw-r--r--src/collision/ColStore.cpp236
-rw-r--r--src/collision/ColStore.h43
-rw-r--r--src/collision/ColTriangle.cpp9
-rw-r--r--src/collision/ColTriangle.h11
-rw-r--r--src/collision/Collision.cpp397
-rw-r--r--src/collision/Collision.h20
-rw-r--r--src/collision/TempColModels.cpp9
-rw-r--r--src/collision/TempColModels.h1
13 files changed, 483 insertions, 314 deletions
diff --git a/src/collision/ColBox.h b/src/collision/ColBox.h
index ac2cd675..0df55925 100644
--- a/src/collision/ColBox.h
+++ b/src/collision/ColBox.h
@@ -2,15 +2,21 @@
#include "SurfaceTable.h"
-struct CColBox
+struct CBox
{
CVector min;
CVector max;
+ CVector GetSize(void) { return max - min; }
+ void Set(const CVector &min, const CVector &max) { this->min = min; this->max = max; }
+};
+
+struct CColBox : public CBox
+{
uint8 surface;
uint8 piece;
- void Set(const CVector &min, const CVector &max, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
- CVector GetSize(void) { return max - min; }
+ void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);
+ using CBox::Set;
CColBox& operator=(const CColBox &other);
}; \ No newline at end of file
diff --git a/src/collision/ColModel.cpp b/src/collision/ColModel.cpp
index fb90e7dd..d2e01f50 100644
--- a/src/collision/ColModel.cpp
+++ b/src/collision/ColModel.cpp
@@ -1,7 +1,9 @@
#include "common.h"
#include "ColModel.h"
+#include "Collision.h"
#include "Game.h"
#include "MemoryHeap.h"
+#include "Pools.h"
CColModel::CColModel(void)
{
@@ -15,7 +17,7 @@ CColModel::CColModel(void)
vertices = nil;
triangles = nil;
trianglePlanes = nil;
- level = CGame::currLevel;
+ level = LEVEL_GENERIC; // generic col slot
ownsCollisionVolumes = true;
}
@@ -25,6 +27,20 @@ CColModel::~CColModel(void)
RemoveTrianglePlanes();
}
+void*
+CColModel::operator new(size_t)
+{
+ CColModel* node = CPools::GetColModelPool()->New();
+ assert(node);
+ return node;
+}
+
+void
+CColModel::operator delete(void *p, size_t)
+{
+ CPools::GetColModelPool()->Delete((CColModel*)p);
+}
+
void
CColModel::RemoveCollisionVolumes(void)
{
@@ -34,6 +50,7 @@ CColModel::RemoveCollisionVolumes(void)
RwFree(boxes);
RwFree(vertices);
RwFree(triangles);
+ CCollision::RemoveTrianglePlanes(this);
}
numSpheres = 0;
numLines = 0;
diff --git a/src/collision/ColModel.h b/src/collision/ColModel.h
index 7dcdfa4d..cd5ae651 100644
--- a/src/collision/ColModel.h
+++ b/src/collision/ColModel.h
@@ -9,14 +9,14 @@
struct CColModel
{
- CColSphere boundingSphere;
- CColBox boundingBox;
+ CSphere boundingSphere;
+ CBox boundingBox;
int16 numSpheres;
- int16 numLines;
int16 numBoxes;
int16 numTriangles;
- int32 level;
- bool ownsCollisionVolumes; // missing on PS2
+ int8 numLines;
+ uint8 level; // colstore slot but probably still named level
+ bool ownsCollisionVolumes;
CColSphere *spheres;
CColLine *lines;
CColBox *boxes;
@@ -33,5 +33,7 @@ struct CColModel
void SetLinkPtr(CLink<CColModel*>*);
void GetTrianglePoint(CVector &v, int i) const;
+ void *operator new(size_t);
+ void operator delete(void *p, size_t);
CColModel& operator=(const CColModel& other);
}; \ No newline at end of file
diff --git a/src/collision/ColSphere.cpp b/src/collision/ColSphere.cpp
index 9aac01e0..65f02860 100644
--- a/src/collision/ColSphere.cpp
+++ b/src/collision/ColSphere.cpp
@@ -1,5 +1,6 @@
#include "common.h"
#include "ColSphere.h"
+#include "General.h"
void
CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
@@ -8,4 +9,19 @@ CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
this->center = center;
this->surface = surf;
this->piece = piece;
+}
+
+bool
+CColSphere::IntersectRay(CVector const& from, CVector const& dir, CVector &entry, CVector &exit)
+{
+ CVector distToCenter = from - center;
+ float distToTouchSqr = distToCenter.MagnitudeSqr() - sq(radius);
+ float root1, root2;
+
+ if (!CGeneral::SolveQuadratic(1.0f, DotProduct(distToCenter, dir) * 2.f, distToTouchSqr, root1, root2))
+ return false;
+
+ entry = from + dir * root1;
+ exit = from + dir * root2;
+ return true;
} \ No newline at end of file
diff --git a/src/collision/ColSphere.h b/src/collision/ColSphere.h
index 70e29763..f86b282a 100644
--- a/src/collision/ColSphere.h
+++ b/src/collision/ColSphere.h
@@ -2,12 +2,20 @@
#include "SurfaceTable.h"
-struct CColSphere
+struct CSphere
{
// NB: this has to be compatible with a CVuVector
CVector center;
float radius;
+ void Set(float radius, const CVector &center) { this->center = center; this->radius = radius; }
+};
+
+struct CColSphere : public CSphere
+{
uint8 surface;
uint8 piece;
- void Set(float radius, const CVector &center, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
+
+ void Set(float radius, const CVector &center, uint8 surf, uint8 piece);
+ bool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit);
+ using CSphere::Set;
}; \ No newline at end of file
diff --git a/src/collision/ColStore.cpp b/src/collision/ColStore.cpp
new file mode 100644
index 00000000..192c373d
--- /dev/null
+++ b/src/collision/ColStore.cpp
@@ -0,0 +1,236 @@
+#include "common.h"
+
+#include "templates.h"
+#include "General.h"
+#include "ModelInfo.h"
+#include "Streaming.h"
+#include "FileLoader.h"
+#include "Script.h"
+#include "Timer.h"
+#include "Camera.h"
+#include "Frontend.h"
+#include "Physical.h"
+#include "ColStore.h"
+
+CPool<ColDef,ColDef> *CColStore::ms_pColPool;
+
+void
+CColStore::Initialise(void)
+{
+ if(ms_pColPool == nil)
+ ms_pColPool = new CPool<ColDef,ColDef>(COLSTORESIZE, "CollisionFiles");
+ AddColSlot("generic"); // slot 0. not streamed
+}
+
+void
+CColStore::Shutdown(void)
+{
+ int i;
+ for(i = 0; i < COLSTORESIZE; i++)
+ RemoveColSlot(i);
+ if(ms_pColPool)
+ delete ms_pColPool;
+ ms_pColPool = nil;
+}
+
+int
+CColStore::AddColSlot(const char *name)
+{
+ ColDef *def = ms_pColPool->New();
+ assert(def);
+ def->isLoaded = false;
+ def->unused = 0;
+ def->bounds.left = 1000000.0f;
+ def->bounds.top = 1000000.0f;
+ def->bounds.right = -1000000.0f;
+ def->bounds.bottom = -1000000.0f;
+ def->minIndex = INT16_MAX;
+ def->maxIndex = INT16_MIN;
+ strcpy(def->name, name);
+ return ms_pColPool->GetJustIndex(def);
+}
+
+void
+CColStore::RemoveColSlot(int slot)
+{
+ if(GetSlot(slot)){
+ if(GetSlot(slot)->isLoaded)
+ RemoveCol(slot);
+ ms_pColPool->Delete(GetSlot(slot));
+ }
+}
+
+int
+CColStore::FindColSlot(const char *name)
+{
+ ColDef *def;
+ int size = ms_pColPool->GetSize();
+ for(int i = 0; i < size; i++){
+ def = GetSlot(i);
+ if(def && !CGeneral::faststricmp(def->name, name))
+ return i;
+ }
+ return -1;
+}
+
+char*
+CColStore::GetColName(int32 slot)
+{
+ return GetSlot(slot)->name;
+}
+
+CRect&
+CColStore::GetBoundingBox(int32 slot)
+{
+ return GetSlot(slot)->bounds;
+}
+
+void
+CColStore::IncludeModelIndex(int32 slot, int32 modelIndex)
+{
+ ColDef *def = GetSlot(slot);
+ if(modelIndex < def->minIndex)
+ def->minIndex = modelIndex;
+ if(modelIndex > def->maxIndex)
+ def->maxIndex = modelIndex;
+}
+
+bool
+CColStore::LoadCol(int32 slot, uint8 *buffer, int32 bufsize)
+{
+ bool success;
+ ColDef *def = GetSlot(slot);
+ if(def->minIndex > def->maxIndex)
+ success = CFileLoader::LoadCollisionFileFirstTime(buffer, bufsize, slot);
+ else
+ success = CFileLoader::LoadCollisionFile(buffer, bufsize, slot);
+ if(success)
+ def->isLoaded = true;
+ else
+ debug("Failed to load Collision\n");
+ return success;
+}
+
+void
+CColStore::RemoveCol(int32 slot)
+{
+ int id;
+ GetSlot(slot)->isLoaded = false;
+ for(id = 0; id < MODELINFOSIZE; id++){
+ CBaseModelInfo *mi = CModelInfo::GetModelInfo(id);
+ if(mi){
+ CColModel *col = mi->GetColModel();
+ if(col && col->level == slot)
+ col->RemoveCollisionVolumes();
+ }
+ }
+}
+
+void
+CColStore::LoadAllCollision(void)
+{
+ int i;
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i))
+ CStreaming::RequestCol(i, 0);
+
+ CStreaming::LoadAllRequestedModels(false);
+}
+
+void
+CColStore::RemoveAllCollision(void)
+{
+ int i;
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i))
+ if(CStreaming::CanRemoveCol(i))
+ CStreaming::RemoveCol(i);
+}
+
+static bool bLoadAtSecondPosition;
+static CVector2D secondPosition;
+
+void
+CColStore::AddCollisionNeededAtPosn(const CVector2D &pos)
+{
+ bLoadAtSecondPosition = true;
+ secondPosition = pos;
+}
+
+void
+CColStore::LoadCollision(const CVector2D &pos)
+{
+ int i;
+
+ if(CStreaming::ms_disableStreaming)
+ return;
+
+ for(i = 1; i < COLSTORESIZE; i++){
+ if(GetSlot(i) == nil)
+ continue;
+
+ bool wantThisOne = false;
+
+ if(GetBoundingBox(i).IsPointInside(pos) ||
+ bLoadAtSecondPosition && GetBoundingBox(i).IsPointInside(secondPosition, -119.0f) ||
+ strcmp(GetColName(i), "yacht") == 0){
+ wantThisOne = true;
+ }else{
+ for (int j = 0; j < MAX_CLEANUP; j++) {
+ CPhysical* pEntity = CTheScripts::MissionCleanup.DoesThisEntityWaitForCollision(j);
+ if (pEntity && !pEntity->bDontLoadCollision && !pEntity->bIsFrozen) {
+ if (GetBoundingBox(i).IsPointInside(pEntity->GetPosition(), -80.0f))
+ wantThisOne = true;
+ }
+ }
+ }
+
+ if(wantThisOne)
+ CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);
+ else
+ CStreaming::RemoveCol(i);
+ }
+ bLoadAtSecondPosition = false;
+}
+
+void
+CColStore::RequestCollision(const CVector2D &pos)
+{
+ int i;
+
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f))
+ CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);
+}
+
+void
+CColStore::EnsureCollisionIsInMemory(const CVector2D &pos)
+{
+ int i;
+
+ if(CStreaming::ms_disableStreaming)
+ return;
+
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -110.0f) &&
+ !CStreaming::HasColLoaded(i)){
+ CStreaming::RequestCol(i, 0);
+ if(TheCamera.GetScreenFadeStatus() == FADE_0)
+ FrontEndMenuManager.MessageScreen("LOADCOL", false);
+ CTimer::Suspend();
+ CStreaming::LoadAllRequestedModels(false);
+ CTimer::Resume();
+ }
+}
+
+bool
+CColStore::HasCollisionLoaded(const CVector2D &pos)
+{
+ int i;
+
+ for(i = 1; i < COLSTORESIZE; i++)
+ if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f) &&
+ !GetSlot(i)->isLoaded)
+ return false;
+ return true;
+}
diff --git a/src/collision/ColStore.h b/src/collision/ColStore.h
new file mode 100644
index 00000000..8e2a3a70
--- /dev/null
+++ b/src/collision/ColStore.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "templates.h"
+
+struct ColDef { // made up name
+ int32 unused;
+ bool isLoaded;
+ CRect bounds;
+ char name[20];
+ int16 minIndex;
+ int16 maxIndex;
+};
+
+class CColStore
+{
+ static CPool<ColDef,ColDef> *ms_pColPool;
+
+public:
+ static void Initialise(void);
+ static void Shutdown(void);
+ static int AddColSlot(const char *name);
+ static void RemoveColSlot(int32 slot);
+ static int FindColSlot(const char *name);
+ static char *GetColName(int32 slot);
+ static CRect &GetBoundingBox(int32 slot);
+ static void IncludeModelIndex(int32 slot, int32 modelIndex);
+ static bool LoadCol(int32 storeID, uint8 *buffer, int32 bufsize);
+ static void RemoveCol(int32 slot);
+ static void AddCollisionNeededAtPosn(const CVector2D &pos);
+ static void LoadAllCollision(void);
+ static void RemoveAllCollision(void);
+ static void LoadCollision(const CVector2D &pos);
+ static void RequestCollision(const CVector2D &pos);
+ static void EnsureCollisionIsInMemory(const CVector2D &pos);
+ static bool HasCollisionLoaded(const CVector2D &pos);
+
+ static ColDef *GetSlot(int slot) {
+ assert(slot >= 0);
+ assert(ms_pColPool);
+ assert(slot < ms_pColPool->GetSize());
+ return ms_pColPool->GetSlot(slot);
+ }
+};
diff --git a/src/collision/ColTriangle.cpp b/src/collision/ColTriangle.cpp
index 9120fcff..843fb93f 100644
--- a/src/collision/ColTriangle.cpp
+++ b/src/collision/ColTriangle.cpp
@@ -1,15 +1,6 @@
#include "common.h"
#include "ColTriangle.h"
-void
-CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
-{
- this->a = a;
- this->b = b;
- this->c = c;
- this->surface = surf;
-}
-
#ifdef VU_COLLISION
void
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
diff --git a/src/collision/ColTriangle.h b/src/collision/ColTriangle.h
index 9e918e38..a2580c58 100644
--- a/src/collision/ColTriangle.h
+++ b/src/collision/ColTriangle.h
@@ -18,7 +18,13 @@ struct CColTriangle
uint16 c;
uint8 surface;
- void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
+ void Set(int a, int b, int c, uint8 surf)
+ {
+ this->a = a;
+ this->b = b;
+ this->c = c;
+ this->surface = surf;
+ }
};
struct CColTrianglePlane
@@ -63,6 +69,9 @@ struct CColTrianglePlane
void Set(const CVector &va, const CVector &vb, const CVector &vc);
void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
void GetNormal(CVector &n) const { n = normal; }
+ float GetNormalX() const { return normal.x; }
+ float GetNormalY() const { return normal.y; }
+ float GetNormalZ() const { return normal.z; }
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
#endif
}; \ No newline at end of file
diff --git a/src/collision/Collision.cpp b/src/collision/Collision.cpp
index 7fb5c30b..c90390c4 100644
--- a/src/collision/Collision.cpp
+++ b/src/collision/Collision.cpp
@@ -21,7 +21,10 @@
#include "SurfaceTable.h"
#include "Lines.h"
#include "Collision.h"
-#include "Frontend.h"
+#include "Camera.h"
+#include "ColStore.h"
+
+//--MIAMI: file done
#ifdef VU_COLLISION
#include "VuCollision.h"
@@ -75,52 +78,22 @@ CCollision::Init(void)
{
ms_colModelCache.Init(NUMCOLCACHELINKS);
ms_collisionInMemory = LEVEL_GENERIC;
+ CColStore::Initialise();
}
void
CCollision::Shutdown(void)
{
ms_colModelCache.Shutdown();
+ CColStore::Shutdown();
}
void
CCollision::Update(void)
{
- CVector playerCoors;
- playerCoors = FindPlayerCoors();
- eLevelName level = CTheZones::m_CurrLevel;
- bool forceLevelChange = false;
-
- if(CTimer::GetTimeInMilliseconds() < 2000 || CCutsceneMgr::IsCutsceneProcessing())
- return;
-
- // hardcode a level if there are no zones
- if(level == LEVEL_GENERIC){
- if(CGame::currLevel == LEVEL_INDUSTRIAL &&
- playerCoors.x < 400.0f){
- level = LEVEL_COMMERCIAL;
- forceLevelChange = true;
- }else if(CGame::currLevel == LEVEL_SUBURBAN &&
- playerCoors.x > -450.0f && playerCoors.y < -1400.0f){
- level = LEVEL_COMMERCIAL;
- forceLevelChange = true;
- }else{
- if(playerCoors.x > 800.0f){
- level = LEVEL_INDUSTRIAL;
- forceLevelChange = true;
- }else if(playerCoors.x < -800.0f){
- level = LEVEL_SUBURBAN;
- forceLevelChange = true;
- }
- }
- }
- if(level != LEVEL_GENERIC && level != CGame::currLevel)
- CGame::currLevel = level;
- if(ms_collisionInMemory != CGame::currLevel)
- LoadCollisionWhenINeedIt(forceLevelChange);
- CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
}
+//--MIAMI: unused
eLevelName
GetCollisionInSectorList(CPtrList &list)
{
@@ -137,6 +110,7 @@ GetCollisionInSectorList(CPtrList &list)
return LEVEL_GENERIC;
}
+//--MIAMI: unused
// Get a level this sector is in based on collision models
eLevelName
GetCollisionInSector(CSector &sect)
@@ -160,155 +134,13 @@ GetCollisionInSector(CSector &sect)
void
CCollision::LoadCollisionWhenINeedIt(bool forceChange)
{
- eLevelName level, l;
- bool multipleLevels;
- CVector playerCoors;
- CVehicle *veh;
- CEntryInfoNode *ei;
- int sx, sy;
- int xmin, xmax, ymin, ymax;
- int x, y;
-
- level = LEVEL_GENERIC;
-
- playerCoors = FindPlayerCoors();
- sx = CWorld::GetSectorIndexX(playerCoors.x);
- sy = CWorld::GetSectorIndexY(playerCoors.y);
- multipleLevels = false;
-
- veh = FindPlayerVehicle();
- if(veh && veh->IsTrain()){
- if(((CTrain*)veh)->m_nDoorState != TRAIN_DOOR_OPEN)
- return;
- }else if(playerCoors.z < -4.0f && !CCullZones::DoINeedToLoadCollision())
- return;
-
- // Figure out whose level's collisions we're most likely to be interested in
- if(!forceChange){
- if(veh && veh->IsBoat()){
- // on water we expect to be between levels
- multipleLevels = true;
- }else{
- xmin = Max(sx - 1, 0);
- xmax = Min(sx + 1, NUMSECTORS_X-1);
- ymin = Max(sy - 1, 0);
- ymax = Min(sy + 1, NUMSECTORS_Y-1);
-
- for(x = xmin; x <= xmax; x++)
- for(y = ymin; y <= ymax; y++){
- l = GetCollisionInSector(*CWorld::GetSector(x, y));
- if(l != LEVEL_GENERIC){
- if(level == LEVEL_GENERIC)
- level = l;
- if(level != l)
- multipleLevels = true;
- }
- }
- }
-
- if(multipleLevels && veh && veh->IsBoat())
- for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){
- level = GetCollisionInSector(*ei->sector);
- if(level != LEVEL_GENERIC)
- break;
- }
- }
-
- if (level == CGame::currLevel || forceChange) {
-#ifdef FIX_BUGS
- CTimer::Suspend();
-#else
- CTimer::Stop();
-#endif
- ISLAND_LOADING_IS(LOW)
- {
- DMAudio.SetEffectsFadeVol(0);
- CPad::StopPadsShaking();
- LoadCollisionScreen(CGame::currLevel);
- DMAudio.Service();
- }
-
- CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false);
-
- ISLAND_LOADING_ISNT(HIGH)
- {
- CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
- CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
- CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
- }
- ISLAND_LOADING_IS(LOW)
- {
- CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
- CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
- CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
- CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
- CStreaming::RemoveUnusedModelsInLoadedList();
- CGame::TidyUpMemory(true, true);
- CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
- }
-
- ms_collisionInMemory = CGame::currLevel;
- CReplay::EmptyReplayBuffer();
- ISLAND_LOADING_IS(LOW)
- {
- if (CGame::currLevel != LEVEL_GENERIC)
- LoadSplash(GetLevelSplashScreen(CGame::currLevel));
- CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
- CStreaming::RemoveUnusedBuildings(CGame::currLevel);
- CStreaming::RequestBigBuildings(CGame::currLevel);
- }
-#ifdef NO_ISLAND_LOADING
- else if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM)
- CStreaming::RequestIslands(CGame::currLevel);
-#endif
- CStreaming::LoadAllRequestedModels(true);
-
- ISLAND_LOADING_IS(LOW)
- {
- CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
-
- CGame::TidyUpMemory(true, true);
- }
-#ifdef FIX_BUGS
- CTimer::Resume();
-#else
- CTimer::Update();
-#endif
- ISLAND_LOADING_IS(LOW)
- DMAudio.SetEffectsFadeVol(127);
- }
}
-#ifdef NO_ISLAND_LOADING
-bool CCollision::bAlreadyLoaded = false;
-#endif
void
CCollision::SortOutCollisionAfterLoad(void)
{
- if(ms_collisionInMemory == CGame::currLevel)
- return;
- ISLAND_LOADING_IS(LOW)
- CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
-
- if (CGame::currLevel != LEVEL_GENERIC) {
-#ifdef NO_ISLAND_LOADING
- if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) {
- if (bAlreadyLoaded) {
- ms_collisionInMemory = CGame::currLevel;
- return;
- }
- bAlreadyLoaded = true;
- CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
- CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
- CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
- } else
-#endif
- CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
- if(!CGame::playingIntro)
- LoadSplash(GetLevelSplashScreen(CGame::currLevel));
- }
- ms_collisionInMemory = CGame::currLevel;
- CGame::TidyUpMemory(true, false);
+ CColStore::LoadCollision(TheCamera.GetPosition());
+ CStreaming::LoadAllRequestedModels(false);
}
void
@@ -332,14 +164,14 @@ CCollision::LoadCollisionScreen(eLevelName level)
bool
-CCollision::TestSphereSphere(const CColSphere &s1, const CColSphere &s2)
+CCollision::TestSphereSphere(const CSphere &s1, const CSphere &s2)
{
float d = s1.radius + s2.radius;
return (s1.center - s2.center).MagnitudeSqr() < d*d;
}
bool
-CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box)
+CCollision::TestSphereBox(const CSphere &sph, const CBox &box)
{
if(sph.center.x + sph.radius < box.min.x) return false;
if(sph.center.x - sph.radius > box.max.x) return false;
@@ -351,7 +183,7 @@ CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box)
}
bool
-CCollision::TestLineBox(const CColLine &line, const CColBox &box)
+CCollision::TestLineBox(const CColLine &line, const CBox &box)
{
float t, x, y, z;
// If either line point is in the box, we have a collision
@@ -436,7 +268,7 @@ CCollision::TestLineBox(const CColLine &line, const CColBox &box)
}
bool
-CCollision::TestVerticalLineBox(const CColLine &line, const CColBox &box)
+CCollision::TestVerticalLineBox(const CColLine &line, const CBox &box)
{
if(line.p0.x <= box.min.x) return false;
if(line.p0.y <= box.min.y) return false;
@@ -628,6 +460,8 @@ CCollision::TestSphereTriangle(const CColSphere &sphere,
int testcase = insideAB + insideAC + insideBC;
float dist = 0.0f;
switch(testcase){
+ case 0:
+ return false; // shouldn't happen
case 1:
// closest to a vertex
if(insideAB) dist = (sphere.center - vc).Magnitude();
@@ -656,7 +490,7 @@ CCollision::TestSphereTriangle(const CColSphere &sphere,
}
bool
-CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough)
+CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough)
{
#ifdef VU_COLLISION
CMatrix matTransform;
@@ -737,12 +571,14 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
for(i = 0; i < model.numSpheres; i++){
if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;
if(TestLineSphere(newline, model.spheres[i]))
return true;
}
for(i = 0; i < model.numBoxes; i++){
if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue;
if(TestLineBox(newline, model.boxes[i]))
return true;
}
@@ -750,6 +586,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
CalculateTrianglePlanes(&model);
for(i = 0; i < model.numTriangles; i++){
if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;
if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i]))
return true;
}
@@ -758,6 +595,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
#endif
}
+// TODO: TestPillWithSpheresInColModel, but only called from overloaded CWeapon::FireMelee which isn't used
//
// Process
@@ -1038,6 +876,7 @@ CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CC
return true;
}
+//--MIAMI: unused
bool
CCollision::ProcessVerticalLineTriangle(const CColLine &line,
const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
@@ -1254,7 +1093,7 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol
bool
CCollision::ProcessLineTriangle(const CColLine &line,
const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
- CColPoint &point, float &mindist)
+ CColPoint &point, float &mindist, CStoredCollPoly *poly)
{
#ifdef VU_COLLISION
// not used in favour of optimized loops
@@ -1349,6 +1188,12 @@ CCollision::ProcessLineTriangle(const CColLine &line,
point.pieceA = 0;
point.surfaceB = tri.surface;
point.pieceB = 0;
+ if(poly){
+ poly->verts[0] = va;
+ poly->verts[1] = vb;
+ poly->verts[2] = vc;
+ poly->valid = true;
+ }
mindist = t;
return true;
#endif
@@ -1419,6 +1264,8 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
float dist = 0.0f;
CVector p;
switch(testcase){
+ case 0:
+ return false; // shouldn't happen
case 1:
// closest to a vertex
if(insideAB) p = vc;
@@ -1465,7 +1312,7 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
bool
CCollision::ProcessLineOfSight(const CColLine &line,
const CMatrix &matrix, CColModel &model,
- CColPoint &point, float &mindist, bool ignoreSeeThrough)
+ CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough)
{
#ifdef VU_COLLISION
CMatrix matTransform;
@@ -1569,17 +1416,20 @@ CCollision::ProcessLineOfSight(const CColLine &line,
float coldist = mindist;
for(i = 0; i < model.numSpheres; i++){
if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;
ProcessLineSphere(newline, model.spheres[i], point, coldist);
}
for(i = 0; i < model.numBoxes; i++){
if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue;
ProcessLineBox(newline, model.boxes[i], point, coldist);
}
CalculateTrianglePlanes(&model);
for(i = 0; i < model.numTriangles; i++){
if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;
ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist);
}
@@ -1596,7 +1446,7 @@ CCollision::ProcessLineOfSight(const CColLine &line,
bool
CCollision::ProcessVerticalLine(const CColLine &line,
const CMatrix &matrix, CColModel &model,
- CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly)
+ CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly)
{
#ifdef VU_COLLISION
static CStoredCollPoly TempStoredPoly;
@@ -1723,28 +1573,27 @@ CCollision::ProcessVerticalLine(const CColLine &line,
// transform line to model space
// Why does the game seem to do this differently than above?
CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));
- newline.p1.x = newline.p0.x;
- newline.p1.y = newline.p0.y;
- if(!TestVerticalLineBox(newline, model.boundingBox))
+ if(!TestLineBox(newline, model.boundingBox))
return false;
+ // BUG? is IsSeeThroughVertical really the right thing? also not checking shoot through
float coldist = mindist;
for(i = 0; i < model.numSpheres; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(ignoreSeeThrough && IsSeeThroughVertical(model.spheres[i].surface)) continue;
ProcessLineSphere(newline, model.spheres[i], point, coldist);
}
for(i = 0; i < model.numBoxes; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(ignoreSeeThrough && IsSeeThroughVertical(model.boxes[i].surface)) continue;
ProcessLineBox(newline, model.boxes[i], point, coldist);
}
CalculateTrianglePlanes(&model);
TempStoredPoly.valid = false;
for(i = 0; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
- ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly);
+ if(ignoreSeeThrough && IsSeeThroughVertical(model.triangles[i].surface)) continue;
+ ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly);
}
if(coldist < mindist){
@@ -2302,6 +2151,15 @@ CCollision::CalculateTrianglePlanes(CColModel *model)
}
void
+CCollision::RemoveTrianglePlanes(CColModel *model)
+{
+ if(model->trianglePlanes){
+ ms_colModelCache.Remove(model->GetLinkPtr());
+ model->RemoveTrianglePlanes();
+ }
+}
+
+void
CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel)
{
int i;
@@ -2523,15 +2381,75 @@ CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel)
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
}
+static void
+GetSurfaceColor(uint8 surf, uint8 &r, uint8 &g, uint8 &b)
+{
+ // game doesn't do this
+ r = 255;
+ g = 128;
+ b = 0;
+
+ switch(CSurfaceTable::GetAdhesionGroup(surf)){
+ case ADHESIVE_RUBBER:
+ r = 255;
+ g = 0;
+ b = 0;
+ break;
+ case ADHESIVE_HARD:
+ r = 255;
+ g = 255;
+ b = 128;
+ break;
+ case ADHESIVE_ROAD:
+ r = 128;
+ g = 128;
+ b = 128;
+ break;
+ case ADHESIVE_LOOSE:
+ r = 0;
+ g = 255;
+ b = 0;
+ break;
+ case ADHESIVE_SAND:
+ r = 255;
+ g = 128;
+ b = 128;
+ break;
+ case ADHESIVE_WET:
+ r = 0;
+ g = 0;
+ b = 255;
+ break;
+ }
+
+ if(surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH){
+ r = 255;
+ g = 255;
+ b = 0;
+ }
+
+ float f = (surf & 0xF)/32.0f + 0.5f;
+ r *= f;
+ g *= f;
+ b *= f;
+
+ if(surf == SURFACE_TRANSPARENT_CLOTH || surf == SURFACE_METAL_CHAIN_FENCE ||
+ surf == SURFACE_TRANSPARENT_STONE || surf == SURFACE_SCAFFOLD_POLE)
+ if(CTimer::GetFrameCounter() & 1){
+ r = 0;
+ g = 0;
+ b = 0;
+ }
+}
+
void
CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id)
{
int i;
int s;
- float f;
CVector verts[8];
CVector min, max;
- int r, g, b;
+ uint8 r, g, b;
RwImVertexIndex *iptr;
RwIm3DVertex *vptr;
@@ -2550,53 +2468,8 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel,
verts[1] = mat * verts[1];
verts[2] = mat * verts[2];
- // game doesn't do this
- r = 255;
- g = 128;
- b = 0;
-
s = colModel.triangles[i].surface;
- f = (s & 0xF)/32.0f + 0.5f;
- switch(CSurfaceTable::GetAdhesionGroup(s)){
- case ADHESIVE_RUBBER:
- r = f * 255.0f;
- g = 0;
- b = 0;
- break;
- case ADHESIVE_HARD:
- r = f*255.0f;
- g = f*255.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_ROAD:
- r = f*128.0f;
- g = f*128.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_LOOSE:
- r = 0;
- g = f * 255.0f;
- b = 0;
- break;
- case ADHESIVE_WET:
- r = 0;
- g = 0;
- b = f * 255.0f;
- break;
- default:
- // this doesn't make much sense
- r *= f;
- g *= f;
- b *= f;
- }
-
- if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE ||
- s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE)
- if(CTimer::GetFrameCounter() & 1){
- r = 0;
- g = 0;
- b = 0;
- }
+ GetSurfaceColor(s, r, g, b);
if(s > SURFACE_METAL_GATE){
r = CGeneral::GetRandomNumber();
@@ -2637,47 +2510,7 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel,
verts[7] = mat * CVector(max.x, max.y, max.z);
s = colModel.boxes[i].surface;
- f = (s & 0xF)/32.0f + 0.5f;
- switch(CSurfaceTable::GetAdhesionGroup(s)){
- case ADHESIVE_RUBBER:
- r = f * 255.0f;
- g = 0;
- b = 0;
- break;
- case ADHESIVE_HARD:
- r = f*255.0f;
- g = f*255.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_ROAD:
- r = f*128.0f;
- g = f*128.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_LOOSE:
- r = 0;
- g = f * 255.0f;
- b = 0;
- break;
- case ADHESIVE_WET:
- r = 0;
- g = 0;
- b = f * 255.0f;
- break;
- default:
- // this doesn't make much sense
- r *= f;
- g *= f;
- b *= f;
- }
-
- if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE ||
- s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE)
- if(CTimer::GetFrameCounter() & 1){
- r = 0;
- g = 0;
- b = 0;
- }
+ GetSurfaceColor(s, r, g, b);
RenderBuffer::StartStoring(36, 8, &iptr, &vptr);
RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255);
diff --git a/src/collision/Collision.h b/src/collision/Collision.h
index f4270bc5..57f5f86e 100644
--- a/src/collision/Collision.h
+++ b/src/collision/Collision.h
@@ -28,9 +28,6 @@ class CCollision
public:
static eLevelName ms_collisionInMemory;
static CLinkList<CColModel*> ms_colModelCache;
-#ifdef NO_ISLAND_LOADING
- static bool bAlreadyLoaded;
-#endif
static void Init(void);
static void Shutdown(void);
@@ -42,26 +39,27 @@ public:
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
static void CalculateTrianglePlanes(CColModel *model);
+ static void RemoveTrianglePlanes(CColModel *model);
// all these return true if there's a collision
- static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2);
- static bool TestSphereBox(const CColSphere &sph, const CColBox &box);
- static bool TestLineBox(const CColLine &line, const CColBox &box);
- static bool TestVerticalLineBox(const CColLine &line, const CColBox &box);
+ static bool TestSphereSphere(const CSphere &s1, const CSphere &s2);
+ static bool TestSphereBox(const CSphere &sph, const CBox &box);
+ static bool TestLineBox(const CColLine &line, const CBox &box);
+ static bool TestVerticalLineBox(const CColLine &line, const CBox &box);
static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
- static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough);
+ static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough);
static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);
static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
- static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist);
+ static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly = nil);
static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
- static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough);
- static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly);
+ static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough);
+ static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly);
static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
diff --git a/src/collision/TempColModels.cpp b/src/collision/TempColModels.cpp
index dabb6ebb..f8b26450 100644
--- a/src/collision/TempColModels.cpp
+++ b/src/collision/TempColModels.cpp
@@ -15,6 +15,7 @@ CColModel CTempColModels::ms_colModelPedGroundHit;
CColModel CTempColModels::ms_colModelBoot1;
CColModel CTempColModels::ms_colModelDoor1;
CColModel CTempColModels::ms_colModelBonnet1;
+CColModel CTempColModels::ms_colModelWeapon;
CColSphere s_aPedSpheres[3];
@@ -292,5 +293,13 @@ CTempColModels::Initialise(void)
SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2);
+ ms_colModelWeapon.boundingSphere.radius = 0.25f;
+ ms_colModelWeapon.boundingBox.min.x = -0.25f;
+ ms_colModelWeapon.boundingBox.min.y = -0.25f;
+ ms_colModelWeapon.boundingBox.min.z = -0.25f;
+ ms_colModelWeapon.boundingBox.max.x = 0.25f;
+ ms_colModelWeapon.boundingBox.max.y = 0.25f;
+ ms_colModelWeapon.boundingBox.max.z = 0.25f;
+
#undef SET_COLMODEL_SPHERES
}
diff --git a/src/collision/TempColModels.h b/src/collision/TempColModels.h
index 3e1dd5e1..0c936d6f 100644
--- a/src/collision/TempColModels.h
+++ b/src/collision/TempColModels.h
@@ -18,6 +18,7 @@ public:
static CColModel ms_colModelBoot1;
static CColModel ms_colModelDoor1;
static CColModel ms_colModelBonnet1;
+ static CColModel ms_colModelWeapon;
static void Initialise(void);
};