diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/ZoneCull.cpp | 247 | ||||
-rw-r--r-- | src/core/ZoneCull.h | 48 |
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 }; |