summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/ZoneCull.cpp247
-rw-r--r--src/core/ZoneCull.h48
2 files changed, 272 insertions, 23 deletions
diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp
index 6b04c213..4d272fb4 100644
--- a/src/core/ZoneCull.cpp
+++ b/src/core/ZoneCull.cpp
@@ -9,14 +9,15 @@
#include "World.h"
#include "FileMgr.h"
#include "ZoneCull.h"
+#include "Zones.h"
int32 &CCullZones::NumCullZones = *(int*)0x8F2564;
-CCullZone *CCullZones::aZones = (CCullZone*)0x864750; // [NUMCULLZONES];
+CCullZone(&CCullZones::aZones)[NUMCULLZONES] = *(CCullZone(*)[NUMCULLZONES])*(uintptr*)0x864750;
int32 &CCullZones::NumAttributeZones = *(int*)0x8E29D0;
-CAttributeZone *CCullZones::aAttributeZones = (CAttributeZone*)0x709C60; // [NUMATTRIBZONES];
-uint16 *CCullZones::aIndices = (uint16*)0x847330; // [NUMZONEINDICES];
-int16 *CCullZones::aPointersToBigBuildingsForBuildings = (int16*)0x86C9D0; // [NUMBUILDINGS];
-int16 *CCullZones::aPointersToBigBuildingsForTreadables = (int16*)0x8F1B8C; // [NUMTREADABLES];
+CAttributeZone (&CCullZones::aAttributeZones)[NUMATTRIBZONES] = *(CAttributeZone(*)[NUMATTRIBZONES])*(uintptr*)0x709C60;
+uint16 (&CCullZones::aIndices)[NUMZONEINDICES] = *(uint16(*)[NUMZONEINDICES])*(uintptr*)0x847330;
+int16 (&CCullZones::aPointersToBigBuildingsForBuildings)[NUMBUILDINGS] = *(int16(*)[NUMBUILDINGS])*(uintptr*)0x86C9D0;
+int16 (&CCullZones::aPointersToBigBuildingsForTreadables)[NUMTREADABLES] = *(int16(*)[NUMTREADABLES])*(uintptr*)0x8F1B8C;
int32 &CCullZones::CurrentWantedLevelDrop_Player = *(int32*)0x880DA8;
int32 &CCullZones::CurrentFlags_Camera = *(int32*)0x940718;
@@ -47,6 +48,30 @@ CCullZones::Init(void)
aPointersToBigBuildingsForTreadables[i] = -1;
}
+bool CCullZone::TestLine(CVector vec1, CVector vec2)
+{
+ CColPoint colPoint;
+ CEntity *entity;
+
+ if (CWorld::ProcessLineOfSight(vec1, vec2, colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x + 0.05f, vec1.y, vec1.z), CVector(vec2.x + 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x - 0.05f, vec1.y, vec1.z), CVector(vec2.x - 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y + 0.05f, vec1.z), CVector(vec2.x, vec2.y + 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y - 0.05f, vec1.z), CVector(vec2.x, vec2.y - 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z + 0.05f), CVector(vec2.x, vec2.y, vec2.z + 0.05f), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ return CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z - 0.05f), CVector(vec2.x, vec2.y, vec2.z - 0.05f), colPoint, entity, true, false, false, false, false, true, false);
+}
+
+
+uint16* pTempArrayIndices;
+int TempEntityIndicesUsed;
+
void
CCullZones::ResolveVisibilities(void)
{
@@ -55,16 +80,135 @@ CCullZones::ResolveVisibilities(void)
CFileMgr::SetDir("");
fd = CFileMgr::OpenFile("DATA\\cullzone.dat", "rb");
if(fd > 0){
- CFileMgr::Read(fd, (char*)&NumCullZones, 4);
- CFileMgr::Read(fd, (char*)aZones, NUMCULLZONES*sizeof(CCullZone));
- CFileMgr::Read(fd, (char*)&NumAttributeZones, 4);
- CFileMgr::Read(fd, (char*)aAttributeZones, NUMATTRIBZONES*sizeof(CAttributeZone));
- CFileMgr::Read(fd, (char*)aIndices, NUMZONEINDICES*2);
- CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForBuildings, NUMBUILDINGS*2);
- CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, NUMTREADABLES*2);
+ CFileMgr::Read(fd, (char*)&NumCullZones, sizeof(NumCullZones));
+ CFileMgr::Read(fd, (char*)aZones, sizeof(aZones));
+ CFileMgr::Read(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones));
+ CFileMgr::Read(fd, (char*)aAttributeZones, sizeof(aAttributeZones));
+ CFileMgr::Read(fd, (char*)aIndices, sizeof(aIndices));
+ CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
+ CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
CFileMgr::CloseFile(fd);
}else{
// TODO: implement code from mobile to generate data here
+ EntityIndicesUsed = 0;
+ BuildListForBigBuildings();
+ pTempArrayIndices = new uint16[140000];
+ TempEntityIndicesUsed = 0;
+
+ for (int i = 0; i < NumCullZones; i++) {
+ DoVisibilityTestCullZone(i, true);
+ }
+
+ CompressIndicesArray();
+ delete[] pTempArrayIndices;
+
+ fd = CFileMgr::OpenFileForWriting("data\\cullzone.dat");
+ if (fd != 0) {
+ CFileMgr::Write(fd, (char*)&NumCullZones, sizeof(NumCullZones));
+ CFileMgr::Write(fd, (char*)aZones, sizeof(aZones));
+ CFileMgr::Write(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones));
+ CFileMgr::Write(fd, (char*)&aAttributeZones, sizeof(aAttributeZones));
+ CFileMgr::Write(fd, (char*)&aIndices, sizeof(aIndices));
+ CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
+ CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
+ CFileMgr::CloseFile(fd);
+ }
+ }
+}
+
+void
+CCullZones::BuildListForBigBuildings()
+{
+ for (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) {
+ CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
+ if (building == nil || !building->bIsBIGBuilding) continue;
+ CSimpleModelInfo *nonlod = (CSimpleModelInfo*)((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->m_atomics[2];
+ if (nonlod == nil) continue;
+
+ for (int j = i; j >= 0; j--) {
+ CBuilding *building2 = CPools::GetBuildingPool()->GetSlot(j);
+ if (building2 == nil || building2->bIsBIGBuilding) continue;
+ if (CModelInfo::GetModelInfo(building2->GetModelIndex()) == nonlod) {
+ if ((building2->GetPosition() - building->GetPosition()).Magnitude() < 5.0f) {
+ aPointersToBigBuildingsForBuildings[j] = i;
+ }
+ }
+ }
+
+ for (int j = CPools::GetTreadablePool()->GetSize()-1; j >= 0; j--) {
+ CTreadable *treadable = CPools::GetTreadablePool()->GetSlot(j);
+ if (treadable == nil || treadable->bIsBIGBuilding) continue;
+ if (CModelInfo::GetModelInfo(treadable->GetModelIndex()) == nonlod) {
+ if ((treadable->GetPosition() - building->GetPosition()).Magnitude() < 5.0f) {
+ aPointersToBigBuildingsForTreadables[j] = i;
+ }
+ }
+ }
+ }
+}
+
+void
+CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
+{
+ aZones[zoneId].m_groupIndexCount[0] = 0;
+ aZones[zoneId].m_groupIndexCount[1] = 0;
+ aZones[zoneId].m_groupIndexCount[2] = 0;
+ aZones[zoneId].m_indexStart = TempEntityIndicesUsed;
+ aZones[zoneId].FindTestPoints();
+
+ if (!doIt) return;
+
+ for (int i = CPools::GetBuildingPool()->GetSize() - 1; i >= 0; i--) {
+ CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
+ if (building != nil && !building->bIsBIGBuilding && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForBuildings[i] != -1)) {
+ CBuilding *building2 = nil;
+ if (aPointersToBigBuildingsForBuildings[i] != -1)
+ building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]);
+
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
+ pTempArrayIndices[TempEntityIndicesUsed++] = i;
+ aZones[zoneId].m_groupIndexCount[0]++;
+ }
+ }
+ }
+
+ for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
+ CTreadable* building = CPools::GetTreadablePool()->GetSlot(i);
+ if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) {
+ CTreadable* building2 = nil;
+ if (aPointersToBigBuildingsForTreadables[i] != -1)
+ building2 = CPools::GetTreadablePool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
+
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, building2)) {
+ pTempArrayIndices[TempEntityIndicesUsed++] = i;
+ aZones[zoneId].m_groupIndexCount[1]++;
+ }
+ }
+ }
+
+ for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
+ CTreadable *building = CPools::GetTreadablePool()->GetSlot(i);
+ if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < 40000.0f) {
+ int start = aZones[zoneId].m_groupIndexCount[0] + aZones[zoneId].m_indexStart;
+ int end = aZones[zoneId].m_groupIndexCount[1] + start;
+
+ bool alreadyAdded = false;
+
+ for (int k = start; k < end; k++) {
+ if (aIndices[k] == i)
+ alreadyAdded = true;
+ }
+
+ if (!alreadyAdded) {
+ CBuilding *building2 = nil;
+ if (aPointersToBigBuildingsForTreadables[i] != -1)
+ building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
+ pTempArrayIndices[TempEntityIndicesUsed++] = i;
+ aZones[zoneId].m_groupIndexCount[2]++;
+ }
+ }
+ }
}
}
@@ -221,9 +365,9 @@ CCullZones::AddCullZone(CVector const &position,
cull->maxy = maxy;
cull->minz = minz;
cull->maxz = maxz;
- cull->unk2 = 0;
- cull->unk3 = 0;
- cull->unk4 = 0;
+ cull->m_groupIndexCount[0] = 0;
+ cull->m_groupIndexCount[1] = 0;
+ cull->m_groupIndexCount[2] = 0;
cull->m_indexStart = 0;
}
if(flag & ~ATTRZONE_NOTCULLZONE){
@@ -357,6 +501,79 @@ CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
}
}
+float
+CCullZone::CalcDistToCullZoneSquared(float x, float y)
+{
+ float rx, ry;
+ float temp;
+
+ temp = minx;
+ if (temp <= x) {
+ temp = maxx;
+ if (x <= temp)
+ rx = 0.0f;
+ else
+ rx = sq(x - temp);
+ } else
+ rx = sq(x - temp);
+
+ temp = miny;
+ if (temp <= y) {
+ temp = maxy;
+ if (y <= temp)
+ ry = 0.0f;
+ else
+ ry = sq(y - temp);
+ } else
+ ry = sq(y - temp);
+
+ return rx + ry;
+}
+
+bool
+CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
+{
+ CVector &pos = entity->GetPosition();
+
+ CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex());
+ float distToZone = CalcDistToCullZone(pos.x, pos.y);
+ float lodDist;
+ if (minfo->m_isSubway)
+ lodDist = minfo->GetLargestLodDistance() + 30.0f;
+ else
+ lodDist = minfo->GetLargestLodDistance() + 50.0f;
+
+ if (lodDist > distToZone) return true;
+ if (!checkLevel) return false;
+ return CTheZones::GetLevelFromPosition(pos) == CTheZones::GetLevelFromPosition(CVector(minx, miny, minz));
+}
+
+bool
+CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set)
+{
+ int32 curCount;
+ int32 start;
+ int32 size;
+
+ for (int i = 0; i < NumCullZones; i++) {
+ curCount = 0;
+ for (int group = 0; group < 3; group++) {
+ aZones[i].GetGroupStartAndSize(group, start, size);
+
+ int unk = 0; // TODO: figure out
+ for (int j = 0; j < size; j++) {
+ for (int k = 0; k < 3; k++) {
+ if (set[k] == pTempArrayIndices[start+j])
+ unk++;
+ }
+ }
+ if (unk == 3 && ++curCount >= count)
+ return true;
+ }
+ }
+ return false;
+}
+
STARTPATCHES
InjectHook(0x524BC0, &CCullZones::Init, PATCH_JUMP);
InjectHook(0x524EC0, &CCullZones::ResolveVisibilities, PATCH_JUMP);
diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h
index 5b04b4f9..74625563 100644
--- a/src/core/ZoneCull.h
+++ b/src/core/ZoneCull.h
@@ -1,3 +1,5 @@
+class CEntity;
+
class CCullZone
{
public:
@@ -11,9 +13,7 @@ public:
// TODO: figure these out:
int32 m_indexStart;
- int16 unk2;
- int16 unk3;
- int16 unk4;
+ int16 m_groupIndexCount[3];
int16 m_numBuildings;
int16 m_numTreadablesPlus10m;
int16 m_numTreadables;
@@ -25,6 +25,32 @@ public:
static void DoStuffEnteringZone_OneBuilding(uint16 i);
static void DoStuffEnteringZone_OneTreadablePlus10m(uint16 i);
static void DoStuffEnteringZone_OneTreadable(uint16 i);
+
+
+ static bool TestLine(CVector a1, CVector a2);
+ float CalcDistToCullZoneSquared(float x, float y);
+ float CalcDistToCullZone(float x, float y) { return Sqrt(CalcDistToCullZoneSquared(x, y)); };
+ bool IsEntityCloseEnoughToZone(CEntity* entity, bool checkLevel);
+
+ void GetGroupStartAndSize(int32 groupid, int32 &start, int32 &size) {
+ switch (groupid) {
+ case 1:
+ start = m_groupIndexCount[0] + m_indexStart;
+ size = m_groupIndexCount[1];
+ break;
+ case 2:
+ start = m_groupIndexCount[0] + m_groupIndexCount[1] + m_indexStart;
+ size = m_groupIndexCount[2];
+ break;
+ default:
+ start = m_indexStart;
+ size = m_groupIndexCount[0];
+ break;
+ }
+ }
+
+ void FindTestPoints() {}; // todo
+ bool TestEntityVisibilityFromCullZone(CEntity*, float, CEntity*) { return false; }; // todo
};
enum eZoneAttribs
@@ -55,12 +81,12 @@ class CCullZones
{
public:
static int32 &NumCullZones;
- static CCullZone *aZones; // [NUMCULLZONES];
+ static CCullZone (&aZones)[NUMCULLZONES];
static int32 &NumAttributeZones;
- static CAttributeZone *aAttributeZones; // [NUMATTRIBZONES];
- static uint16 *aIndices; // [NUMZONEINDICES];
- static int16 *aPointersToBigBuildingsForBuildings; // [NUMBUILDINGS];
- static int16 *aPointersToBigBuildingsForTreadables; // [NUMTREADABLES];
+ static CAttributeZone(&aAttributeZones)[NUMATTRIBZONES];
+ static uint16 (&aIndices)[NUMZONEINDICES];
+ static int16 (&aPointersToBigBuildingsForBuildings)[NUMBUILDINGS];
+ static int16 (&aPointersToBigBuildingsForTreadables)[NUMTREADABLES];
static int32 &CurrentWantedLevelDrop_Player;
static int32 &CurrentFlags_Camera;
@@ -91,4 +117,10 @@ public:
static bool PlayerNoRain(void) { return (CurrentFlags_Player & ATTRZONE_NORAIN) != 0; }
static bool CamNoRain(void) { return (CurrentFlags_Camera & ATTRZONE_NORAIN) != 0; }
static int32 GetWantedLevelDrop(void) { return CurrentWantedLevelDrop_Player; }
+
+ static void BuildListForBigBuildings();
+ static void DoVisibilityTestCullZone(int zoneId, bool doIt);
+ static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set);
+
+ static void CompressIndicesArray() {};// todo
};