summaryrefslogtreecommitdiffstats
path: root/src/core/ZoneCull.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ZoneCull.cpp')
-rw-r--r--src/core/ZoneCull.cpp1479
1 files changed, 31 insertions, 1448 deletions
diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp
index 5a76e5ed..db3577ad 100644
--- a/src/core/ZoneCull.cpp
+++ b/src/core/ZoneCull.cpp
@@ -1,6 +1,5 @@
#include "common.h"
-#include "General.h"
#include "Building.h"
#include "Treadable.h"
#include "Train.h"
@@ -12,242 +11,23 @@
#include "ZoneCull.h"
#include "Zones.h"
-#include "Debug.h"
-#include "Renderer.h"
-
-int32 CCullZones::NumCullZones;
-CCullZone CCullZones::aZones[NUMCULLZONES];
int32 CCullZones::NumAttributeZones;
CAttributeZone CCullZones::aAttributeZones[NUMATTRIBZONES];
-uint16 CCullZones::aIndices[NUMZONEINDICES];
-int16 CCullZones::aPointersToBigBuildingsForBuildings[NUMBUILDINGS];
-int16 CCullZones::aPointersToBigBuildingsForTreadables[NUMTREADABLES];
int32 CCullZones::CurrentWantedLevelDrop_Player;
int32 CCullZones::CurrentFlags_Camera;
int32 CCullZones::CurrentFlags_Player;
-int32 CCullZones::OldCullZone;
-int32 CCullZones::EntityIndicesUsed;
bool CCullZones::bCurrentSubwayIsInvisible;
-bool CCullZones::bCullZonesDisabled;
-
-#define NUMUNCOMPRESSED (6000)
-#define NUMTEMPINDICES (140000)
+bool CCullZones::bAtBeachForAudio;
void
CCullZones::Init(void)
{
- int i;
-
NumAttributeZones = 0;
CurrentWantedLevelDrop_Player = 0;
CurrentFlags_Camera = 0;
CurrentFlags_Player = 0;
bCurrentSubwayIsInvisible = false;
- NumCullZones = 0;
- OldCullZone = -1;
- EntityIndicesUsed = 0;
-
- for(i = 0; i < NUMBUILDINGS; i++)
- aPointersToBigBuildingsForBuildings[i] = -1;
- for(i = 0; i < NUMTREADABLES; i++)
- aPointersToBigBuildingsForTreadables[i] = -1;
-}
-
-
-uint16* pTempArrayIndices;
-int TempEntityIndicesUsed;
-
-void
-CCullZones::ResolveVisibilities(void)
-{
- int fd;
-
- CFileMgr::SetDir("");
- fd = CFileMgr::OpenFile("DATA\\cullzone.dat", "rb");
- if(fd > 0){
- 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{
-#ifndef MASTER
- EntityIndicesUsed = 0;
- BuildListForBigBuildings();
- pTempArrayIndices = new uint16[NUMTEMPINDICES];
- TempEntityIndicesUsed = 0;
-
-// if(!LoadTempFile()) // not in final game
- {
- for (int i = 0; i < NumCullZones; i++) {
-//printf("testing zone %d (%d indices)\n", i, TempEntityIndicesUsed);
- DoVisibilityTestCullZone(i, true);
- }
-
-// SaveTempFile(); // not in final game
- }
-
- CompressIndicesArray();
- delete[] pTempArrayIndices;
- pTempArrayIndices = nil;
-
- 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);
- }
-#endif
- }
-}
-
-bool
-CCullZones::LoadTempFile(void)
-{
- int fd = CFileMgr::OpenFile("cullzone.tmp");
- if (fd != 0) {
- 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*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16));
- CFileMgr::Read(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed));
- CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
- CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
- CFileMgr::CloseFile(fd);
- return true;
- }
- return false;
-}
-
-void
-CCullZones::SaveTempFile(void)
-{
- int fd = CFileMgr::OpenFileForWriting("cullzone.tmp");
- 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*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16));
- CFileMgr::Write(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed));
- 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 *)CModelInfo::GetModelInfo(building->GetModelIndex()))->GetRelatedModel();
- if (nonlod == nil) continue;
-
- for (int j = CPools::GetBuildingPool()->GetSize()-1; 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 findIndices)
-{
- 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 (!findIndices) 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 *LODbuilding = nil;
- if (aPointersToBigBuildingsForBuildings[i] != -1)
- LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]);
-
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) {
- assert(TempEntityIndicesUsed < NUMTEMPINDICES);
- pTempArrayIndices[TempEntityIndicesUsed++] = i;
- aZones[zoneId].m_groupIndexCount[0]++;
- }
- }
- }
-
- for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
- CBuilding* building = CPools::GetTreadablePool()->GetSlot(i);
- if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) {
- CBuilding *LODbuilding = nil;
- if (aPointersToBigBuildingsForTreadables[i] != -1)
- LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
-
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, LODbuilding)) {
- assert(TempEntityIndicesUsed < NUMTEMPINDICES);
- pTempArrayIndices[TempEntityIndicesUsed++] = i;
- aZones[zoneId].m_groupIndexCount[1]++;
- }
- }
- }
-
- for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
- CBuilding *building = CPools::GetTreadablePool()->GetSlot(i);
- if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < SQR(200.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++) {
-#ifdef FIX_BUGS
- if (pTempArrayIndices[k] == i)
-#else
- if (aIndices[k] == i)
-#endif
- alreadyAdded = true;
- }
-
- if (!alreadyAdded) {
- CBuilding *LODbuilding = nil;
- if (aPointersToBigBuildingsForTreadables[i] != -1)
- LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) {
- assert(TempEntityIndicesUsed < NUMTEMPINDICES);
- pTempArrayIndices[TempEntityIndicesUsed++] = i;
- aZones[zoneId].m_groupIndexCount[2]++;
- }
- }
- }
- }
}
void
@@ -255,14 +35,10 @@ CCullZones::Update(void)
{
bool invisible;
- if(bCullZonesDisabled)
- return;
-
switch(CTimer::GetFrameCounter() & 7){
case 0:
case 4:
- /* Update Cull zone */
- ForceCullZoneCoors(TheCamera.GetGameCamPosition());
+ UpdateAtBeachForAudio();
break;
case 2:
@@ -283,31 +59,30 @@ CCullZones::Update(void)
}
}
-void
-CCullZones::ForceCullZoneCoors(CVector coors)
+// TODO? put somewhere else?
+bool
+IsPointWithinArbitraryArea(float px, float py, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
{
- int32 z;
- z = FindCullZoneForCoors(coors);
- if(z != OldCullZone){
- if(OldCullZone >= 0)
- aZones[OldCullZone].DoStuffLeavingZone();
- if(z >= 0)
- aZones[z].DoStuffEnteringZone();
- OldCullZone = z;
- }
+ if((px-x1)*(x2-x1) - (py-y1)*(y2-y1) < 0.0f) return false;
+ if((px-x2)*(x3-x2) - (py-y2)*(y3-y2) < 0.0f) return false;
+ if((px-x3)*(x4-x3) - (py-y3)*(y4-y3) < 0.0f) return false;
+ if((px-x4)*(x1-x4) - (py-y4)*(y1-y4) < 0.0f) return false;
+ return true;
}
-int32
-CCullZones::FindCullZoneForCoors(CVector coors)
+void
+CCullZones::UpdateAtBeachForAudio(void)
{
- int i;
+ bAtBeachForAudio = IsPointWithinArbitraryArea(TheCamera.GetPosition().x, TheCamera.GetPosition().y,
+ 400.0f, -1644.4f,
+ 751.9f, 1267.8f,
+ 971.9f, 1216.2f,
+ 840.0f, -1744.0f);
+}
- for(i = 0; i < NumCullZones; i++)
- if(coors.x >= aZones[i].minx && coors.x <= aZones[i].maxx &&
- coors.y >= aZones[i].miny && coors.y <= aZones[i].maxy &&
- coors.z >= aZones[i].minz && coors.z <= aZones[i].maxz)
- return i;
- return -1;
+void
+CCullZones::ForceCullZoneCoors(CVector coors)
+{
}
int32
@@ -382,1208 +157,16 @@ CCullZones::AddCullZone(CVector const &position,
float minz, float maxz,
uint16 flag, int16 wantedLevel)
{
- CCullZone *cull;
CAttributeZone *attrib;
- CVector v;
- if((flag & ATTRZONE_NOTCULLZONE) == 0){
- cull = &aZones[NumCullZones++];
- v = position;
- // reposition start point to the start/end of the
- // alley next to the big building in the industrial district.
- // probably isn't analyzed correctly otherwise?s
- if((v-CVector(1032.14f, -624.255f, 24.93f)).Magnitude() < 1.0f)
- v = CVector(1061.7f, -613.0f, 19.0f);
- if((v-CVector(1029.48f, -495.757f, 21.98f)).Magnitude() < 1.0f)
- v = CVector(1061.4f, -506.0f, 18.5f);
- cull->position.x = Clamp(v.x, minx, maxx);
- cull->position.y = Clamp(v.y, miny, maxy);
- cull->position.z = Clamp(v.z, minz, maxz);
- cull->minx = minx;
- cull->maxx = maxx;
- cull->miny = miny;
- cull->maxy = maxy;
- cull->minz = minz;
- cull->maxz = maxz;
- cull->m_groupIndexCount[0] = 0;
- cull->m_groupIndexCount[1] = 0;
- cull->m_groupIndexCount[2] = 0;
- cull->m_indexStart = 0;
- }
- if(flag & ~ATTRZONE_NOTCULLZONE){
- attrib = &aAttributeZones[NumAttributeZones++];
- attrib->minx = minx;
- attrib->maxx = maxx;
- attrib->miny = miny;
- attrib->maxy = maxy;
- attrib->minz = minz;
- attrib->maxz = maxz;
- attrib->attributes = flag;
- attrib->wantedLevel = wantedLevel;
- }
-}
-
-uint16 *pExtraArrayIndices;
-
-void
-CCullZones::CompressIndicesArray()
-{
- uint16 set[3];
-
- // These are used to hold the compressed groups in sets of 3
- int numExtraIndices = 0;
- pExtraArrayIndices = new uint16[NUMTEMPINDICES];
-
- for(int numOccurrences = 6; numOccurrences > 1; numOccurrences--){
- if(NumCullZones == 0)
- break;
-
-//printf("checking occurrences %d\n", numOccurrences);
- int attempt = 0;
- while(attempt < 10000){
- for(;;){
- attempt++;
-
- int zone = CGeneral::GetRandomNumber() % NumCullZones;
- int group = CGeneral::GetRandomNumber() % 3;
- if(!PickRandomSetForGroup(zone, group, set))
- break;
- if(!DoWeHaveMoreThanXOccurencesOfSet(numOccurrences, set))
- break;
-
- // add this set
- attempt = 1;
- int setId = numExtraIndices + NUMUNCOMPRESSED;
- pExtraArrayIndices[numExtraIndices++] = set[0];
- pExtraArrayIndices[numExtraIndices++] = set[1];
- pExtraArrayIndices[numExtraIndices++] = set[2];
- ReplaceSetForAllGroups(set, setId);
- }
- }
- }
-
- TidyUpAndMergeLists(pExtraArrayIndices, numExtraIndices);
-
- delete[] pExtraArrayIndices;
-}
-
-// Get three random indices for this group of a zone
-bool
-CCullZones::PickRandomSetForGroup(int32 zone, int32 group, uint16 *set)
-{
- int32 start;
- int32 size;
-
- aZones[zone].GetGroupStartAndSize(group, start, size);
- if(size <= 0)
- return false;
-
- int numIndices = 0;
- for(int i = 0; i < size; i++)
- if(pTempArrayIndices[start + i] != 0xFFFF)
- numIndices++;
- if(numIndices < 3)
- return false;
-
- int first = CGeneral::GetRandomNumber() % (numIndices-2);
-
- numIndices = 0;
- int n = 0;
- for(int i = 0; i < size; i++)
- if(pTempArrayIndices[start + i] != 0xFFFF){
- if(n++ < first) continue;
-
- set[numIndices++] = pTempArrayIndices[start + i];
- if(numIndices == 3)
- break;
- }
- return true;
-}
-
-bool
-CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set)
-{
- int32 curCount;
- int32 start;
- int32 size;
-
- curCount = 0;
- for (int i = 0; i < NumCullZones; i++) {
- for (int group = 0; group < 3; group++) {
- aZones[i].GetGroupStartAndSize(group, start, size);
- if(size <= 0) continue;
-
- // check if the set is a subset of the group
- int n = 0;
- for (int j = 0; j < size; j++) {
- for (int k = 0; k < 3; k++) {
- if (pTempArrayIndices[start+j] == set[k])
- n++;
- }
- }
- // yes it is
- if(n == 3){
- curCount++;
- // check if we have seen this set often enough
- if(curCount >= count)
- return true;
- }
- }
- }
- return false;
-}
-
-void
-CCullZones::ReplaceSetForAllGroups(uint16 *set, uint16 setid)
-{
- int32 start;
- int32 size;
-
- for(int i = 0; i < NumCullZones; i++)
- for(int group = 0; group < 3; group++){
- aZones[i].GetGroupStartAndSize(group, start, size);
- if(size <= 0) continue;
-
- // check if the set is a subset of the group
- int n = 0;
- for(int j = 0; j < size; j++){
- for(int k = 0; k < 3; k++){
- if(pTempArrayIndices[start+j] == set[k])
- n++;
- }
- }
-
- // yes it is, so replace it
- if(n == 3){
- bool insertedSet = false;
- for(int j = 0; j < size; j++){
- for(int k = 0; k < 3; k++){
- // replace first element by set, invalidate others
- if(pTempArrayIndices[start+j] == set[k]){
- if(!insertedSet)
- pTempArrayIndices[start+j] = setid;
- else
- pTempArrayIndices[start+j] = 0xFFFF;
- insertedSet = true;
- }
- }
- }
- }
- }
-}
-
-void
-CCullZones::TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices)
-{
- int numTempIndices = 0;
- for(int i = 0; i < TempEntityIndicesUsed; i++)
- if(pTempArrayIndices[i] != 0xFFFF)
- numTempIndices++;
-
- // Fix up zone ranges such that there are no holes
- for(int i = 0; i < NumCullZones; i++){
- int j;
- int start = 0;
- for(j = 0; j < aZones[i].m_indexStart; j++)
- if(pTempArrayIndices[j] != 0xFFFF)
- start++;
-
- aZones[i].m_indexStart = start;
- aZones[i].m_numBuildings = 0;
- aZones[i].m_numTreadablesPlus10m = 0;
- aZones[i].m_numTreadables = 0;
-
- for(int k = 0; k < aZones[i].m_groupIndexCount[0]; k++)
- if(pTempArrayIndices[j++] != 0xFFFF)
- aZones[i].m_numBuildings++;
- for(int k = 0; k < aZones[i].m_groupIndexCount[1]; k++)
- if(pTempArrayIndices[j++] != 0xFFFF)
- aZones[i].m_numTreadablesPlus10m++;
- for(int k = 0; k < aZones[i].m_groupIndexCount[2]; k++)
- if(pTempArrayIndices[j++] != 0xFFFF)
- aZones[i].m_numTreadables++;
- }
-
- // Now copy the actually used indices
- EntityIndicesUsed = 0;
- for(int i = 0; i < TempEntityIndicesUsed; i++)
- if(pTempArrayIndices[i] != 0xFFFF){
- assert(EntityIndicesUsed < NUMZONEINDICES);
- if(pTempArrayIndices[i] < NUMUNCOMPRESSED)
- aIndices[EntityIndicesUsed++] = pTempArrayIndices[i];
- else
- aIndices[EntityIndicesUsed++] = pTempArrayIndices[i] + numTempIndices;
- }
- for(int i = 0; i < numExtraIndices; i++)
- if(extraIndices[i] != 0xFFFF){
- assert(EntityIndicesUsed < NUMZONEINDICES);
- if(extraIndices[i] < NUMUNCOMPRESSED)
- aIndices[EntityIndicesUsed++] = extraIndices[i];
- else
- aIndices[EntityIndicesUsed++] = extraIndices[i] + numTempIndices;
- }
-}
-
-
-
-void
-CCullZone::DoStuffLeavingZone(void)
-{
- int i;
-
- for(i = 0; i < m_numBuildings; i++)
- DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
- for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables ; i++)
- DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[m_indexStart + i]);
-}
-
-void
-CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i)
-{
- int16 bb;
- int j;
-
-
- if(i < NUMUNCOMPRESSED){
- CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false;
- bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
- }else{
- i -= NUMUNCOMPRESSED;
- for(j = 0; j < 3; j++)
- DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < NUMUNCOMPRESSED){
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = false;
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = false;
- bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
- }else{
- i -= NUMUNCOMPRESSED;
- for(j = 0; j < 3; j++)
- DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffEnteringZone(void)
-{
- int i;
-
- for(i = 0; i < m_numBuildings; i++)
- DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
- for(; i < m_numBuildings + m_numTreadablesPlus10m; i++)
- DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[m_indexStart + i]);
- for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables; i++)
- DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[m_indexStart + i]);
-}
-
-void
-CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < NUMUNCOMPRESSED){
- CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true;
- bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
- }else{
- i -= NUMUNCOMPRESSED;
- for(j = 0; j < 3; j++)
- DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < NUMUNCOMPRESSED){
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = true;
- bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
- }else{
- i -= NUMUNCOMPRESSED;
- for(j = 0; j < 3; j++)
- DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[i+j]);
- }
-}
-
-void
-CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
-{
- int16 bb;
- int j;
-
- if(i < NUMUNCOMPRESSED){
- CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;
- bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
- if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
- }else{
- i -= NUMUNCOMPRESSED;
- for(j = 0; j < 3; j++)
- DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[i+j]);
- }
-}
-
-float
-CCullZone::CalcDistToCullZoneSquared(float x, float y)
-{
- float rx, ry;
-
- if (x < minx) rx = sq(x - minx);
- else if (x > maxx) rx = sq(x - maxx);
- else rx = 0.0f;
-
- if (y < miny) ry = sq(y - miny);
- else if (y > maxy) ry = sq(y - maxy);
- else ry = 0.0f;
-
- return rx + ry;
-}
-
-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);
-}
-
-bool
-CCullZone::DoThoroughLineTest(CVector start, CVector end, CEntity *testEntity)
-{
- CColPoint colPoint;
- CEntity *entity;
-
- if(CWorld::ProcessLineOfSight(start, end, colPoint, entity, true, false, false, false, false, true, false) &&
- testEntity != entity)
- return false;
-
- CVector side;
-#ifdef FIX_BUGS
- if(start.x != end.x || start.y != end.y)
-#else
- if(start.x != end.x && start.y != end.y)
-#endif
- side = CVector(0.0f, 0.0f, 1.0f);
- else
- side = CVector(1.0f, 0.0f, 0.0f);
- CVector up = CrossProduct(side, end - start);
- side = CrossProduct(up, end - start);
- side.Normalise();
- up.Normalise();
- side *= 0.1f;
- up *= 0.1f;
-
- if(CWorld::ProcessLineOfSight(start+side, end+side, colPoint, entity, true, false, false, false, false, true, false) &&
- testEntity != entity)
- return false;
- if(CWorld::ProcessLineOfSight(start-side, end-side, colPoint, entity, true, false, false, false, false, true, false) &&
- testEntity != entity)
- return false;
- if(CWorld::ProcessLineOfSight(start+up, end+up, colPoint, entity, true, false, false, false, false, true, false) &&
- testEntity != entity)
- return false;
- if(CWorld::ProcessLineOfSight(start-up, end-up, colPoint, entity, true, false, false, false, false, true, false) &&
- testEntity != entity)
- return false;
- return true;
-}
-
-bool
-CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
-{
- const CVector &pos = entity->GetPosition();
-
- CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex());
- float distToZone = CalcDistToCullZone(pos.x, pos.y);
- float lodDist;
- if (minfo->m_noFade)
- lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE;
- else
- lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE + FADE_DISTANCE;
-
- if (lodDist > distToZone) return true;
- if (!checkLevel) return false;
- CVector tempPos(minx, miny, minz);
- return CTheZones::GetLevelFromPosition(&pos) == CTheZones::GetLevelFromPosition(&tempPos);
-}
-
-bool
-CCullZone::PointFallsWithinZone(CVector pos, float radius)
-{
- if(minx - radius > pos.x ||
- maxx + radius < pos.x ||
- miny - radius > pos.y ||
- maxy + radius < pos.y ||
- minz - radius > pos.z ||
- maxz + radius < pos.z)
- return false;
- return true;
-}
-
-
-CVector ExtraFudgePointsCoors[] = {
- CVector(978.0f, -394.0f, 18.0f),
- CVector(1189.7f, -414.6f, 27.0f),
- CVector(978.8f, -391.0f, 19.0f),
- CVector(1199.0f, -502.3f, 28.0f),
- CVector(1037.0f, -391.9f, 18.4f),
- CVector(1140.0f, -608.7f, 16.0f),
- CVector(1051.0f, -26.0f, 11.0f),
- CVector(951.5f, -345.1f, 12.0f),
- CVector(958.2f, -394.6f, 16.0f),
- CVector(1036.5f, -390.0f, 15.2f),
- CVector(960.6f, -390.5f, 20.9f),
- CVector(1061.0f, -640.6f, 16.3f),
- CVector(1034.5f, -388.96f, 14.78f),
- CVector(1038.4f, -13.98f, 12.2f),
- CVector(1047.2f, -16.7f, 10.6f),
- CVector(1257.9f, -333.3f, 40.0f),
- CVector(885.6f, -424.9f, 17.0f),
- CVector(1127.5f, -795.8f, 17.7f),
- CVector(1133.0f, -716.0f, 19.0f),
- CVector(1125.0f, -694.0f, 18.5f),
- CVector(1125.0f, -670.0f, 16.3f),
- CVector(1051.6f, 36.3f, 17.9f),
- CVector(1054.6f, -11.4f, 15.0f),
- CVector(1058.9f, -278.0f, 15.0f),
- CVector(1059.4f, -261.0f, 10.9f),
- CVector(1051.5f, -638.5f, 16.5f),
- CVector(1058.2f, -643.4f, 15.5f),
- CVector(1058.2f, -643.4f, 18.0f),
- CVector(826.0f, -260.0f, 7.0f),
- CVector(826.0f, -260.0f, 11.0f),
- CVector(833.0f, -603.6f, 16.4f),
- CVector(833.0f, -603.6f, 20.0f),
- CVector(1002.0f, -318.5f, 10.5f),
- CVector(998.0f, -318.0f, 9.8f),
- CVector(1127.0f, -183.0f, 18.1f),
- CVector(1123.0f, -331.5f, 23.8f),
- CVector(1123.8f, -429.0f, 24.0f),
- CVector(1197.0f, -30.0f, 13.7f),
- CVector(1117.5f, -230.0f, 17.3f),
- CVector(1117.5f, -230.0f, 20.0f),
- CVector(1120.0f, -281.6f, 21.5f),
- CVector(1120.0f, -281.6f, 24.0f),
- CVector(1084.5f, -1022.7f, 17.0f),
- CVector(1071.5f, 5.4f, 4.6f),
- CVector(1177.2f, -215.7f, 27.6f),
- CVector(841.6f, -460.0f, 19.7f),
- CVector(874.8f, -456.6f, 16.6f),
- CVector(918.3f, -451.8f, 17.8f),
- CVector(844.0f, -495.7f, 16.7f),
- CVector(842.0f, -493.4f, 21.0f),
- CVector(1433.5f, -774.4f, 16.9f),
- CVector(1051.0f, -205.0f, 7.5f),
- CVector(885.5f, -425.6f, 15.6f),
- CVector(182.6f, -470.4f, 27.8f),
- CVector(132.5f, -930.2f, 29.0f),
- CVector(124.7f, -904.0f, 28.0f),
- CVector(-50.0f, -686.0f, 22.0f),
- CVector(-49.1f, -694.5f, 22.5f),
- CVector(1063.8f, -404.45f, 16.2f),
- CVector(1062.2f, -405.5f, 17.0f)
-};
-int32 NumTestPoints;
-int32 aTestPointsX[100];
-int32 aTestPointsY[100];
-int32 aTestPointsZ[100];
-CVector aTestPoints[100];
-int32 ElementsX, ElementsY, ElementsZ;
-float StepX, StepY, StepZ;
-int32 Memsize;
-uint8 *pMem;
-#define MEM(x, y, z) pMem[((x)*ElementsY + (y))*ElementsZ + (z)]
-#define FLAG_FREE 1
-#define FLAG_PROCESSED 2
-
-int32 MinValX, MaxValX;
-int32 MinValY, MaxValY;
-int32 MinValZ, MaxValZ;
-int32 Point1, Point2;
-int32 NewPointX, NewPointY, NewPointZ;
-
-
-void
-CCullZone::FindTestPoints()
-{
- static int CZNumber;
-
- NumTestPoints = 0;
- ElementsX = (maxx-minx) < 1.0f ? 2 : (maxx-minx)+1.0f;
- ElementsY = (maxy-miny) < 1.0f ? 2 : (maxy-miny)+1.0f;
- ElementsZ = (maxz-minz) < 1.0f ? 2 : (maxz-minz)+1.0f;
- if(ElementsX > 32) ElementsX = 32;
- if(ElementsY > 32) ElementsY = 32;
- if(ElementsZ > 32) ElementsZ = 32;
- Memsize = ElementsX * ElementsY * ElementsZ;
- StepX = (maxx-minx)/(ElementsX-1);
- StepY = (maxy-miny)/(ElementsY-1);
- StepZ = (maxz-minz)/(ElementsZ-1);
-
- pMem = new uint8[Memsize];
- memset(pMem, 0, Memsize);
-
- // indices of center
- int x = ElementsX * (position.x-minx)/(maxx-minx);
- x = Clamp(x, 0, ElementsX-1);
- int y = ElementsY * (position.y-miny)/(maxy-miny);
- y = Clamp(y, 0, ElementsY-1);
- int z = ElementsZ * (position.z-minz)/(maxz-minz);
- z = Clamp(z, 0, ElementsZ-1);
-
- // Mark which test points inside the zone are not occupied by buildings.
- // To do this, mark the start point as free and do a food fill.
-
- // NB: we just assume the start position is free here!
- MEM(x, y, z) |= FLAG_FREE;
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- NumTestPoints++;
-
- bool notDoneYet;
- do{
- notDoneYet = false;
- for(x = 0; x < ElementsX; x++){
- for(y = 0; y < ElementsY; y++){
- for(z = 0; z < ElementsZ; z++){
- if(!(MEM(x, y, z) & FLAG_FREE) || MEM(x, y, z) & FLAG_PROCESSED)
- continue;
-
- float pX = x*StepX + minx;
- float pY = y*StepY + miny;
- float pZ = z*StepZ + minz;
-
- if(x > 0 && !(MEM(x-1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
- !TestLine(CVector(pX, pY, pZ), CVector(pX-StepX, pY, pZ)))
- MEM(x-1, y, z) |= FLAG_FREE;
- if(x < ElementsX-1 && !(MEM(x+1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
- !TestLine(CVector(pX, pY, pZ), CVector(pX+StepX, pY, pZ)))
- MEM(x+1, y, z) |= FLAG_FREE;
-
- if(y > 0 && !(MEM(x, y-1, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
- !TestLine(CVector(pX, pY, pZ), CVector(pX, pY-StepY, pZ)))
- MEM(x, y-1, z) |= FLAG_FREE;
- if(y < ElementsY-1 && !(MEM(x, y+1, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
- !TestLine(CVector(pX, pY, pZ), CVector(pX, pY+StepY, pZ)))
- MEM(x, y+1, z) |= FLAG_FREE;
-
- if(z > 0 && !(MEM(x, y, z-1) & (FLAG_FREE | FLAG_PROCESSED)) &&
- !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ-StepZ)))
- MEM(x, y, z-1) |= FLAG_FREE;
- if(z < ElementsZ-1 && !(MEM(x, y, z+1) & (FLAG_FREE | FLAG_PROCESSED)) &&
- !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ+StepZ)))
- MEM(x, y, z+1) |= FLAG_FREE;
-
- notDoneYet = true;
- MEM(x, y, z) |= FLAG_PROCESSED;
- }
- }
- }
- }while(notDoneYet);
-
- bool done;
-
- // Find bound planes of free space
-
- // increase x, bounds in y and z
- x = 0;
- do{
- done = false;
- int minA = 10000;
- int minB = 10000;
- int maxA = -10000;
- int maxB = -10000;
- for(y = 0; y < ElementsY; y++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(x, y, z) & FLAG_FREE){
- if(y + z < minA){
- minA = y + z;
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- }
- if(y + z > maxA){
- maxA = y + z;
- aTestPointsX[NumTestPoints+1] = x;
- aTestPointsY[NumTestPoints+1] = y;
- aTestPointsZ[NumTestPoints+1] = z;
- }
- if(y - z < minB){
- minB = y - z;
- aTestPointsX[NumTestPoints+2] = x;
- aTestPointsY[NumTestPoints+2] = y;
- aTestPointsZ[NumTestPoints+2] = z;
- }
- if(y - z > maxB){
- maxB = y - z;
- aTestPointsX[NumTestPoints+3] = x;
- aTestPointsY[NumTestPoints+3] = y;
- aTestPointsZ[NumTestPoints+3] = z;
- }
- done = true;
- }
- x++;
- }while(!done);
- NumTestPoints += 4;
-
- // decrease x, bounds in y and z
- x = ElementsX-1;
- do{
- done = false;
- int minA = 10000;
- int minB = 10000;
- int maxA = -10000;
- int maxB = -10000;
- for(y = 0; y < ElementsY; y++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(x, y, z) & FLAG_FREE){
- if(y + z < minA){
- minA = y + z;
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- }
- if(y + z > maxA){
- maxA = y + z;
- aTestPointsX[NumTestPoints+1] = x;
- aTestPointsY[NumTestPoints+1] = y;
- aTestPointsZ[NumTestPoints+1] = z;
- }
- if(y - z < minB){
- minB = y - z;
- aTestPointsX[NumTestPoints+2] = x;
- aTestPointsY[NumTestPoints+2] = y;
- aTestPointsZ[NumTestPoints+2] = z;
- }
- if(y - z > maxB){
- maxB = y - z;
- aTestPointsX[NumTestPoints+3] = x;
- aTestPointsY[NumTestPoints+3] = y;
- aTestPointsZ[NumTestPoints+3] = z;
- }
- done = true;
- }
- x--;
- }while(!done);
- NumTestPoints += 4;
-
- // increase y, bounds in x and z
- y = 0;
- do{
- done = false;
- int minA = 10000;
- int minB = 10000;
- int maxA = -10000;
- int maxB = -10000;
- for(x = 0; x < ElementsX; x++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(x, y, z) & FLAG_FREE){
- if(x + z < minA){
- minA = x + z;
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- }
- if(x + z > maxA){
- maxA = x + z;
- aTestPointsX[NumTestPoints+1] = x;
- aTestPointsY[NumTestPoints+1] = y;
- aTestPointsZ[NumTestPoints+1] = z;
- }
- if(x - z < minB){
- minB = x - z;
- aTestPointsX[NumTestPoints+2] = x;
- aTestPointsY[NumTestPoints+2] = y;
- aTestPointsZ[NumTestPoints+2] = z;
- }
- if(x - z > maxB){
- maxB = x - z;
- aTestPointsX[NumTestPoints+3] = x;
- aTestPointsY[NumTestPoints+3] = y;
- aTestPointsZ[NumTestPoints+3] = z;
- }
- done = true;
- }
- y++;
- }while(!done);
- NumTestPoints += 4;
-
- // decrease y, bounds in x and z
- y = ElementsY-1;
- do{
- done = false;
- int minA = 10000;
- int minB = 10000;
- int maxA = -10000;
- int maxB = -10000;
- for(x = 0; x < ElementsX; x++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(x, y, z) & FLAG_FREE){
- if(x + z < minA){
- minA = x + z;
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- }
- if(x + z > maxA){
- maxA = x + z;
- aTestPointsX[NumTestPoints+1] = x;
- aTestPointsY[NumTestPoints+1] = y;
- aTestPointsZ[NumTestPoints+1] = z;
- }
- if(x - z < minB){
- minB = x - z;
- aTestPointsX[NumTestPoints+2] = x;
- aTestPointsY[NumTestPoints+2] = y;
- aTestPointsZ[NumTestPoints+2] = z;
- }
- if(x - z > maxB){
- maxB = x - z;
- aTestPointsX[NumTestPoints+3] = x;
- aTestPointsY[NumTestPoints+3] = y;
- aTestPointsZ[NumTestPoints+3] = z;
- }
- done = true;
- }
- y--;
- }while(!done);
- NumTestPoints += 4;
-
- // increase z, bounds in x and y
- z = 0;
- do{
- done = false;
- int minA = 10000;
- int minB = 10000;
- int maxA = -10000;
- int maxB = -10000;
- for(x = 0; x < ElementsX; x++)
- for(y = 0; y < ElementsY; y++)
- if(MEM(x, y, z) & FLAG_FREE){
- if(x + y < minA){
- minA = x + y;
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- }
- if(x + y > maxA){
- maxA = x + y;
- aTestPointsX[NumTestPoints+1] = x;
- aTestPointsY[NumTestPoints+1] = y;
- aTestPointsZ[NumTestPoints+1] = z;
- }
- if(x - y < minB){
- minB = x - y;
- aTestPointsX[NumTestPoints+2] = x;
- aTestPointsY[NumTestPoints+2] = y;
- aTestPointsZ[NumTestPoints+2] = z;
- }
- if(x - y > maxB){
- maxB = x - y;
- aTestPointsX[NumTestPoints+3] = x;
- aTestPointsY[NumTestPoints+3] = y;
- aTestPointsZ[NumTestPoints+3] = z;
- }
- done = true;
- }
- z++;
- }while(!done);
- NumTestPoints += 4;
-
- // decrease z, bounds in x and y
- z = ElementsZ-1;
- do{
- done = false;
- int minA = 10000;
- int minB = 10000;
- int maxA = -10000;
- int maxB = -10000;
- for(x = 0; x < ElementsX; x++)
- for(y = 0; y < ElementsY; y++)
- if(MEM(x, y, z) & FLAG_FREE){
- if(x + y < minA){
- minA = x + y;
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- }
- if(x + y > maxA){
- maxA = x + y;
- aTestPointsX[NumTestPoints+1] = x;
- aTestPointsY[NumTestPoints+1] = y;
- aTestPointsZ[NumTestPoints+1] = z;
- }
- if(x - y < minB){
- minB = x - y;
- aTestPointsX[NumTestPoints+2] = x;
- aTestPointsY[NumTestPoints+2] = y;
- aTestPointsZ[NumTestPoints+2] = z;
- }
- if(x - y > maxB){
- maxB = x - y;
- aTestPointsX[NumTestPoints+3] = x;
- aTestPointsY[NumTestPoints+3] = y;
- aTestPointsZ[NumTestPoints+3] = z;
- }
- done = true;
- }
- z--;
- }while(!done);
- NumTestPoints += 4;
-
- // divide the axis aligned bounding planes into 4 and place some test points
-
- // x = 0 plane
- MinValY = 999999;
- MinValZ = 999999;
- MaxValY = 0;
- MaxValZ = 0;
- for(y = 0; y < ElementsY; y++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(0, y, z) & FLAG_FREE){
- if(y < MinValY) MinValY = y;
- if(z < MinValZ) MinValZ = z;
- if(y > MaxValY) MaxValY = y;
- if(z > MaxValZ) MaxValZ = z;
- }
- // pick 4 points in the found bounds and add new test points
- if(MaxValY != 0 && MaxValZ != 0)
- for(Point1 = 0; Point1 < 2; Point1++)
- for(Point2 = 0; Point2 < 2; Point2++){
- NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
- NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
- if(MEM(0, NewPointY, NewPointZ) & FLAG_FREE){
- aTestPointsX[NumTestPoints] = 0;
- aTestPointsY[NumTestPoints] = NewPointY;
- aTestPointsZ[NumTestPoints] = NewPointZ;
- NumTestPoints++;
- }
- }
-
- // x = ElementsX-1 plane
- MinValY = 999999;
- MinValZ = 999999;
- MaxValY = 0;
- MaxValZ = 0;
- for(y = 0; y < ElementsY; y++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(ElementsX-1, y, z) & FLAG_FREE){
- if(y < MinValY) MinValY = y;
- if(z < MinValZ) MinValZ = z;
- if(y > MaxValY) MaxValY = y;
- if(z > MaxValZ) MaxValZ = z;
- }
- // pick 4 points in the found bounds and add new test points
- if(MaxValY != 0 && MaxValZ != 0)
- for(Point1 = 0; Point1 < 2; Point1++)
- for(Point2 = 0; Point2 < 2; Point2++){
- NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
- NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
- if(MEM(ElementsX-1, NewPointY, NewPointZ) & FLAG_FREE){
- aTestPointsX[NumTestPoints] = ElementsX-1;
- aTestPointsY[NumTestPoints] = NewPointY;
- aTestPointsZ[NumTestPoints] = NewPointZ;
- NumTestPoints++;
- }
- }
-
- // y = 0 plane
- MinValX = 999999;
- MinValZ = 999999;
- MaxValX = 0;
- MaxValZ = 0;
- for(x = 0; x < ElementsX; x++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(x, 0, z) & FLAG_FREE){
- if(x < MinValX) MinValX = x;
- if(z < MinValZ) MinValZ = z;
- if(x > MaxValX) MaxValX = x;
- if(z > MaxValZ) MaxValZ = z;
- }
- // pick 4 points in the found bounds and add new test points
- if(MaxValX != 0 && MaxValZ != 0)
- for(Point1 = 0; Point1 < 2; Point1++)
- for(Point2 = 0; Point2 < 2; Point2++){
- NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
- NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
- if(MEM(NewPointX, 0, NewPointZ) & FLAG_FREE){
- aTestPointsX[NumTestPoints] = NewPointX;
- aTestPointsY[NumTestPoints] = 0;
- aTestPointsZ[NumTestPoints] = NewPointZ;
- NumTestPoints++;
- }
- }
-
- // y = ElementsY-1 plane
- MinValX = 999999;
- MinValZ = 999999;
- MaxValX = 0;
- MaxValZ = 0;
- for(x = 0; x < ElementsX; x++)
- for(z = 0; z < ElementsZ; z++)
- if(MEM(x, ElementsY-1, z) & FLAG_FREE){
- if(x < MinValX) MinValX = x;
- if(z < MinValZ) MinValZ = z;
- if(x > MaxValX) MaxValX = x;
- if(z > MaxValZ) MaxValZ = z;
- }
- // pick 4 points in the found bounds and add new test points
- if(MaxValX != 0 && MaxValZ != 0)
- for(Point1 = 0; Point1 < 2; Point1++)
- for(Point2 = 0; Point2 < 2; Point2++){
- NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
- NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
- if(MEM(NewPointX, ElementsY-1, NewPointZ) & FLAG_FREE){
- aTestPointsX[NumTestPoints] = NewPointX;
- aTestPointsY[NumTestPoints] = ElementsY-1;
- aTestPointsZ[NumTestPoints] = NewPointZ;
- NumTestPoints++;
- }
- }
-
- // z = 0 plane
- MinValX = 999999;
- MinValY = 999999;
- MaxValX = 0;
- MaxValY = 0;
- for(x = 0; x < ElementsX; x++)
- for(y = 0; y < ElementsY; y++)
- if(MEM(x, y, 0) & FLAG_FREE){
- if(x < MinValX) MinValX = x;
- if(y < MinValY) MinValY = y;
- if(x > MaxValX) MaxValX = x;
- if(y > MaxValY) MaxValY = y;
- }
- // pick 4 points in the found bounds and add new test points
- if(MaxValX != 0 && MaxValY != 0)
- for(Point1 = 0; Point1 < 2; Point1++)
- for(Point2 = 0; Point2 < 2; Point2++){
- NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
- NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
- if(MEM(NewPointX, NewPointY, 0) & FLAG_FREE){
- aTestPointsX[NumTestPoints] = NewPointX;
- aTestPointsY[NumTestPoints] = NewPointY;
- aTestPointsZ[NumTestPoints] = 0;
- NumTestPoints++;
- }
- }
-
- // z = ElementsZ-1 plane
- MinValX = 999999;
- MinValY = 999999;
- MaxValX = 0;
- MaxValY = 0;
- for(x = 0; x < ElementsX; x++)
- for(y = 0; y < ElementsY; y++)
- if(MEM(x, y, ElementsZ-1) & FLAG_FREE){
- if(x < MinValX) MinValX = x;
- if(y < MinValY) MinValY = y;
- if(x > MaxValX) MaxValX = x;
- if(y > MaxValY) MaxValY = y;
- }
- // pick 4 points in the found bounds and add new test points
- if(MaxValX != 0 && MaxValY != 0)
- for(Point1 = 0; Point1 < 2; Point1++)
- for(Point2 = 0; Point2 < 2; Point2++){
- NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
- NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
- if(MEM(NewPointX, NewPointY, ElementsZ-1) & FLAG_FREE){
- aTestPointsX[NumTestPoints] = NewPointX;
- aTestPointsY[NumTestPoints] = NewPointY;
- aTestPointsZ[NumTestPoints] = ElementsZ-1;
- NumTestPoints++;
- }
- }
-
- // add some hardcoded test points
- for(int i = 0; i < ARRAY_SIZE(ExtraFudgePointsCoors); i++)
- if(PointFallsWithinZone(ExtraFudgePointsCoors[i], 0.0f)){
- x = ElementsX * (ExtraFudgePointsCoors[i].x-minx)/(maxx-minx);
- y = ElementsY * (ExtraFudgePointsCoors[i].y-miny)/(maxy-miny);
- z = ElementsZ * (ExtraFudgePointsCoors[i].z-minz)/(maxz-minz);
- if(MEM(x, y, z) & FLAG_FREE){
- aTestPointsX[NumTestPoints] = x;
- aTestPointsY[NumTestPoints] = y;
- aTestPointsZ[NumTestPoints] = z;
- NumTestPoints++;
- }
- }
-
- // remove duplicate points
- for(int i = 0; i < NumTestPoints; i++)
- for(int j = i+1; j < NumTestPoints; j++)
- if(aTestPointsX[j] == aTestPointsX[i] &&
- aTestPointsY[j] == aTestPointsY[i] &&
- aTestPointsZ[j] == aTestPointsZ[i]){
- // get rid of [j]
- for(int k = j; k < NumTestPoints-1; k++){
- aTestPointsX[k] = aTestPointsX[k+1];
- aTestPointsY[k] = aTestPointsY[k+1];
- aTestPointsZ[k] = aTestPointsZ[k+1];
- }
- NumTestPoints--;
- }
-
- // convert points to floating point
- for(int i = 0; i < NumTestPoints; i++){
- aTestPoints[i].x = aTestPointsX[i]*StepX + minx;
- aTestPoints[i].y = aTestPointsY[i]*StepY + miny;
- aTestPoints[i].z = aTestPointsZ[i]*StepZ + minz;
- }
-
- CZNumber++;
-
- delete[] pMem;
- pMem = nil;
-}
-
-bool
-CCullZone::TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity)
-{
- CColModel *colmodel = entity->GetColModel();
- float boundMaxX = colmodel->boundingBox.max.x;
- float boundMaxY = colmodel->boundingBox.max.y;
- float boundMaxZ = colmodel->boundingBox.max.z;
- float boundMinX = colmodel->boundingBox.min.x;
- float boundMinY = colmodel->boundingBox.min.y;
- float boundMinZ = colmodel->boundingBox.min.z;
- if(LODentity){
- colmodel = LODentity->GetColModel();
- boundMaxX = Max(boundMaxX, colmodel->boundingBox.max.x);
- boundMaxY = Max(boundMaxY, colmodel->boundingBox.max.y);
- boundMaxZ = Max(boundMaxZ, colmodel->boundingBox.max.z);
- boundMinX = Min(boundMinX, colmodel->boundingBox.min.x);
- boundMinY = Min(boundMinY, colmodel->boundingBox.min.y);
- boundMinZ = Min(boundMinZ, colmodel->boundingBox.min.z);
- }
-
- if(boundMaxZ-boundMinZ + extraDist < 0.5f)
- boundMaxZ = boundMinZ + 0.5f;
- else
- boundMaxZ += extraDist;
-
- CVector vecMin = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMinZ);
- CVector vecMaxX = entity->GetMatrix() * CVector(boundMaxX, boundMinY, boundMinZ);
- CVector vecMaxY = entity->GetMatrix() * CVector(boundMinX, boundMaxY, boundMinZ);
- CVector vecMaxZ = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMaxZ);
- CVector dirx = vecMaxX - vecMin;
- CVector diry = vecMaxY - vecMin;
- CVector dirz = vecMaxZ - vecMin;
-
- // If building intersects zone at all, it's visible
- int x, y, z;
- for(x = 0; x < 9; x++){
- CVector posX = vecMin + x/8.0f*dirx;
- for(y = 0; y < 9; y++){
- CVector posY = posX + y/8.0f*diry;
- for(z = 0; z < 9; z++){
- CVector posZ = posY + z/8.0f*dirz;
- if(PointFallsWithinZone(posZ, 2.0f))
- return true;
- }
- }
- }
-
- float distToZone = CalcDistToCullZone(entity->GetPosition().x, entity->GetPosition().y)/15.0f;
- distToZone = Max(distToZone, 7.0f);
- int numX = (boundMaxX - boundMinX)/distToZone + 2.0f;
- int numY = (boundMaxY - boundMinY)/distToZone + 2.0f;
- int numZ = (boundMaxZ - boundMinZ)/distToZone + 2.0f;
-
- float stepX = 1.0f/(numX-1);
- float stepY = 1.0f/(numY-1);
- float stepZ = 1.0f/(numZ-1);
- float midX = (boundMaxX + boundMinX)/2.0f;
- float midY = (boundMaxY + boundMinY)/2.0f;
- float midZ = (boundMaxZ + boundMinZ)/2.0f;
-
- // check both xy planes
- for(int i = 0; i < NumTestPoints; i++){
- CVector testPoint = aTestPoints[i];
- CVector mid = entity->GetMatrix() * CVector(midX, midY, midZ);
- mid.z += 0.1f;
- if(DoThoroughLineTest(testPoint, mid, entity))
- return true;
-
- CVector ray = entity->GetPosition() - testPoint;
-
- float dotX = DotProduct(ray, dirx);
- float dotY = DotProduct(ray, diry);
- float dotZ = DotProduct(ray, dirz);
-
- for(x = 0; x < numX; x++){
- CVector pMinZ = vecMin + x*stepX*dirx;
- CVector pMaxZ = vecMin + x*stepX*dirx + dirz;
- for(y = 0; y < numY; y++)
- if(dotZ > 0.0f){
- if(DoThoroughLineTest(testPoint, pMinZ + y*stepY*diry, entity))
- return true;
- }else{
- if(DoThoroughLineTest(testPoint, pMaxZ + y*stepY*diry, entity))
- return true;
- }
- }
-
- for(x = 0; x < numX; x++){
- CVector pMinY = vecMin + x*stepX*dirx;
- CVector pMaxY = vecMin + x*stepX*dirx + diry;
- for(z = 1; z < numZ-1; z++) // edge cases already handled
- if(dotY > 0.0f){
- if(DoThoroughLineTest(testPoint, pMinY + z*stepZ*dirz, entity))
- return true;
- }else{
- if(DoThoroughLineTest(testPoint, pMaxY + z*stepZ*dirz, entity))
- return true;
- }
- }
-
- for(y = 1; y < numY-1; y++){ // edge cases already handled
- CVector pMinX = vecMin + y*stepY*diry;
- CVector pMaxX = vecMin + y*stepY*diry + dirx;
- for(z = 1; z < numZ-1; z++) // edge cases already handled
- if(dotX > 0.0f){
- if(DoThoroughLineTest(testPoint, pMinX + z*stepZ*dirz, entity))
- return true;
- }else{
- if(DoThoroughLineTest(testPoint, pMaxX + z*stepZ*dirz, entity))
- return true;
- }
- }
- }
-
- return false;
+ assert(NumAttributeZones < NUMATTRIBZONES);
+ attrib = &aAttributeZones[NumAttributeZones++];
+ attrib->minx = minx;
+ attrib->maxx = maxx;
+ attrib->miny = miny;
+ attrib->maxy = maxy;
+ attrib->minz = minz;
+ attrib->maxz = maxz;
+ attrib->attributes = flag;
+ attrib->wantedLevel = wantedLevel;
}