From f6c767d87c5cb04710fb7e2363706d07dfcef8a6 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 27 Jun 2019 14:17:42 +0200 Subject: CStreaming almost done --- src/CullZones.cpp | 24 +-- src/Frontend.cpp | 2 +- src/Radar.cpp | 36 ++-- src/Radar.h | 2 +- src/Streaming.cpp | 370 +++++++++++++++++++++++++++++++++++++++- src/Streaming.h | 7 +- src/entities/CutsceneObject.cpp | 2 +- src/entities/Entity.cpp | 18 +- src/entities/Entity.h | 16 +- src/render/Renderer.cpp | 10 +- 10 files changed, 421 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/CullZones.cpp b/src/CullZones.cpp index 76052351..f89d8256 100644 --- a/src/CullZones.cpp +++ b/src/CullZones.cpp @@ -233,10 +233,10 @@ CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i) int j; if(i < 6000){ - CPools::GetBuildingPool()->GetSlot(i)->m_bZoneCulled = false; + CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false; bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = false; + CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false; }else{ i -= 6000; for(j = 0; j < 3; j++) @@ -251,11 +251,11 @@ CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i) int j; if(i < 6000){ - CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = false; - CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled2 = false; + CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = false; + CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = false; bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = false; + CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false; }else{ i -= 6000; for(j = 0; j < 3; j++) @@ -283,10 +283,10 @@ CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i) int j; if(i < 6000){ - CPools::GetBuildingPool()->GetSlot(i)->m_bZoneCulled = true; + CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true; bb = CCullZones::aPointersToBigBuildingsForBuildings[i]; if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true; + CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; }else{ i -= 6000; for(j = 0; j < 3; j++) @@ -301,11 +301,11 @@ CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i) int j; if(i < 6000){ - CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = true;; - CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled2 = true;; + CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;; + CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = true;; bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true; + CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; }else{ i -= 6000; for(j = 0; j < 3; j++) @@ -320,10 +320,10 @@ CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i) int j; if(i < 6000){ - CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = true;; + CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;; bb = CCullZones::aPointersToBigBuildingsForTreadables[i]; if(bb != -1) - CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true; + CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true; }else{ i -= 6000; for(j = 0; j < 3; j++) diff --git a/src/Frontend.cpp b/src/Frontend.cpp index de9e8a65..8eff0324 100644 --- a/src/Frontend.cpp +++ b/src/Frontend.cpp @@ -906,7 +906,7 @@ void CMenuManager::LoadAllTextures() CFileMgr::SetDir(""); CTimer::Stop(); - CStreaming::MakeSpaceFor(716800); + CStreaming::MakeSpaceFor(700 * 1024); CStreaming::ImGonnaUseStreamingMemory(); CTxdStore::PushCurrentTxd(); diff --git a/src/Radar.cpp b/src/Radar.cpp index 1b6ca527..71f9aacd 100644 --- a/src/Radar.cpp +++ b/src/Radar.cpp @@ -645,7 +645,7 @@ int32 CRadar::GetRadarTraceColour(int32 color, bool bright) } #endif -#if 0 +#if 1 WRAPPER void CRadar::Initialise() { EAXJMP(0x4A3EF0); } #else void CRadar::Initialise() @@ -671,8 +671,8 @@ float CRadar::LimitRadarPoint(CVector2D &point) } #endif -#if 0 -WRAPPER void CRadar::LoadAllRadarBlips() { EAXJMP(0x4A6F30); } +#if 1 +WRAPPER void CRadar::LoadAllRadarBlips(int32) { EAXJMP(0x4A6F30); } #else void CRadar::LoadAllRadarBlips(int32) { @@ -680,7 +680,7 @@ void CRadar::LoadAllRadarBlips(int32) } #endif -#if 0 +#if 1 WRAPPER void CRadar::LoadTextures() { EAXJMP(0x4A4030); } #else void CRadar::LoadTextures() @@ -689,8 +689,8 @@ void CRadar::LoadTextures() } #endif -#if 0 -WRAPPER void CRadar::RemoveRadarSections() { EAXJMP(0x00); } +#if 1 +WRAPPER void CRadar::RemoveRadarSections() { EAXJMP(0x4A60E0); } #else void CRadar::RemoveRadarSections() { @@ -718,8 +718,8 @@ void CRadar::RequestMapSection(int32 x, int32 y) } #endif -#if 0 -WRAPPER void CRadar::SaveAllRadarBlips(int32) { EAXJMP(0x00); } +#if 1 +WRAPPER void CRadar::SaveAllRadarBlips(int32) { EAXJMP(0x4A6E30); } #else void CRadar::SaveAllRadarBlips(int32) { @@ -727,8 +727,8 @@ void CRadar::SaveAllRadarBlips(int32) } #endif -#if 0 -WRAPPER void CRadar::SetBlipSprite(int32, int32) { EAXJMP(0x00); } +#if 1 +WRAPPER void CRadar::SetBlipSprite(int32, int32) { EAXJMP(0x4A5840); } #else void CRadar::SetBlipSprite(int32 i, int32 icon) { @@ -736,8 +736,8 @@ void CRadar::SetBlipSprite(int32 i, int32 icon) } #endif -#if 0 -WRAPPER void CRadar::SetCoordBlip(int32, CVector, int32) { EAXJMP(0x00); } +#if 1 +WRAPPER int CRadar::SetCoordBlip(int32, CVector, int32) { EAXJMP(0x4A5590); } #else int CRadar::SetCoordBlip(int32 type, CVector pos, int32 flag) { @@ -745,8 +745,8 @@ int CRadar::SetCoordBlip(int32 type, CVector pos, int32 flag) } #endif -#if 0 -WRAPPER void CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) { EAXJMP(0x00); } +#if 1 +WRAPPER int CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) { EAXJMP(0x4A5640); } #else int CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) { @@ -815,7 +815,7 @@ void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 gr } #endif -#if 0 +#if 1 WRAPPER void CRadar::Shutdown() { EAXJMP(0x4A3F60); } #else void CRadar::Shutdown() @@ -824,10 +824,10 @@ void CRadar::Shutdown() } #endif -#if 0 -WRAPPER void CRadar::StreamRadarSections() { EAXJMP(0x4A6B60); } +#if 1 +WRAPPER void CRadar::StreamRadarSections(const CVector &posn) { EAXJMP(0x4A6B60); } #else -void CRadar::StreamRadarSections(CVector posn) +void CRadar::StreamRadarSections(const CVector &posn) { } diff --git a/src/Radar.h b/src/Radar.h index 5943498f..e5396a50 100644 --- a/src/Radar.h +++ b/src/Radar.h @@ -131,7 +131,7 @@ public: static void ShowRadarMarker(CVector pos, int16 color, float radius); static void ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha); static void Shutdown(); - static void StreamRadarSections(CVector posn); + static void StreamRadarSections(const CVector &posn); static void StreamRadarSections(int32 x, int32 y); static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y); static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in); diff --git a/src/Streaming.cpp b/src/Streaming.cpp index 65c0b0b8..7d633d90 100644 --- a/src/Streaming.cpp +++ b/src/Streaming.cpp @@ -15,6 +15,10 @@ #include "Entity.h" #include "FileMgr.h" #include "FileLoader.h" +#include "Zones.h" +#include "CullZones.h" +#include "Radar.h" +#include "Camera.h" #include "CdStream.h" #include "Streaming.h" @@ -46,7 +50,7 @@ uint16 &CStreaming::ms_loadedGangs = *(uint16*)0x95CC60; int32 *CStreaming::ms_imageOffsets = (int32*)0x6E60A0; int32 &CStreaming::ms_lastImageRead = *(int32*)0x880E2C; int32 &CStreaming::ms_imageSize = *(int32*)0x8F1A34; -int32 &CStreaming::ms_memoryAvailable = *(int32*)0x880F8C; +uint32 &CStreaming::ms_memoryAvailable = *(uint32*)0x880F8C; int32 &desiredNumVehiclesLoaded = *(int32*)0x5EC194; @@ -61,9 +65,6 @@ int32 &islandLODcomSub = *(int32*)0x6212D0; int32 &islandLODsubInd = *(int32*)0x6212D4; int32 &islandLODsubCom = *(int32*)0x6212D8; -WRAPPER void CStreaming::MakeSpaceFor(int32 size) { EAXJMP(0x409B70); } -WRAPPER void CStreaming::LoadScene(const CVector &pos) { EAXJMP(0x40A6D0); } - bool CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size) { @@ -1697,7 +1698,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float continue; e->m_scanCode = CWorld::GetCurrentScanCode(); - if(!e->m_flagC20 && !e->bIsSubway && + if(!e->bStreamingDontDelete && !e->bIsSubway && (!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){ CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()); if(mi->m_type != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())){ @@ -1727,7 +1728,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list) continue; e->m_scanCode = CWorld::GetCurrentScanCode(); - if(!e->m_flagC20 && !e->bIsSubway && + if(!e->bStreamingDontDelete && !e->bIsSubway && (!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){ CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()); if(mi->m_type != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())) @@ -1740,7 +1741,126 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list) void CStreaming::DeleteFarAwayRwObjects(const CVector &pos) { - // TODO + int posx, posy; + int x, y; + int r, i; + CSector *sect; + + posx = CWorld::GetSectorIndexX(pos.x); + posy = CWorld::GetSectorIndexY(pos.y); + + // Move oldSectorX/Y to new sector and delete RW objects in its "wake" for every step: + // O is the old sector, <- is the direction in which we move it, + // X are the sectors we delete RW objects from (except we go up to 10) + // X + // X X + // X X X + // X X X + // <- O X X X + // X X X + // X X X + // X X + // X + + while(posx != ms_oldSectorX){ + if(posx < ms_oldSectorX){ + for(r = 2; r <= 10; r++){ + x = ms_oldSectorX + r; + if(x < 0) + continue; + if(x >= NUMSECTORS_X) + break; + + for(i = -r; i <= r; i++){ + y = ms_oldSectorY + i; + if(y < 0) + continue; + if(y >= NUMSECTORS_Y) + break; + + sect = CWorld::GetSector(x, y); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]); + DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]); + } + } + ms_oldSectorX--; + }else{ + for(r = 2; r <= 10; r++){ + x = ms_oldSectorX - r; + if(x < 0) + break; + if(x >= NUMSECTORS_X) + continue; + + for(i = -r; i <= r; i++){ + y = ms_oldSectorY + i; + if(y < 0) + continue; + if(y >= NUMSECTORS_Y) + break; + + sect = CWorld::GetSector(x, y); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]); + DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]); + } + } + ms_oldSectorX++; + } + } + + while(posy != ms_oldSectorY){ + if(posy < ms_oldSectorY){ + for(r = 2; r <= 10; r++){ + y = ms_oldSectorY + r; + if(y < 0) + continue; + if(y >= NUMSECTORS_Y) + break; + + for(i = -r; i <= r; i++){ + x = ms_oldSectorX + i; + if(x < 0) + continue; + if(x >= NUMSECTORS_X) + break; + + sect = CWorld::GetSector(x, y); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]); + DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]); + } + } + ms_oldSectorY--; + }else{ + for(r = 2; r <= 10; r++){ + y = ms_oldSectorY - r; + if(y < 0) + break; + if(y >= NUMSECTORS_Y) + continue; + + for(i = -r; i <= r; i++){ + x = ms_oldSectorX + i; + if(x < 0) + continue; + if(x >= NUMSECTORS_X) + break; + + sect = CWorld::GetSector(x, y); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]); + DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]); + DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]); + } + } + ms_oldSectorY++; + } + } } void @@ -1785,6 +1905,152 @@ CStreaming::DeleteRwObjectsAfterDeath(const CVector &pos) } } +void +CStreaming::DeleteRwObjectsBehindCamera(int32 mem) +{ + int ix, iy; + int x, y; + int xmin, xmax, ymin, ymax; + int inc; + CSector *sect; + + if(ms_memoryUsed < mem) + return; + + ix = CWorld::GetSectorIndexX(TheCamera.GetPosition().x); + iy = CWorld::GetSectorIndexX(TheCamera.GetPosition().y); + + if(fabs(TheCamera.GetForward().x) > fabs(TheCamera.GetForward().y)){ + // looking west/east + + ymin = max(iy - 10, 0); + ymax = min(iy + 10, NUMSECTORS_Y); + assert(ymin <= ymax); + + // Delete a block of sectors that we know is behind the camera + if(TheCamera.GetForward().x > 0){ + // looking east + xmax = max(ix - 2, 0); + xmin = max(ix - 10, 0); + inc = 1; + }else{ + // looking west + xmax = min(ix + 2, NUMSECTORS_X); + xmin = min(ix + 10, NUMSECTORS_X); + inc = -1; + } + for(y = ymin; y <= ymax; y++){ + for(x = xmin; x != xmax; x += inc){ + sect = CWorld::GetSector(x, y); + if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem)) + return; + } + } + + // Now a block that intersects with the camera's frustum + if(TheCamera.GetForward().x > 0){ + // looking east + xmax = max(ix + 10, 0); + xmin = max(ix - 2, 0); + inc = 1; + }else{ + // looking west + xmax = min(ix - 10, NUMSECTORS_X); + xmin = min(ix + 2, NUMSECTORS_X); + inc = -1; + } + for(y = ymin; y <= ymax; y++){ + for(x = xmin; x != xmax; x += inc){ + sect = CWorld::GetSector(x, y); + if(DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) || + DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) || + DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem)) + return; + } + } + + if(RemoveReferencedTxds(mem)) + return; + + // As last resort, delete objects from the last step more aggressively + for(y = ymin; y <= ymax; y++){ + for(x = xmax; x != xmin; x -= inc){ + sect = CWorld::GetSector(x, y); + if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem)) + return; + } + } + }else{ + // looking north/south + + xmin = max(ix - 10, 0); + xmax = min(ix + 10, NUMSECTORS_X); + assert(xmin <= xmax); + + // Delete a block of sectors that we know is behind the camera + if(TheCamera.GetForward().y > 0){ + // looking north + ymax = max(iy - 2, 0); + ymin = max(iy - 10, 0); + inc = 1; + }else{ + // looking south + ymax = min(iy + 2, NUMSECTORS_Y); + ymin = min(iy + 10, NUMSECTORS_Y); + inc = -1; + } + for(x = xmin; x <= xmax; x++){ + for(y = ymin; y != ymax; y += inc){ + sect = CWorld::GetSector(x, y); + if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem)) + return; + } + } + + // Now a block that intersects with the camera's frustum + if(TheCamera.GetForward().y > 0){ + // looking north + ymax = max(iy + 10, 0); + ymin = max(iy - 2, 0); + inc = 1; + }else{ + // looking south + ymax = min(iy - 10, NUMSECTORS_Y); + ymin = min(iy + 2, NUMSECTORS_Y); + inc = -1; + } + for(x = xmin; x <= xmax; x++){ + for(y = ymin; y != ymax; y += inc){ + sect = CWorld::GetSector(x, y); + if(DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) || + DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) || + DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem)) + return; + } + } + + if(RemoveReferencedTxds(mem)) + return; + + // As last resort, delete objects from the last step more aggressively + for(x = xmin; x <= xmax; x++){ + for(y = ymax; y != ymin; y -= inc){ + sect = CWorld::GetSector(x, y); + if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) || + DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem)) + return; + } + } + } +} + void CStreaming::DeleteRwObjectsInSectorList(CPtrList &list) { @@ -1793,7 +2059,7 @@ CStreaming::DeleteRwObjectsInSectorList(CPtrList &list) for(node = list.first; node; node = node->next){ e = (CEntity*)node->item; - if(!e->m_flagC20 && !e->bImBeingRendered) + if(!e->bStreamingDontDelete && !e->bImBeingRendered) e->DeleteRwObject(); } } @@ -1806,7 +2072,7 @@ CStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y) for(node = list.first; node; node = node->next){ e = (CEntity*)node->item; - if(e->m_rwObject && !e->m_flagC20 && !e->bImBeingRendered){ + if(e->m_rwObject && !e->bStreamingDontDelete && !e->bImBeingRendered){ // Now this is pretty weird... if(fabs(CWorld::GetSectorIndexX(e->GetPosition().x) - x) >= 2.0f) // { @@ -1820,6 +2086,86 @@ CStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y) } } +bool +CStreaming::DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem) +{ + CPtrNode *node; + CEntity *e; + + for(node = list.first; node; node = node->next){ + e = (CEntity*)node->item; + if(!e->bStreamingDontDelete && !e->bImBeingRendered && + e->m_rwObject && ms_aInfoForModel[e->GetModelIndex()].m_next){ + e->DeleteRwObject(); + if(CModelInfo::GetModelInfo(e->GetModelIndex())->m_refCount == 0){ + RemoveModel(e->GetModelIndex()); + if(ms_memoryUsed < mem) + return true; + } + } + } + return false; +} + +bool +CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem) +{ + CPtrNode *node; + CEntity *e; + + for(node = list.first; node; node = node->next){ + e = (CEntity*)node->item; + if(!e->bStreamingDontDelete && !e->bImBeingRendered && + e->m_rwObject && !e->IsVisible() && ms_aInfoForModel[e->GetModelIndex()].m_next){ + e->DeleteRwObject(); + if(CModelInfo::GetModelInfo(e->GetModelIndex())->m_refCount == 0){ + RemoveModel(e->GetModelIndex()); + if(ms_memoryUsed < mem) + return true; + } + } + } + return false; +} + +void +CStreaming::MakeSpaceFor(int32 size) +{ + // BUG: ms_memoryAvailable can be uninitialized + // the code still happens to work in that case because ms_memoryAvailable is unsigned + // but it's not nice.... + + while((uint32)ms_memoryUsed >= ms_memoryAvailable - size) + if(!RemoveLeastUsedModel()){ + DeleteRwObjectsBehindCamera(ms_memoryAvailable - size); + return; + } +} + +void +CStreaming::LoadScene(const CVector &pos) +{ + CStreamingInfo *si, *prev; + eLevelName level; + + level = CTheZones::GetLevelFromPosition(pos); + debug("Start load scene\n"); + for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){ + prev = si->m_prev; + if((si->m_flags & (STREAMFLAGS_KEEP_IN_MEMORY|STREAMFLAGS_PRIORITY)) == 0) + RemoveModel(si - ms_aInfoForModel); + } + CRenderer::m_loadingPriority = false; + CCullZones::ForceCullZoneCoors(pos); + DeleteAllRwObjects(); + AddModelsToRequestList(pos); + CRadar::StreamRadarSections(pos); + RemoveUnusedBigBuildings(level); + RequestBigBuildings(level); + LoadAllRequestedModels(false); + debug("End load scene\n"); +} + STARTPATCHES InjectHook(0x406430, CStreaming::Init, PATCH_JUMP); InjectHook(0x406C80, CStreaming::Shutdown, PATCH_JUMP); @@ -1871,10 +2217,16 @@ STARTPATCHES InjectHook(0x407C50, (void (*)(CPtrList&,float,float,float,float,float,float))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP); InjectHook(0x407DD0, (void (*)(CPtrList&))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP); + InjectHook(0x407070, CStreaming::DeleteFarAwayRwObjects, PATCH_JUMP); InjectHook(0x407390, CStreaming::DeleteAllRwObjects, PATCH_JUMP); InjectHook(0x407400, CStreaming::DeleteRwObjectsAfterDeath, PATCH_JUMP); + InjectHook(0x408A60, CStreaming::DeleteRwObjectsBehindCamera, PATCH_JUMP); InjectHook(0x407560, CStreaming::DeleteRwObjectsInSectorList, PATCH_JUMP); InjectHook(0x4075A0, CStreaming::DeleteRwObjectsInOverlapSectorList, PATCH_JUMP); + InjectHook(0x409340, CStreaming::DeleteRwObjectsBehindCameraInSectorList, PATCH_JUMP); + InjectHook(0x4093C0, CStreaming::DeleteRwObjectsNotInFrustumInSectorList, PATCH_JUMP); + InjectHook(0x409B70, CStreaming::MakeSpaceFor, PATCH_JUMP); + InjectHook(0x40A6D0, CStreaming::LoadScene, PATCH_JUMP); InjectHook(0x4063E0, &CStreamingInfo::GetCdPosnAndSize, PATCH_JUMP); InjectHook(0x406410, &CStreamingInfo::SetCdPosnAndSize, PATCH_JUMP); diff --git a/src/Streaming.h b/src/Streaming.h index f35c56d5..4caefb6d 100644 --- a/src/Streaming.h +++ b/src/Streaming.h @@ -103,7 +103,7 @@ public: static int32 *ms_imageOffsets; //[NUMCDIMAGES] static int32 &ms_lastImageRead; static int32 &ms_imageSize; - static int32 &ms_memoryAvailable; + static uint32 &ms_memoryAvailable; static void Init(void); static void Shutdown(void); @@ -162,9 +162,12 @@ public: static void ProcessEntitiesInSectorList(CPtrList &list); static void DeleteFarAwayRwObjects(const CVector &pos); static void DeleteAllRwObjects(void); + static void DeleteRwObjectsAfterDeath(const CVector &pos); + static void DeleteRwObjectsBehindCamera(int32 mem); static void DeleteRwObjectsInSectorList(CPtrList &list); static void DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y); - static void DeleteRwObjectsAfterDeath(const CVector &pos); + static bool DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem); + static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem); static void LoadInitialPeds(void); static void LoadInitialVehicles(void); diff --git a/src/entities/CutsceneObject.cpp b/src/entities/CutsceneObject.cpp index 163d0513..a7bca122 100644 --- a/src/entities/CutsceneObject.cpp +++ b/src/entities/CutsceneObject.cpp @@ -15,7 +15,7 @@ CCutsceneObject::CCutsceneObject(void) { m_status = STATUS_SIMPLE; bUsesCollision = false; - m_flagC20 = true; + bStreamingDontDelete = true; ObjectCreatedBy = CUTSCENE_OBJECT; m_fMass = 1.0f; m_fTurnMass = 1.0f; diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 294518c8..e9b35cd5 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -35,14 +35,14 @@ CEntity::CEntity(void) bIsBIGBuilding = false; bRenderDamaged = false; - m_flagC1 = false; - m_flagC2 = false; - m_flagC4 = false; - m_flagC8 = false; - m_flagC10 = false; - m_flagC20 = false; - m_bZoneCulled = false; - m_bZoneCulled2 = false; + bBulletProof = false; + bFireProof = false; + bCollisionProof = false; + bMeleeProof = false; + bOnlyDamagedByPlayer = false; + bStreamingDontDelete = false; + bZoneCulled = false; + bZoneCulled2 = false; bRemoveFromWorld = false; bHasHitWall = false; @@ -305,7 +305,7 @@ CEntity::SetupBigBuilding(void) mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex); bIsBIGBuilding = true; - m_flagC20 = true; + bStreamingDontDelete = true; bUsesCollision = false; m_level = CTheZones::GetLevelFromPosition(GetPosition()); if(m_level == LEVEL_NONE){ diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 8816e206..27dd8c14 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -78,14 +78,14 @@ public: uint32 bRenderDamaged : 1; // flagsC - uint32 m_flagC1 : 1; // bullet proof? - uint32 m_flagC2 : 1; // fire proof? - uint32 m_flagC4 : 1; // collision proof? - uint32 m_flagC8 : 1; // melee proof? - uint32 m_flagC10 : 1; // bOnlyDamagedByPlayer? - uint32 m_flagC20 : 1; - uint32 m_bZoneCulled : 1; - uint32 m_bZoneCulled2 : 1; // only treadables+10m + uint32 bBulletProof : 1; + uint32 bFireProof : 1; + uint32 bCollisionProof : 1; + uint32 bMeleeProof : 1; + uint32 bOnlyDamagedByPlayer : 1; + uint32 bStreamingDontDelete : 1; + uint32 bZoneCulled : 1; + uint32 bZoneCulled2 : 1; // only treadables+10m // flagsD uint32 bRemoveFromWorld : 1; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 10001100..d8b0bbe6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -917,7 +917,7 @@ CRenderer::ScanBigBuildingList(CPtrList &list) for(node = list.first; node; node = node->next){ ent = (CEntity*)node->item; - if(!ent->m_bZoneCulled && SetupBigBuildingVisibility(ent) == 1) + if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == 1) ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; } } @@ -1122,7 +1122,7 @@ CRenderer::IsEntityCullZoneVisible(CEntity *ent) CPed *ped; CObject *obj; - if(ent->m_bZoneCulled) + if(ent->bZoneCulled) return false; switch(ent->m_type){ @@ -1132,12 +1132,12 @@ CRenderer::IsEntityCullZoneVisible(CEntity *ent) ped = (CPed*)ent; if(ped->bInVehicle) return ped->m_pMyVehicle && IsVehicleCullZoneVisible(ped->m_pMyVehicle); - return !(ped->m_pCurSurface && ped->m_pCurSurface->m_bZoneCulled2); + return !(ped->m_pCurSurface && ped->m_pCurSurface->bZoneCulled2); case ENTITY_TYPE_OBJECT: obj = (CObject*)ent; if(!obj->bIsStatic) return true; - return !(obj->m_pCurSurface && obj->m_pCurSurface->m_bZoneCulled2); + return !(obj->m_pCurSurface && obj->m_pCurSurface->bZoneCulled2); } return true; } @@ -1151,7 +1151,7 @@ CRenderer::IsVehicleCullZoneVisible(CEntity *ent) case STATUS_PHYSICS: case STATUS_ABANDONED: case STATUS_WRECKED: - return !(v->m_pCurSurface && v->m_pCurSurface->m_bZoneCulled2); + return !(v->m_pCurSurface && v->m_pCurSurface->bZoneCulled2); return true; } -- cgit v1.2.3