From b44df26d3ea5fcdaf6d954016303f358d2c64b79 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 5 May 2020 13:02:42 +0200 Subject: [PATCH] implemented most of streamed collisions and big buildings --- src/control/CarCtrl.cpp | 4 +- src/control/Record.cpp | 3 + src/control/Script.h | 3 + src/core/Camera.cpp | 2 + src/core/Camera.h | 7 +- src/core/ColStore.cpp | 231 ++++++++++++++++++++ src/core/ColStore.h | 43 ++++ src/core/Collision.cpp | 32 +++ src/core/Collision.h | 16 +- src/core/FileLoader.cpp | 164 ++++++++++++++- src/core/FileLoader.h | 6 + src/core/Frontend.h | 4 + src/core/Game.cpp | 26 +-- src/core/Game.h | 3 + src/core/PlayerInfo.h | 3 +- src/core/Streaming.cpp | 336 ++++++++++++++++++++++++++++-- src/core/Streaming.h | 42 +++- src/core/World.cpp | 4 +- src/core/config.h | 6 + src/core/re3.cpp | 26 +-- src/core/templates.h | 9 + src/entities/Entity.cpp | 26 +++ src/entities/Entity.h | 12 +- src/math/Rect.h | 19 ++ src/modelinfo/BaseModelInfo.cpp | 6 +- src/modelinfo/BaseModelInfo.h | 14 +- src/modelinfo/ClumpModelInfo.h | 2 +- src/modelinfo/ModelInfo.cpp | 16 ++ src/modelinfo/ModelInfo.h | 3 + src/modelinfo/SimpleModelInfo.cpp | 16 +- src/modelinfo/SimpleModelInfo.h | 7 +- src/peds/CivilianPed.cpp | 2 + src/peds/CopPed.cpp | 4 +- src/peds/EmergencyPed.cpp | 2 + src/peds/Ped.cpp | 2 + src/peds/Population.cpp | 2 + src/render/Renderer.cpp | 330 +++++++++++++++++++++++++++-- src/render/Renderer.h | 2 + src/save/GenericGameStorage.cpp | 2 + src/vehicles/Automobile.cpp | 2 + src/vehicles/Boat.cpp | 2 + 41 files changed, 1346 insertions(+), 95 deletions(-) create mode 100644 src/core/ColStore.cpp create mode 100644 src/core/ColStore.h diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index bfa33f27..7e772162 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -696,7 +696,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) if (pVehicle->bExtendedRange) threshold *= 1.5f; if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){ - if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)){ + if (pVehicle->GetIsOnScreenAndNotCulled()){ pVehicle->bFadeOut = true; }else{ CWorld::Remove(pVehicle); @@ -722,7 +722,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) if (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0) return; if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 && - (!pVehicle->GetIsOnScreen() || !CRenderer::IsEntityCullZoneVisible(pVehicle))){ + !pVehicle->GetIsOnScreenAndNotCulled()){ if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){ if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){ CWorld::Remove(pVehicle); diff --git a/src/control/Record.cpp b/src/control/Record.cpp index d086543f..6ae99e2c 100644 --- a/src/control/Record.cpp +++ b/src/control/Record.cpp @@ -417,8 +417,10 @@ void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomo *ppCar = pCar; } +//--MIAMI: unused void RemoveUnusedCollision(void) { +#ifndef MIAMI static const char* dontDeleteArray[] = { "rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22", "road_broadway02", "road_broadway01", "com_21way5", "com_21way50", @@ -430,6 +432,7 @@ void RemoveUnusedCollision(void) CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE); for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++) CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL; +#endif } void CRecordDataForChase::StartChaseScene(float startTime) diff --git a/src/control/Script.h b/src/control/Script.h index 01cad269..12a507c1 100644 --- a/src/control/Script.h +++ b/src/control/Script.h @@ -372,6 +372,9 @@ private: friend class CRunningScript; friend class CHud; friend void CMissionCleanup::Process(); +#ifdef MIAMI + friend class CColStore; +#endif }; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index 3f4684e7..830a2bb2 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -934,11 +934,13 @@ CCamera::CamControl(void) if(CCullZones::CamStairsForPlayer() && CCullZones::FindZoneWithStairsAttributeForPlayer()) stairs = true; // Some hack for Mr Whoopee in a bomb shop +#ifndef MIAMI // uhh, check this if(Cams[ActiveCam].Using3rdPersonMouseCam() && CCollision::ms_collisionInMemory == LEVEL_COMMERCIAL){ if(pTargetEntity->GetPosition().x < 83.0f && pTargetEntity->GetPosition().x > 18.0f && pTargetEntity->GetPosition().y < -305.0f && pTargetEntity->GetPosition().y > -390.0f) disableGarageCam = true; } +#endif if(!disableGarageCam && (CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) || stairs)){ if(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer){ if(pToGarageWeAreIn || stairs){ diff --git a/src/core/Camera.h b/src/core/Camera.h index 6d53f417..02122dfe 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -298,11 +298,12 @@ enum enum { - // TODO: figure out - FADE_0, + // TODO: find better names + FADE_0, // faded in FADE_1, // mid fade - FADE_2, + FADE_2, // faded out + // Direction FADE_OUT = 0, FADE_IN, FADE_NONE diff --git a/src/core/ColStore.cpp b/src/core/ColStore.cpp new file mode 100644 index 00000000..0c3356c5 --- /dev/null +++ b/src/core/ColStore.cpp @@ -0,0 +1,231 @@ +#include "common.h" +#ifdef MIAMI + +#include "templates.h" +#include "General.h" +#include "ModelInfo.h" +#include "Streaming.h" +#include "FileLoader.h" +#include "Script.h" +#include "Timer.h" +#include "Camera.h" +#include "Frontend.h" +#include "ColStore.h" + +CPool *CColStore::ms_pColPool; + +void +CColStore::Initialise(void) +{ + if(ms_pColPool == nil) + ms_pColPool = new CPool(COLSTORESIZE, "CollisionFiles"); + AddColSlot("generic"); // slot 0. not streamed +} + +void +CColStore::Shutdown(void) +{ + int i; + for(i = 0; i < COLSTORESIZE; i++) + RemoveColSlot(i); + if(ms_pColPool) + delete ms_pColPool; + ms_pColPool = nil; +} + +int +CColStore::AddColSlot(const char *name) +{ + ColDef *def = ms_pColPool->New(); + assert(def); + def->isLoaded = false; + def->a = 0; + def->bounds.left = 1000000.0f; + def->bounds.top = 1000000.0f; + def->bounds.right = -1000000.0f; + def->bounds.bottom = -1000000.0f; + def->minIndex = INT16_MAX; + def->maxIndex = INT16_MIN; + strcpy(def->name, name); + return ms_pColPool->GetJustIndex(def); +} + +void +CColStore::RemoveColSlot(int slot) +{ + if(GetSlot(slot)){ + if(GetSlot(slot)->isLoaded) + RemoveCol(slot); + ms_pColPool->Delete(GetSlot(slot)); + } +} + +int +CColStore::FindColSlot(const char *name) +{ + ColDef *def; + int size = ms_pColPool->GetSize(); + for(int i = 0; i < size; i++){ + def = GetSlot(i); + if(def && !CGeneral::faststricmp(def->name, name)) + return i; + } + return -1; +} + +char* +CColStore::GetColName(int32 slot) +{ + return GetSlot(slot)->name; +} + +CRect& +CColStore::GetBoundingBox(int32 slot) +{ + return GetSlot(slot)->bounds; +} + +void +CColStore::IncludeModelIndex(int32 slot, int32 modelIndex) +{ + ColDef *def = GetSlot(slot); + if(modelIndex < def->minIndex) + def->minIndex = modelIndex; + if(modelIndex > def->maxIndex) + def->maxIndex = modelIndex; +} + +bool +CColStore::LoadCol(int32 slot, uint8 *buffer, int32 bufsize) +{ + bool success; + ColDef *def = GetSlot(slot); + if(def->minIndex > def->maxIndex) + success = CFileLoader::LoadCollisionFileFirstTime(buffer, bufsize, slot); + else + success = CFileLoader::LoadCollisionFile(buffer, bufsize, slot); + if(success) + def->isLoaded = true; + else + debug("Failed to load Collision\n"); + return success; +} + +void +CColStore::RemoveCol(int32 slot) +{ + int id; + GetSlot(slot)->isLoaded = false; + for(id = 0; id < MODELINFOSIZE; id++){ + CBaseModelInfo *mi = CModelInfo::GetModelInfo(id); + if(mi){ + CColModel *col = mi->GetColModel(); + if(col && col->level == slot) + col->RemoveCollisionVolumes(); + } + } +} + +void +CColStore::LoadAllCollision(void) +{ + int i; + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i)) + CStreaming::RequestCol(i, 0); + CStreaming::LoadAllRequestedModels(false); +} + +void +CColStore::RemoveAllCollision(void) +{ + int i; + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i)) + if(CStreaming::CanRemoveCol(i)) + CStreaming::RemoveCol(i); +} + +static bool bLoadAtSecondPosition; +static CVector2D secondPosition; + +void +CColStore::AddCollisionNeededAtPosn(const CVector2D &pos) +{ + bLoadAtSecondPosition = true; + secondPosition = pos; +} + +void +CColStore::LoadCollision(const CVector2D &pos) +{ + int i; + + if(CStreaming::ms_disableStreaming) + return; + + for(i = 1; i < COLSTORESIZE; i++){ + if(GetSlot(i) == nil) + continue; + + bool wantThisOne = false; + + if(GetBoundingBox(i).IsPointInside(pos) || + bLoadAtSecondPosition && GetBoundingBox(i).IsPointInside(secondPosition, -119.0f) || + CGeneral::faststrcmp(GetColName(i), "yacht") == 0){ + wantThisOne = true; + }else{ + // TODO: check mission cleanup list + } + + if(wantThisOne) + CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY); + else + CStreaming::RemoveCol(i); + } + bLoadAtSecondPosition = false; +} + +void +CColStore::RequestCollision(const CVector2D &pos) +{ + int i; + + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f)) + CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY); +} + +void +CColStore::EnsureCollisionIsInMemory(const CVector2D &pos) +{ + int i; + + if(CStreaming::ms_disableStreaming) + return; + + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -110.0f) && + !CStreaming::HasColLoaded(i)){ + CStreaming::RequestCol(i, 0); + if(TheCamera.GetScreenFadeStatus() == FADE_0) + FrontEndMenuManager.MessageScreen("LOADCOL", false); + CTimer::Suspend(); + CStreaming::LoadAllRequestedModels(false); + CTimer::Resume(); + } +} + +bool +CColStore::HasCollisionLoaded(const CVector2D &pos) +{ + int i; + + for(i = 1; i < COLSTORESIZE; i++) + if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -110.0f) && + !GetSlot(i)->isLoaded) + return false; + return true; +} + +#endif diff --git a/src/core/ColStore.h b/src/core/ColStore.h new file mode 100644 index 00000000..0d686ffd --- /dev/null +++ b/src/core/ColStore.h @@ -0,0 +1,43 @@ +#pragma once + +#include "templates.h" + +struct ColDef { // made up name + int32 a; + bool isLoaded; + CRect bounds; + char name[20]; + int16 minIndex; + int16 maxIndex; +}; + +class CColStore +{ + static CPool *ms_pColPool; + +public: + static void Initialise(void); + static void Shutdown(void); + static int AddColSlot(const char *name); + static void RemoveColSlot(int32 slot); + static int FindColSlot(const char *name); + static char *GetColName(int32 slot); + static CRect &GetBoundingBox(int32 slot); + static void IncludeModelIndex(int32 slot, int32 modelIndex); + static bool LoadCol(int32 storeID, uint8 *buffer, int32 bufsize); + static void RemoveCol(int32 slot); + static void AddCollisionNeededAtPosn(const CVector2D &pos); + static void LoadAllCollision(void); + static void RemoveAllCollision(void); + static void LoadCollision(const CVector2D &pos); + static void RequestCollision(const CVector2D &pos); + static void EnsureCollisionIsInMemory(const CVector2D &pos); + static bool HasCollisionLoaded(const CVector2D &pos); + + static ColDef *GetSlot(int slot) { + assert(slot >= 0); + assert(ms_pColPool); + assert(slot < ms_pColPool->GetSize()); + return ms_pColPool->GetSlot(slot); + } +}; diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index 7dfe3651..f20fee6d 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -20,6 +20,10 @@ #include "SurfaceTable.h" #include "Lines.h" #include "Collision.h" +#ifdef MIAMI +#include "Camera.h" +#include "ColStore.h" +#endif enum Direction { @@ -34,22 +38,32 @@ enum Direction eLevelName CCollision::ms_collisionInMemory; CLinkList CCollision::ms_colModelCache; +//--MIAMI: done void CCollision::Init(void) { ms_colModelCache.Init(NUMCOLCACHELINKS); ms_collisionInMemory = LEVEL_NONE; +#ifdef MIAMI + CColStore::Initialise(); +#endif } +//--MIAMI: done void CCollision::Shutdown(void) { ms_colModelCache.Shutdown(); +#ifdef MIAMI + CColStore::Shutdown(); +#endif } +//--MIAMI: done void CCollision::Update(void) { +#ifndef MIAMI CVector playerCoors; playerCoors = FindPlayerCoors(); eLevelName level = CTheZones::m_CurrLevel; @@ -83,8 +97,10 @@ CCollision::Update(void) if(ms_collisionInMemory != CGame::currLevel) LoadCollisionWhenINeedIt(forceLevelChange); CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); +#endif } +//--MIAMI: unused eLevelName GetCollisionInSectorList(CPtrList &list) { @@ -101,6 +117,7 @@ GetCollisionInSectorList(CPtrList &list) return LEVEL_NONE; } +//--MIAMI: unused // Get a level this sector is in based on collision models eLevelName GetCollisionInSector(CSector §) @@ -121,9 +138,11 @@ GetCollisionInSector(CSector §) return (eLevelName)level; } +//--MIAMI: done void CCollision::LoadCollisionWhenINeedIt(bool forceChange) { +#ifndef MIAMI eLevelName level, l; bool multipleLevels; CVector playerCoors; @@ -184,6 +203,7 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) CPad::StopPadsShaking(); LoadCollisionScreen(CGame::currLevel); DMAudio.Service(); + CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false); CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL); CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL); @@ -204,15 +224,19 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange) CStreaming::RequestBigBuildings(CGame::currLevel); CStreaming::LoadAllRequestedModels(true); CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); + CGame::TidyUpMemory(true, true); CTimer::Update(); DMAudio.SetEffectsFadeVol(127); } +#endif } +//--MIAMI: done void CCollision::SortOutCollisionAfterLoad(void) { +#ifndef MIAMI if(ms_collisionInMemory == CGame::currLevel) return; @@ -224,6 +248,10 @@ CCollision::SortOutCollisionAfterLoad(void) } ms_collisionInMemory = CGame::currLevel; CGame::TidyUpMemory(true, false); +#else + CColStore::LoadCollision(TheCamera.GetPosition()); + CStreaming::LoadAllRequestedModels(false); +#endif } void @@ -1972,7 +2000,11 @@ CColModel::CColModel(void) vertices = nil; triangles = nil; trianglePlanes = nil; +#ifndef MIAMI level = CGame::currLevel; +#else + level = 0; // generic col slot +#endif ownsCollisionVolumes = true; } diff --git a/src/core/Collision.h b/src/core/Collision.h index bdf51eb8..4933606d 100644 --- a/src/core/Collision.h +++ b/src/core/Collision.h @@ -87,13 +87,19 @@ struct CStoredCollPoly struct CColModel { +#ifndef MIAMI CColSphere boundingSphere; CColBox boundingBox; - short numSpheres; - short numLines; - short numBoxes; - short numTriangles; - int level; +#endif + int16 numSpheres; + int16 numLines; + int16 numBoxes; + int16 numTriangles; +#ifndef MIAMI + int32 level; +#else + uint8 level; // colstore slot but probably same name +#endif bool ownsCollisionVolumes; CColSphere *spheres; CColLine *lines; diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index b7d82089..06eb5a34 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -24,6 +24,10 @@ #include "ZoneCull.h" #include "CdStream.h" #include "FileLoader.h" +#ifdef MIAMI +#include "Streaming.h" +#include "ColStore.h" +#endif char CFileLoader::ms_line[256]; @@ -53,7 +57,9 @@ CFileLoader::LoadLevel(const char *filename) savedTxd = RwTexDictionaryGetCurrent(); objectsLoaded = false; +#ifndef MIAMI savedLevel = CGame::currLevel; +#endif if(savedTxd == nil){ savedTxd = RwTexDictionaryCreate(); RwTexDictionarySetCurrent(savedTxd); @@ -77,12 +83,17 @@ CFileLoader::LoadLevel(const char *filename) AddTexDictionaries(savedTxd, txd); RwTexDictionaryDestroy(txd); }else if(strncmp(line, "COLFILE", 7) == 0){ +#ifndef MIAMI int level; sscanf(line+8, "%d", &level); CGame::currLevel = (eLevelName)level; LoadingScreenLoadingFile(line+10); LoadCollisionFile(line+10); CGame::currLevel = savedLevel; +#else + LoadingScreenLoadingFile(line+10); + LoadCollisionFile(line+10, 0); +#endif }else if(strncmp(line, "MODELFILE", 9) == 0){ LoadingScreenLoadingFile(line + 10); LoadModelFile(line + 10); @@ -94,8 +105,16 @@ CFileLoader::LoadLevel(const char *filename) LoadObjectTypes(line + 4); }else if(strncmp(line, "IPL", 3) == 0){ if(!objectsLoaded){ +#ifndef MIAMI CModelInfo::ConstructMloClumps(); CObjectData::Initialise("DATA\\OBJECT.DAT"); +#else + LoadingScreenLoadingFile("Collision"); + CObjectData::Initialise("DATA\\OBJECT.DAT"); + CStreaming::Init(); + CColStore::LoadAllCollision(); + // TODO: anim indices +#endif objectsLoaded = true; } LoadingScreenLoadingFile(line + 4); @@ -112,8 +131,18 @@ CFileLoader::LoadLevel(const char *filename) CFileMgr::CloseFile(fd); RwTexDictionarySetCurrent(savedTxd); + +#ifdef MIAMI + int i; + for(i = 1; i < COLSTORESIZE; i++) + if(CColStore::GetSlot(i)) + CColStore::GetBoundingBox(i).Grow(120.0f); + CWorld::RepositionCertainDynamicObjects(); + CColStore::RemoveAllCollision(); +#endif } +#ifndef MIAMI void CFileLoader::LoadCollisionFromDatFile(int currlevel) { @@ -137,6 +166,7 @@ CFileLoader::LoadCollisionFromDatFile(int currlevel) CFileMgr::CloseFile(fd); } +#endif char* CFileLoader::LoadLine(int fd) @@ -172,16 +202,25 @@ CFileLoader::LoadTexDictionary(const char *filename) return txd; } +struct ColHeader +{ + char ident[4]; + uint32 size; +}; + +//--MIAMI: done +#ifndef MIAMI void CFileLoader::LoadCollisionFile(const char *filename) +#else +void +CFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot) +#endif { int fd; char modelname[24]; CBaseModelInfo *mi; - struct { - char ident[4]; - uint32 size; - } header; + ColHeader header; debug("Loading collision file %s\n", filename); fd = CFileMgr::OpenFile(filename, "rb"); @@ -193,10 +232,17 @@ CFileLoader::LoadCollisionFile(const char *filename) mi = CModelInfo::GetModelInfo(modelname, nil); if(mi){ +#ifndef MIAMI if(mi->GetColModel()){ +#else + if(mi->GetColModel() && mi->m_bOwnsColModel){ +#endif LoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname); }else{ CColModel *model = new CColModel; +#ifdef MIAMI + model->level = colSlot; +#endif LoadCollisionModel(work_buff+24, *model, modelname); mi->SetColModel(model, true); } @@ -208,6 +254,82 @@ CFileLoader::LoadCollisionFile(const char *filename) CFileMgr::CloseFile(fd); } +#ifdef MIAMI +bool +CFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot) +{ + uint32 modelsize; + char modelname[24]; + CBaseModelInfo *mi; + ColHeader *header; + int modelIndex; + + while(size > 8){ + header = (ColHeader*)buffer; + modelsize = header->size; + if(strncmp(header->ident, "COLL", 4) != 0) + return size-8 < CDSTREAM_SECTOR_SIZE; + memcpy(modelname, buffer+8, 24); + memcpy(work_buff, buffer+32, modelsize-24); + size -= 32 + (modelsize-24); + buffer += 32 + (modelsize-24); + if(modelsize > 15*1024) + debug("colmodel %s is huge, size %d\n", modelname, modelsize); + + mi = CModelInfo::GetModelInfo(modelname, &modelIndex); + if(mi){ +if(modelIndex == 855) +modelIndex = modelIndex; + CColStore::IncludeModelIndex(colSlot, modelIndex); + CColModel *model = new CColModel; + model->level = colSlot; + LoadCollisionModel(work_buff, *model, modelname); + mi->SetColModel(model, true); + }else{ + debug("colmodel %s can't find a modelinfo\n", modelname); + } + } + return true; +} + +bool +CFileLoader::LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot) +{ + uint32 modelsize; + char modelname[24]; + CBaseModelInfo *mi; + ColHeader *header; + + while(size > 8){ + header = (ColHeader*)buffer; + modelsize = header->size; + if(strncmp(header->ident, "COLL", 4) != 0) + return size-8 < CDSTREAM_SECTOR_SIZE; + memcpy(modelname, buffer+8, 24); + memcpy(work_buff, buffer+32, modelsize-24); + size -= 32 + (modelsize-24); + buffer += 32 + (modelsize-24); + if(modelsize > 15*1024) + debug("colmodel %s is huge, size %d\n", modelname, modelsize); + + mi = CModelInfo::GetModelInfo(modelname, CColStore::GetSlot(colSlot)->minIndex, CColStore::GetSlot(colSlot)->maxIndex); + if(mi){ + if(mi->GetColModel()){ + LoadCollisionModel(work_buff, *mi->GetColModel(), modelname); + }else{ + CColModel *model = new CColModel; + model->level = colSlot; + LoadCollisionModel(work_buff, *model, modelname); + mi->SetColModel(model, true); + } + }else{ + debug("colmodel %s can't find a modelinfo\n", modelname); + } + } + return true; +} +#endif + void CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname) { @@ -1060,19 +1182,36 @@ CFileLoader::LoadObjectInstance(const char *line) CSimpleModelInfo *mi; RwMatrix *xform; CEntity *entity; +#ifdef MIAMI + float area; + if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f %f", + &id, name, &area, + &trans.x, &trans.y, &trans.z, + &scale.x, &scale.y, &scale.z, + &axis.x, &axis.y, &axis.z, &angle) != 13){ +#endif if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f", &id, name, &trans.x, &trans.y, &trans.z, &scale.x, &scale.y, &scale.z, &axis.x, &axis.y, &axis.z, &angle) != 12) return; +#ifdef MIAMI + area = 0; + } +#endif mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); if(mi == nil) return; assert(mi->IsSimple()); +#ifdef MIAMI + if(!CStreaming::IsObjectInCdImage(id)) + debug("Not in cdimage %s\n", mi->GetName()); +#endif + angle = -RADTODEG(2.0f * acosf(angle)); xform = RwMatrixCreate(); RwMatrixRotate(xform, &axis, angle, rwCOMBINEREPLACE); @@ -1087,6 +1226,9 @@ CFileLoader::LoadObjectInstance(const char *line) entity->SetModelIndexNoCreate(id); entity->GetMatrix() = CMatrix(xform); entity->m_level = CTheZones::GetLevelFromPosition(entity->GetPosition()); +#ifdef MIAMI + entity->m_area = area; +#endif if(mi->IsSimple()){ if(mi->m_isBigBuilding) entity->SetupBigBuilding(); @@ -1096,14 +1238,28 @@ CFileLoader::LoadObjectInstance(const char *line) if(mi->GetLargestLodDistance() < 2.0f) entity->bIsVisible = false; CWorld::Add(entity); + +#ifdef MIAMI + CColModel *col = entity->GetColModel(); + if(col->numSpheres || col->numBoxes || col->numTriangles){ + if(col->level != 0) + CColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect()); + }else + entity->bUsesCollision = false; + // TODO: set some flag here if col min is below 6 +#endif }else{ entity = new CDummyObject; entity->SetModelIndexNoCreate(id); entity->GetMatrix() = CMatrix(xform); CWorld::Add(entity); +//--MIAMI: TODO if(IsGlass(entity->GetModelIndex())) entity->bIsVisible = false; entity->m_level = CTheZones::GetLevelFromPosition(entity->GetPosition()); +#ifdef MIAMI + entity->m_area = area; +#endif } RwMatrixDestroy(xform); diff --git a/src/core/FileLoader.h b/src/core/FileLoader.h index 87b8fe61..aa8dcdb8 100644 --- a/src/core/FileLoader.h +++ b/src/core/FileLoader.h @@ -8,7 +8,13 @@ public: static void LoadCollisionFromDatFile(int currlevel); static char *LoadLine(int fd); static RwTexDictionary *LoadTexDictionary(const char *filename); +#ifndef MIAMI static void LoadCollisionFile(const char *filename); +#else + static void LoadCollisionFile(const char *filename, uint8 colSlot = 0); + static bool LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot); + static bool LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot); +#endif static void LoadCollisionModel(uint8 *buf, struct CColModel &model, char *name); static void LoadModelFile(const char *filename); static RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 3286f275..c27e5239 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -624,6 +624,10 @@ public: void LoadAllTextures(); void LoadSettings(); void MessageScreen(const char *); +#ifdef MIAMI + //--MIAMI: TODO: implement the second argument + void MessageScreen(const char *str, bool) { MessageScreen(str); } +#endif void PickNewPlayerColour(); void PrintBriefs(); static void PrintErrorMessage(); diff --git a/src/core/Game.cpp b/src/core/Game.cpp index 0e618c84..d0b3f5a3 100644 --- a/src/core/Game.cpp +++ b/src/core/Game.cpp @@ -89,6 +89,9 @@ eLevelName CGame::currLevel; +#ifdef MIAMI +int32 CGame::currArea; +#endif bool CGame::bDemoMode = true; bool CGame::nastyGame = true; bool CGame::frenchGame; @@ -319,22 +322,7 @@ bool CGame::Initialise(const char* datFile) CDraw::SetFOV(120.0f); CDraw::ms_fLODDistance = 500.0f; LoadingScreen("Loading the Game", "Setup streaming", nil); -#ifdef USE_TXD_CDIMAGE - int txdHandle = CFileMgr::OpenFile("MODELS\\TXD.IMG", "r"); - if (txdHandle) - CFileMgr::CloseFile(txdHandle); - if (!CheckVideoCardCaps() && txdHandle) { - CdStreamAddImage("MODELS\\TXD.IMG"); - CStreaming::Init(); - } else { - CStreaming::Init(); - if (CreateTxdImageForVideoCard()) { - CStreaming::Shutdown(); - CdStreamAddImage("MODELS\\TXD.IMG"); - CStreaming::Init(); - } - } -#else +#ifndef MIAMI CStreaming::Init(); #endif CStreaming::LoadInitialVehicles(); @@ -384,8 +372,10 @@ bool CGame::Initialise(const char* datFile) CWaterCannons::Init(); CBridge::Init(); CGarages::Init(); +#ifndef MIAMI LoadingScreen("Loading the Game", "Position dynamic objects", nil); CWorld::RepositionCertainDynamicObjects(); +#endif LoadingScreen("Loading the Game", "Initialise vehicle paths", nil); #ifdef GTA_ZONECULL CCullZones::ResolveVisibilities(); @@ -400,7 +390,9 @@ bool CGame::Initialise(const char* datFile) CTheScripts::Process(); TheCamera.Process(); LoadingScreen("Loading the Game", "Load scene", nil); +#ifndef MIAMI CModelInfo::RemoveColModelsFromOtherLevels(currLevel); +#endif CCollision::ms_collisionInMemory = currLevel; for (int i = 0; i < MAX_PADS; i++) CPad::GetPad(i)->Clear(true); @@ -540,7 +532,9 @@ void CGame::ReloadIPLs(void) CRoadBlocks::Init(); CCranes::InitCranes(); CGarages::Init(); +#ifndef MIAMI CWorld::RepositionCertainDynamicObjects(); +#endif #ifdef GTA_ZONECULL CCullZones::ResolveVisibilities(); #endif diff --git a/src/core/Game.h b/src/core/Game.h index 48f31abc..8db5adf5 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -12,6 +12,9 @@ class CGame { public: static eLevelName currLevel; +#ifdef MIAMI + static int32 currArea; +#endif static bool bDemoMode; static bool nastyGame; static bool frenchGame; diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h index 8d0a27b6..13266331 100644 --- a/src/core/PlayerInfo.h +++ b/src/core/PlayerInfo.h @@ -80,5 +80,6 @@ public: ~CPlayerInfo() { }; }; - +#ifndef MIAMI static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error"); +#endif diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index a76e9038..f1aa4cc5 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -32,6 +32,10 @@ #include "Replay.h" #endif #include "main.h" +#ifdef MIAMI +#include "ColStore.h" +#include "DMAudio.h" +#endif bool CStreaming::ms_disableStreaming; bool CStreaming::ms_bLoadingBigModel; @@ -53,7 +57,9 @@ int32 CStreaming::ms_vehiclesLoaded[MAXVEHICLESLOADED]; int32 CStreaming::ms_lastVehicleDeleted; CDirectory *CStreaming::ms_pExtraObjectsDir; int32 CStreaming::ms_numPriorityRequests; +#ifndef MIAMI bool CStreaming::ms_hasLoadedLODs; +#endif int32 CStreaming::ms_currentPedGrp; int32 CStreaming::ms_currentPedLoading; int32 CStreaming::ms_lastCullZone; @@ -114,7 +120,7 @@ CStreamingInfo::RemoveFromList(void) } void -CStreaming::Init(void) +CStreaming::Init2(void) { int i; @@ -184,7 +190,9 @@ CStreaming::Init(void) ms_pExtraObjectsDir = new CDirectory(EXTRADIRSIZE); ms_numPriorityRequests = 0; +#ifndef MIAMI ms_hasLoadedLODs = true; +#endif ms_currentPedGrp = -1; ms_lastCullZone = -1; // unused because RemoveModelsNotVisibleFromCullzone is gone ms_loadedGangs = 0; @@ -231,6 +239,7 @@ CStreaming::Init(void) CModelInfo::GetModelInfo("IslandLODsubIND", &islandLODsubInd); CModelInfo::GetModelInfo("IslandLODsubCOM", &islandLODsubCom); +#ifndef MIAMI for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){ CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); if(building == nil) @@ -241,6 +250,30 @@ CStreaming::Init(void) if(building->GetModelIndex() == islandLODsubInd) pIslandLODsubIndEntity = building; if(building->GetModelIndex() == islandLODsubCom) pIslandLODsubComEntity = building; } +#endif +} + +void +CStreaming::Init(void) +{ +#ifdef USE_TXD_CDIMAGE + int txdHandle = CFileMgr::OpenFile("MODELS\\TXD.IMG", "r"); + if (txdHandle) + CFileMgr::CloseFile(txdHandle); + if (!CheckVideoCardCaps() && txdHandle) { + CdStreamAddImage("MODELS\\TXD.IMG"); + CStreaming::Init2(); + } else { + CStreaming::Init2(); + if (CreateTxdImageForVideoCard()) { + CStreaming::Shutdown(); + CdStreamAddImage("MODELS\\TXD.IMG"); + CStreaming::Init2(); + } + } +#else + CStreaming::Init(); +#endif } void @@ -269,21 +302,35 @@ CStreaming::Update(void) if(CTimer::GetIsPaused()) return; +#ifndef MIAMI train = FindPlayerTrain(); if(train && train->GetPosition().z < 0.0f){ RequestSubway(); requestedSubway = true; }else if(!ms_disableStreaming) AddModelsToRequestList(TheCamera.GetPosition()); +#else + LoadBigBuildingsWhenNeeded(); + if(!ms_disableStreaming && TheCamera.GetPosition().z < 55.0f) + AddModelsToRequestList(TheCamera.GetPosition()); +#endif DeleteFarAwayRwObjects(TheCamera.GetPosition()); if(!ms_disableStreaming && +#ifndef MIAMI !CCutsceneMgr::IsRunning() && !requestedSubway && !CGame::playingIntro && +#else + !CCutsceneMgr::IsCutsceneProcessing() && +#endif ms_numModelsRequested < 5 && !CRenderer::m_loadingPriority +#ifdef MIAMI + && CGame::currArea == 0 + // replay is also MIAMI +#endif #ifdef FIX_BUGS && !CReplay::IsPlayingBack() #endif @@ -294,6 +341,17 @@ CStreaming::Update(void) LoadRequestedModels(); +#ifdef MIAMI + if(CWorld::Players[0].m_pRemoteVehicle){ + CColStore::AddCollisionNeededAtPosn(FindPlayerCoors()); + CColStore::LoadCollision(CWorld::Players[0].m_pRemoteVehicle->GetPosition()); + CColStore::EnsureCollisionIsInMemory(CWorld::Players[0].m_pRemoteVehicle->GetPosition()); + }else{ + CColStore::LoadCollision(FindPlayerCoors()); + CColStore::EnsureCollisionIsInMemory(FindPlayerCoors()); + } +#endif + 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) @@ -351,6 +409,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) imgSelector = n<<24; assert(sizeof(direntry) == 32); while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){ +#ifndef MIAMI dot = strchr(direntry.name, '.'); if(dot) *dot = '\0'; if(direntry.size > (uint32)ms_streamingBufferSize) @@ -393,6 +452,64 @@ CStreaming::LoadCdDirectory(const char *dirname, int n) } }else lastID = -1; +#else + bool bAddToStreaming = false; + + if(direntry.size > (uint32)ms_streamingBufferSize) + ms_streamingBufferSize = direntry.size; + direntry.name[23] = '\0'; + dot = strchr(direntry.name, '.'); + if(dot == nil || dot-direntry.name > 20){ + debug("%s is too long\n", direntry.name); + lastID = -1; + continue; + } + + *dot = '\0'; + + if(!CGeneral::faststricmp(dot+1, "DFF")){ + if(CModelInfo::GetModelInfo(direntry.name, &modelId)){ + bAddToStreaming = true; + }else{ +#ifdef FIX_BUGS + // remember which cdimage this came from + ms_pExtraObjectsDir->AddItem(direntry, n); +#else + ms_pExtraObjectsDir->AddItem(direntry); +#endif + lastID = -1; + } + }else if(!CGeneral::faststricmp(dot+1, "TXD")){ + modelId = CTxdStore::FindTxdSlot(direntry.name); + if(modelId == -1) + modelId = CTxdStore::AddTxdSlot(direntry.name); + modelId += STREAM_OFFSET_TXD; + bAddToStreaming = true; + }else if(!CGeneral::faststricmp(dot+1, "COL")){ + modelId = CColStore::FindColSlot(direntry.name); + if(modelId == -1) + modelId = CColStore::AddColSlot(direntry.name); + modelId += STREAM_OFFSET_COL; + bAddToStreaming = true; + // TODO: IFP + }else{ + *dot = '.'; + lastID = -1; + } + + if(bAddToStreaming){ + if(ms_aInfoForModel[modelId].GetCdSize()){ + debug("%s.%s appears more than once in %s\n", direntry.name, dot+1, dirname); + lastID = -1; + }else{ + direntry.offset |= imgSelector; + ms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size); + if(lastID != -1) + ms_aInfoForModel[lastID].m_nextID = modelId; + lastID = modelId; + } + } +#endif } CFileMgr::CloseFile(fd); @@ -416,6 +533,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) stream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem); if(streamId < STREAM_OFFSET_TXD){ +//--MIAMI: also check animation // Model mi = CModelInfo::GetModelInfo(streamId); @@ -457,7 +575,11 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) RwStreamClose(stream, &mem); return false; } +#ifndef MIAMI }else{ +#else + }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ +#endif // Txd assert(streamId < NUMSTREAMINFO); if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 && @@ -482,10 +604,22 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) RwStreamClose(stream, &mem); return false; } +#ifdef MIAMI + }else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO){ + if(!CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length)){ + debug("Failed to load %s.col\n", CColStore::GetColName(streamId - STREAM_OFFSET_COL)); + RemoveModel(streamId); + ReRequestModel(streamId); + RwStreamClose(stream, &mem); + return false; + } + // TODO: IFPs +#endif } RwStreamClose(stream, &mem); +#ifndef MIAMI // We shouldn't even end up here unless load was successful if(!success){ ReRequestModel(streamId); @@ -495,6 +629,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) debug("Failed to load %s.txd\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD)); return false; } +#endif if(streamId < STREAM_OFFSET_TXD){ // Model @@ -510,12 +645,16 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) smi->m_alpha = 0; } - if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0) + if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0) ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList); } +#ifndef MIAMI }else{ +#else + }else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){ // TODO: animations +#endif // Txd - if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0) + if((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_CANT_REMOVE) == 0) ms_aInfoForModel[streamId].AddToList(&ms_startLoadedList); } @@ -528,10 +667,23 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId) endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond(); timeDiff = endTime - startTime; if(timeDiff > 5){ +#ifndef MIAMI if(streamId < STREAM_OFFSET_TXD) debug("model %s took %d ms\n", CModelInfo::GetModelInfo(streamId)->GetName(), timeDiff); else debug("txd %s took %d ms\n", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD), timeDiff); +#else + // TODO: is this inlined? + static char objname[32]; + if(streamId < STREAM_OFFSET_TXD) + sprintf(objname, "%s.dff", CModelInfo::GetModelInfo(streamId)->GetName()); + else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL) + sprintf(objname, "%s.txd", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD)); + else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO) + sprintf(objname, "%s.col", CColStore::GetColName(streamId-STREAM_OFFSET_COL)); + // TODO: IFP + debug("%s took %d ms\n", objname, timeDiff); +#endif } return true; @@ -628,7 +780,7 @@ CStreaming::RequestModel(int32 id, int32 flags) // reinsert into list if(ms_aInfoForModel[id].m_next){ ms_aInfoForModel[id].RemoveFromList(); - if((ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0) + if((ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0) ms_aInfoForModel[id].AddToList(&ms_startLoadedList); } }else if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED || @@ -689,6 +841,12 @@ CStreaming::RequestSubway(void) } } +#ifndef MIAMI +#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY +#else +#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE +#endif + void CStreaming::RequestBigBuildings(eLevelName level) { @@ -699,27 +857,69 @@ CStreaming::RequestBigBuildings(eLevelName level) for(i = n; i >= 0; i--){ b = CPools::GetBuildingPool()->GetSlot(i); if(b && b->bIsBIGBuilding && b->m_level == level) - RequestModel(b->GetModelIndex(), STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); +#ifdef MIAMI + if(!b->bStreamBIGBuilding) +#endif + RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS); } RequestIslands(level); +#ifndef MIAMI ms_hasLoadedLODs = false; +#endif } +#ifdef MIAMI +void +CStreaming::RequestBigBuildings(eLevelName level, const CVector &pos) +{ + int i, n; + CBuilding *b; + + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ + b = CPools::GetBuildingPool()->GetSlot(i); + if(b && b->bIsBIGBuilding && b->m_level == level) + if(b->bStreamBIGBuilding){ + if(CRenderer::ShouldModelBeStreamed(b)) + RequestModel(b->GetModelIndex(), 0); + }else + RequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS); + } + RequestIslands(level); +} + +void +CStreaming::InstanceBigBuildings(eLevelName level, const CVector &pos) +{ + int i, n; + CBuilding *b; + + n = CPools::GetBuildingPool()->GetSize()-1; + for(i = n; i >= 0; i--){ + b = CPools::GetBuildingPool()->GetSlot(i); + if(b && b->bIsBIGBuilding && b->m_level == level && + b->bStreamBIGBuilding && b->m_rwObject == nil) + if(CRenderer::ShouldModelBeStreamed(b)) + b->CreateRwObject(); + } +} +#endif + void CStreaming::RequestIslands(eLevelName level) { switch(level){ case LEVEL_INDUSTRIAL: - RequestModel(islandLODcomInd, STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); - RequestModel(islandLODsubInd, STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); + RequestModel(islandLODcomInd, BIGBUILDINGFLAGS); + RequestModel(islandLODsubInd, BIGBUILDINGFLAGS); break; case LEVEL_COMMERCIAL: - RequestModel(islandLODindust, STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); - RequestModel(islandLODsubCom, STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); + RequestModel(islandLODindust, BIGBUILDINGFLAGS); + RequestModel(islandLODsubCom, BIGBUILDINGFLAGS); break; case LEVEL_SUBURBAN: - RequestModel(islandLODindust, STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); - RequestModel(islandLODcomSub, STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY); + RequestModel(islandLODindust, BIGBUILDINGFLAGS); + RequestModel(islandLODcomSub, BIGBUILDINGFLAGS); break; } } @@ -802,10 +1002,20 @@ CStreaming::RemoveModel(int32 id) return; if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){ +#ifndef MIAMI if(id < STREAM_OFFSET_TXD) CModelInfo::GetModelInfo(id)->DeleteRwObject(); else CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); +#else + if(id < STREAM_OFFSET_TXD) + CModelInfo::GetModelInfo(id)->DeleteRwObject(); + else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL) + CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); + else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO) + CColStore::RemoveCol(id - STREAM_OFFSET_COL); + // TODO: IFP +#endif ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE; } @@ -824,15 +1034,26 @@ CStreaming::RemoveModel(int32 id) } if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_STARTED){ +#ifndef MIAMI if(id < STREAM_OFFSET_TXD) RpClumpGtaCancelStream(); else CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); +#else + if(id < STREAM_OFFSET_TXD) + RpClumpGtaCancelStream(); + else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL) + CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD); + else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO) + CColStore::RemoveCol(id - STREAM_OFFSET_COL); + // TODO: IFP +#endif } ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED; } +//--MIAMI: change islands void CStreaming::RemoveUnusedBuildings(eLevelName level) { @@ -844,6 +1065,7 @@ CStreaming::RemoveUnusedBuildings(eLevelName level) RemoveBuildings(LEVEL_SUBURBAN); } +//--MIAMI: done void CStreaming::RemoveBuildings(eLevelName level) { @@ -904,6 +1126,7 @@ CStreaming::RemoveBuildings(eLevelName level) } } +//--MIAMI: change islands void CStreaming::RemoveUnusedBigBuildings(eLevelName level) { @@ -932,6 +1155,21 @@ DeleteIsland(CEntity *island) void CStreaming::RemoveIslandsNotUsed(eLevelName level) { +#ifdef MIAMI + int i; + if(pIslandLODindustEntity == nil) + for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){ + CBuilding *building = CPools::GetBuildingPool()->GetSlot(i); + if(building == nil) + continue; + if(building->GetModelIndex() == islandLODindust) pIslandLODindustEntity = building; + if(building->GetModelIndex() == islandLODcomInd) pIslandLODcomIndEntity = building; + if(building->GetModelIndex() == islandLODcomSub) pIslandLODcomSubEntity = building; + if(building->GetModelIndex() == islandLODsubInd) pIslandLODsubIndEntity = building; + if(building->GetModelIndex() == islandLODsubCom) pIslandLODsubComEntity = building; + } +#endif + switch(level){ case LEVEL_INDUSTRIAL: DeleteIsland(pIslandLODindustEntity); @@ -958,6 +1196,7 @@ CStreaming::RemoveIslandsNotUsed(eLevelName level) } } +//--MIAMI: done void CStreaming::RemoveBigBuildings(eLevelName level) { @@ -990,7 +1229,7 @@ CStreaming::RemoveLoadedVehicle(void) ms_lastVehicleDeleted = 0; id = ms_vehiclesLoaded[ms_lastVehicleDeleted]; if(id != -1 && - (ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0 && + (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 && CModelInfo::GetModelInfo(id)->m_refCount == 0 && ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED) goto found; @@ -1129,7 +1368,7 @@ CStreaming::AddToLoadedVehiclesList(int32 modelId) for(i = 0; i < MAXVEHICLESLOADED; i++){ id = ms_vehiclesLoaded[ms_lastVehicleDeleted]; if(id != -1 && - (ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0 && + (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 && CModelInfo::GetModelInfo(id)->m_refCount == 0) goto found; ms_lastVehicleDeleted++; @@ -1163,6 +1402,7 @@ CStreaming::IsObjectInCdImage(int32 id) return ms_aInfoForModel[id].GetCdPosnAndSize(posn, size); } +#ifndef MIAMI void CStreaming::HaveAllBigBuildingsLoaded(eLevelName level) { @@ -1197,6 +1437,7 @@ CStreaming::HaveAllBigBuildingsLoaded(eLevelName level) RemoveUnusedBigBuildings(level); ms_hasLoadedLODs = true; } +#endif void CStreaming::SetModelIsDeletable(int32 id) @@ -1430,6 +1671,43 @@ CStreaming::RemoveCurrentZonesModels(void) ms_loadedGangCars = 0; } +#ifdef MIAMI +void +CStreaming::LoadBigBuildingsWhenNeeded(void) +{ + // Very much like CCollision::Update and CCollision::LoadCollisionWhenINeedIt + if(CCutsceneMgr::IsCutsceneProcessing()) + return; + + if(CTheZones::m_CurrLevel == LEVEL_NONE || + CTheZones::m_CurrLevel == CGame::currLevel) + return; + + CTimer::Suspend(); + CGame::currLevel = CTheZones::m_CurrLevel; + DMAudio.SetEffectsFadeVol(0); + CPad::StopPadsShaking(); + CCollision::LoadCollisionScreen(CGame::currLevel); + DMAudio.Service(); + + // CPopulation::DealWithZoneChange is unused in VC + RemoveUnusedBigBuildings(CGame::currLevel); + RemoveUnusedBuildings(CGame::currLevel); + RemoveUnusedModelsInLoadedList(); + CGame::TidyUpMemory(true, true); + + CReplay::EmptyReplayBuffer(); + if(CGame::currLevel != LEVEL_NONE) + LoadSplash(GetLevelSplashScreen(CGame::currLevel)); + + CStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition()); + CStreaming::LoadAllRequestedModels(true); + + CGame::TidyUpMemory(true, true); + CTimer::Resume(); + DMAudio.SetEffectsFadeVol(127); +} +#endif // Find starting offset of the cdimage we next want to read @@ -1683,10 +1961,10 @@ CStreaming::ProcessLoadingChannel(int32 ch) CModelInfo::GetModelInfo(id)->m_type == MITYPE_VEHICLE && ms_numVehiclesLoaded >= desiredNumVehiclesLoaded && !RemoveLoadedVehicle() && - ((ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) == 0 || GetAvailableVehicleSlot() == -1)){ + ((ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0 || GetAvailableVehicleSlot() == -1)){ // can't load vehicle RemoveModel(id); - if(ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOT_IN_LIST) + if(ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) ReRequestModel(id); else if(CTxdStore::GetNumRefs(CModelInfo::GetModelInfo(id)->GetTxdSlot()) == 0) RemoveTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot()); @@ -1960,7 +2238,9 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float if(xmin < pos.x && pos.x < xmax && ymin < pos.y && pos.y < ymax && (CVector2D(x, y) - pos).MagnitudeSqr() < lodDistSq) +#ifdef GTA_ZONECULL if(CRenderer::IsEntityCullZoneVisible(e)) +#endif RequestModel(e->GetModelIndex(), 0); } } @@ -1984,7 +2264,9 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list) (!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())) +#ifdef GTA_ZONECULL if(CRenderer::IsEntityCullZoneVisible(e)) +#endif RequestModel(e->GetModelIndex(), 0); } } @@ -2408,13 +2690,37 @@ CStreaming::LoadScene(const CVector &pos) RemoveModel(si - ms_aInfoForModel); } CRenderer::m_loadingPriority = false; +#ifdef GTA_ZONECULL CCullZones::ForceCullZoneCoors(pos); +#endif DeleteAllRwObjects(); +#ifndef MIAMI AddModelsToRequestList(pos); CRadar::StreamRadarSections(pos); RemoveUnusedBigBuildings(level); RequestBigBuildings(level); LoadAllRequestedModels(false); +#else + if(level == LEVEL_NONE) + level = CGame::currLevel; + CGame::currLevel = level; + RemoveUnusedBigBuildings(level); + RequestBigBuildings(level, pos); + RequestBigBuildings(LEVEL_NONE, pos); + RemoveIslandsNotUsed(level); + LoadAllRequestedModels(false); + InstanceBigBuildings(level, pos); + InstanceBigBuildings(LEVEL_NONE, pos); + AddModelsToRequestList(pos); + CRadar::StreamRadarSections(pos); + + // TODO: stream zone vehicles + LoadAllRequestedModels(false); + // TODO: InstanceLoadedModels + + for(int i = 0; i < NUMSTREAMINFO; i++) + ms_aInfoForModel[i].m_flags &= ~STREAMFLAGS_20; +#endif debug("End load scene\n"); } diff --git a/src/core/Streaming.h b/src/core/Streaming.h index cf8790e9..d2920824 100644 --- a/src/core/Streaming.h +++ b/src/core/Streaming.h @@ -3,9 +3,13 @@ #include "Game.h" enum { - STREAM_OFFSET_MODEL = 0, - STREAM_OFFSET_TXD = STREAM_OFFSET_MODEL+MODELINFOSIZE, + STREAM_OFFSET_TXD = MODELINFOSIZE, +#ifndef MIAMI NUMSTREAMINFO = STREAM_OFFSET_TXD+TXDSTORESIZE +#else + STREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE, + NUMSTREAMINFO = STREAM_OFFSET_COL+COLSTORESIZE +#endif }; enum StreamFlags @@ -15,9 +19,11 @@ enum StreamFlags STREAMFLAGS_DEPENDENCY = 0x04, // Is this right? STREAMFLAGS_PRIORITY = 0x08, STREAMFLAGS_NOFADE = 0x10, +#ifdef MIAMI + STREAMFLAGS_20 = 0x20, +#endif - // TODO: this isn't named well, maybe CANT_REMOVE? - STREAMFLAGS_NOT_IN_LIST = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED, + STREAMFLAGS_CANT_REMOVE = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED, STREAMFLAGS_KEEP_IN_MEMORY = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED|STREAMFLAGS_DEPENDENCY, }; @@ -96,7 +102,9 @@ public: static int32 ms_lastVehicleDeleted; static CDirectory *ms_pExtraObjectsDir; static int32 ms_numPriorityRequests; +#ifndef MIAMI static bool ms_hasLoadedLODs; +#endif static int32 ms_currentPedGrp; static int32 ms_lastCullZone; static uint16 ms_loadedGangs; @@ -108,6 +116,7 @@ public: static uint32 ms_memoryAvailable; static void Init(void); + static void Init2(void); static void Shutdown(void); static void Update(void); static void LoadCdDirectory(void); @@ -115,12 +124,29 @@ public: static bool ConvertBufferToObject(int8 *buf, int32 streamId); static bool FinishLoadingLargeFile(int8 *buf, int32 streamId); static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; } + static bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); } +#ifdef MIAMI + static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); } +#endif + static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; } + static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); } +#ifdef MIAMI + static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); } +#endif static void RequestModel(int32 model, int32 flags); static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); } static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); } static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); } +#ifdef MIAMI + static void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); } + static void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); } +#endif static void RequestSubway(void); static void RequestBigBuildings(eLevelName level); +#ifdef MIAMI + static void RequestBigBuildings(eLevelName level, const CVector &pos); + static void InstanceBigBuildings(eLevelName level, const CVector &pos); +#endif static void RequestIslands(eLevelName level); static void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags); static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags); @@ -129,6 +155,9 @@ public: static void DecrementRef(int32 id); static void RemoveModel(int32 id); static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); } +#ifdef MIAMI + static void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); } +#endif static void RemoveUnusedBuildings(eLevelName level); static void RemoveBuildings(eLevelName level); static void RemoveUnusedBigBuildings(eLevelName level); @@ -143,7 +172,9 @@ public: static bool IsTxdUsedByRequestedModels(int32 txdId); static bool AddToLoadedVehiclesList(int32 modelId); static bool IsObjectInCdImage(int32 id); +#ifndef MIAMI static void HaveAllBigBuildingsLoaded(eLevelName level); +#endif static void SetModelIsDeletable(int32 id); static void SetModelTxdIsDeletable(int32 id); static void SetMissionDoesntRequireModel(int32 id); @@ -152,6 +183,9 @@ public: static void StreamVehiclesAndPeds(void); static void StreamZoneModels(const CVector &pos); static void RemoveCurrentZonesModels(void); +#ifdef MIAMI + static void LoadBigBuildingsWhenNeeded(void); +#endif static int32 GetCdImageOffset(int32 lastPosn); static int32 GetNextFileOnCd(int32 position, bool priority); diff --git a/src/core/World.cpp b/src/core/World.cpp index e87d23f2..befdfad4 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1,4 +1,4 @@ -#include "World.h" +#include "common.h" #include "Camera.h" #include "CarCtrl.h" #include "CopPed.h" @@ -26,7 +26,7 @@ #include "TempColModels.h" #include "Vehicle.h" #include "WaterLevel.h" -#include "common.h" +#include "World.h" #define OBJECT_REPOSITION_OFFSET_Z 2.0f diff --git a/src/core/config.h b/src/core/config.h index f4f7205b..c3904fa9 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -7,8 +7,14 @@ enum Config { MAX_CDIMAGES = 8, // additional cdimages MAX_CDCHANNELS = 5, +#ifndef MIAMI MODELINFOSIZE = 5500, TXDSTORESIZE = 850, +#else + MODELINFOSIZE = 6500, + TXDSTORESIZE = 1385, + COLSTORESIZE = 31, +#endif EXTRADIRSIZE = 128, CUTSCENEDIRSIZE = 512, diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 44253c14..a74b81a3 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -323,14 +323,26 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); }); DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); }); + DebugMenuAddVarBool8("Render", "Draw hud", &CHud::m_Wants_To_Draw_Hud, nil); #ifdef LIBRW DebugMenuAddVarBool8("Render", "PS2 Alpha test Emu", &gPS2alphaTest, nil); #endif DebugMenuAddVarBool8("Render", "Frame limiter", &FrontEndMenuManager.m_PrefsFrameLimiter, nil); DebugMenuAddVarBool8("Render", "VSynch", &FrontEndMenuManager.m_PrefsVsync, nil); DebugMenuAddVar("Render", "Max FPS", &RsGlobal.maxFPS, nil, 1, 1, 1000, nil); + DebugMenuAddVarBool8("Render", "Show Ped Paths", &gbShowPedPaths, nil); + DebugMenuAddVarBool8("Render", "Show Car Paths", &gbShowCarPaths, nil); + DebugMenuAddVarBool8("Render", "Show Car Path Links", &gbShowCarPathsLinks, nil); + DebugMenuAddVarBool8("Render", "Show Ped Road Groups", &gbShowPedRoadGroups, nil); + DebugMenuAddVarBool8("Render", "Show Car Road Groups", &gbShowCarRoadGroups, nil); + DebugMenuAddVarBool8("Render", "Show Collision Lines", &gbShowCollisionLines, nil); + DebugMenuAddVarBool8("Render", "Show Collision Polys", &gbShowCollisionPolys, nil); + DebugMenuAddVarBool8("Render", "Don't render Buildings", &gbDontRenderBuildings, nil); + DebugMenuAddVarBool8("Render", "Don't render Big Buildings", &gbDontRenderBigBuildings, nil); + DebugMenuAddVarBool8("Render", "Don't render Peds", &gbDontRenderPeds, nil); + DebugMenuAddVarBool8("Render", "Don't render Vehicles", &gbDontRenderVehicles, nil); + DebugMenuAddVarBool8("Render", "Don't render Objects", &gbDontRenderObjects, nil); - DebugMenuAddVarBool8("Debug", "Draw hud", &CHud::m_Wants_To_Draw_Hud, nil); DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil); #ifdef MENU_MAP DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint); @@ -347,18 +359,6 @@ DebugMenuPopulate(void) DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); DebugMenuAddVarBool8("Debug", "Script Heli On", &CHeli::ScriptHeliOn, nil); - DebugMenuAddVarBool8("Debug", "Show Ped Paths", &gbShowPedPaths, nil); - DebugMenuAddVarBool8("Debug", "Show Car Paths", &gbShowCarPaths, nil); - DebugMenuAddVarBool8("Debug", "Show Car Path Links", &gbShowCarPathsLinks, nil); - DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", &gbShowPedRoadGroups, nil); - DebugMenuAddVarBool8("Debug", "Show Car Road Groups", &gbShowCarRoadGroups, nil); - DebugMenuAddVarBool8("Debug", "Show Collision Lines", &gbShowCollisionLines, nil); - DebugMenuAddVarBool8("Debug", "Show Collision Polys", &gbShowCollisionPolys, nil); - DebugMenuAddVarBool8("Debug", "Don't render Buildings", &gbDontRenderBuildings, nil); - DebugMenuAddVarBool8("Debug", "Don't render Big Buildings", &gbDontRenderBigBuildings, nil); - DebugMenuAddVarBool8("Debug", "Don't render Peds", &gbDontRenderPeds, nil); - DebugMenuAddVarBool8("Debug", "Don't render Vehicles", &gbDontRenderVehicles, nil); - DebugMenuAddVarBool8("Debug", "Don't render Objects", &gbDontRenderObjects, nil); #ifdef TOGGLEABLE_BETA_FEATURES DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil); DebugMenuAddVarBool8("Debug", "Toggle peds running to phones to report crimes", &CPed::bMakePedsRunToPhonesToReportCrimes, nil); diff --git a/src/core/templates.h b/src/core/templates.h index 51a24e4c..74bc4713 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -35,15 +35,24 @@ class CPool public: CPool(int size){ + // TODO: use new here m_entries = (U*)malloc(sizeof(U)*size); m_flags = (Flags*)malloc(sizeof(Flags)*size); m_size = size; +#ifndef MIAMI m_allocPtr = 0; +#else + m_allocPtr = -1; +#endif for(int i = 0; i < size; i++){ m_flags[i].id = 0; m_flags[i].free = 1; } } +#ifdef MIAMI + CPool(int size, const char *name) + : CPool(size) {} +#endif ~CPool() { Flush(); } diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 2a6211d6..8014a47a 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -27,6 +27,7 @@ #include "Zones.h" #include "Bones.h" #include "Debug.h" +#include "Renderer.h" int gBuildings; @@ -51,6 +52,9 @@ CEntity::CEntity(void) bRenderScorched = false; bHasBlip = false; bIsBIGBuilding = false; +#ifdef MIAMI + bStreamBIGBuilding = false; +#endif bRenderDamaged = false; bBulletProof = false; @@ -59,8 +63,10 @@ CEntity::CEntity(void) bMeleeProof = false; bOnlyDamagedByPlayer = false; bStreamingDontDelete = false; +#ifdef GTA_ZONECULL bZoneCulled = false; bZoneCulled2 = false; +#endif bRemoveFromWorld = false; bHasHitWall = false; @@ -147,6 +153,17 @@ CEntity::GetIsOnScreenComplex(void) return TheCamera.IsBoxVisible(boundBox, &TheCamera.GetCameraMatrix()); } +bool +CEntity::GetIsOnScreenAndNotCulled(void) +{ +#ifdef GTA_ZONECULL + return GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(this); +#else + return GetIsOnScreen(); +#endif +} + + void CEntity::Add(void) { @@ -331,6 +348,11 @@ CEntity::SetupBigBuilding(void) bStreamingDontDelete = true; bUsesCollision = false; m_level = CTheZones::GetLevelFromPosition(GetPosition()); +#ifdef MIAMI + if(mi->m_lodDistances[0] <= 2000.0f) + bStreamBIGBuilding = true; + // TODO: the stuff down there isn't right yet +#endif if(m_level == LEVEL_NONE){ if(mi->GetTxdSlot() != CTxdStore::FindTxdSlot("generic")){ mi->SetTexDictionary("generic"); @@ -953,8 +975,10 @@ CEntity::SaveEntityFlags(uint8*& buf) if (bMeleeProof) tmp |= BIT(27); if (bOnlyDamagedByPlayer) tmp |= BIT(28); if (bStreamingDontDelete) tmp |= BIT(29); +#ifdef GTA_ZONECULL if (bZoneCulled) tmp |= BIT(30); if (bZoneCulled2) tmp |= BIT(31); +#endif WriteSaveBuf(buf, tmp); @@ -1006,8 +1030,10 @@ CEntity::LoadEntityFlags(uint8*& buf) bMeleeProof = !!(tmp & BIT(27)); bOnlyDamagedByPlayer = !!(tmp & BIT(28)); bStreamingDontDelete = !!(tmp & BIT(29)); +#ifdef GTA_ZONECULL bZoneCulled = !!(tmp & BIT(30)); bZoneCulled2 = !!(tmp & BIT(31)); +#endif tmp = ReadSaveBuf(buf); diff --git a/src/entities/Entity.h b/src/entities/Entity.h index dbe2c08b..94022224 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -59,7 +59,9 @@ public: uint32 bRenderScorched : 1; uint32 bHasBlip : 1; uint32 bIsBIGBuilding : 1; // Set if this entity is a big building - // VC inserts one more flag here: if drawdist <= 2000 +#ifdef MIAMI + uint32 bStreamBIGBuilding : 1; // set when draw dist <= 2000 +#endif uint32 bRenderDamaged : 1; // use damaged LOD models for objects with applicable damage // flagsC @@ -69,8 +71,10 @@ public: uint32 bMeleeProof : 1; uint32 bOnlyDamagedByPlayer : 1; uint32 bStreamingDontDelete : 1; // Dont let the streaming remove this +#ifdef GTA_ZONECULL uint32 bZoneCulled : 1; uint32 bZoneCulled2 : 1; // only treadables+10m +#endif // flagsD uint32 bRemoveFromWorld : 1; // remove this entity next time it should be processed @@ -89,7 +93,12 @@ public: uint16 m_scanCode; uint16 m_randomSeed; int16 m_modelIndex; +#ifndef MIAMI uint16 m_level; // int16 +#else + int8 m_level; + int8 m_area; +#endif CReference *m_pFirstReference; public: @@ -147,6 +156,7 @@ public: bool GetIsTouching(CVector const ¢er, float r); bool GetIsOnScreen(void); bool GetIsOnScreenComplex(void); + bool GetIsOnScreenAndNotCulled(void); bool IsVisible(void) { return m_rwObject && bIsVisible && GetIsOnScreen(); } bool IsVisibleComplex(void) { return m_rwObject && bIsVisible && GetIsOnScreenComplex(); } int GetModelIndex(void) { return m_modelIndex; } diff --git a/src/math/Rect.h b/src/math/Rect.h index fd1bd05e..326bb479 100644 --- a/src/math/Rect.h +++ b/src/math/Rect.h @@ -26,6 +26,25 @@ public: if(v.y < top) top = v.y; if(v.y > bottom) bottom = v.y; } + void ContainRect(const CRect &r){ + if(r.left < left) left = r.left; + if(r.right > right) right = r.right; + if(r.top < top) top = r.top; + if(r.bottom > bottom) bottom = r.bottom; + } + + bool IsPointInside(const CVector2D &p){ + return p.x >= left && + p.x <= right && + p.y >= top && + p.y <= bottom; + } + bool IsPointInside(const CVector2D &p, float extraRadius){ + return p.x >= left-extraRadius && + p.x <= right+extraRadius && + p.y >= top-extraRadius && + p.y <= bottom+extraRadius; + } void Translate(float x, float y){ left += x; diff --git a/src/modelinfo/BaseModelInfo.cpp b/src/modelinfo/BaseModelInfo.cpp index e8d2601f..a2779107 100644 --- a/src/modelinfo/BaseModelInfo.cpp +++ b/src/modelinfo/BaseModelInfo.cpp @@ -6,7 +6,7 @@ #include "BaseModelInfo.h" -CBaseModelInfo::CBaseModelInfo(ModeInfoType type) +CBaseModelInfo::CBaseModelInfo(ModelInfoType type) { m_colModel = nil; m_twodEffects = nil; @@ -15,7 +15,7 @@ CBaseModelInfo::CBaseModelInfo(ModeInfoType type) m_txdSlot = -1; m_type = type; m_num2dEffects = 0; - m_freeCol = false; + m_bOwnsColModel = false; } void @@ -31,7 +31,7 @@ CBaseModelInfo::Shutdown(void) void CBaseModelInfo::DeleteCollisionModel(void) { - if(m_colModel && m_freeCol){ + if(m_colModel && m_bOwnsColModel){ if(m_colModel) delete m_colModel; m_colModel = nil; diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h index 0c4bf934..44f4c47a 100644 --- a/src/modelinfo/BaseModelInfo.h +++ b/src/modelinfo/BaseModelInfo.h @@ -4,7 +4,7 @@ #define MAX_MODEL_NAME (24) -enum ModeInfoType : uint8 +enum ModelInfoType : uint8 { MITYPE_NA = 0, MITYPE_SIMPLE = 1, @@ -15,7 +15,7 @@ enum ModeInfoType : uint8 MITYPE_PED = 6, MITYPE_XTRACOMPS = 7, }; -static_assert(sizeof(ModeInfoType) == 1, "ModeInfoType: error"); +static_assert(sizeof(ModelInfoType) == 1, "ModeInfoType: error"); class C2dEffect; @@ -30,11 +30,11 @@ protected: public: uint16 m_refCount; int16 m_txdSlot; - ModeInfoType m_type; + ModelInfoType m_type; uint8 m_num2dEffects; - bool m_freeCol; + bool m_bOwnsColModel; - CBaseModelInfo(ModeInfoType type); + CBaseModelInfo(ModelInfoType type); virtual ~CBaseModelInfo() {} virtual void Shutdown(void); virtual void DeleteRwObject(void) = 0; @@ -48,8 +48,8 @@ public: } char *GetName(void) { return m_name; } void SetName(const char *name) { strncpy(m_name, name, 24); } - void SetColModel(CColModel *col, bool free = false){ - m_colModel = col; m_freeCol = free; } + void SetColModel(CColModel *col, bool owns = false){ + m_colModel = col; m_bOwnsColModel = owns; } CColModel *GetColModel(void) { return m_colModel; } void DeleteCollisionModel(void); void ClearTexDictionary(void) { m_txdSlot = -1; } diff --git a/src/modelinfo/ClumpModelInfo.h b/src/modelinfo/ClumpModelInfo.h index 100aa30b..c37a468a 100644 --- a/src/modelinfo/ClumpModelInfo.h +++ b/src/modelinfo/ClumpModelInfo.h @@ -32,7 +32,7 @@ public: RpClump *m_clump; CClumpModelInfo(void) : CBaseModelInfo(MITYPE_CLUMP) {} - CClumpModelInfo(ModeInfoType id) : CBaseModelInfo(id) {} + CClumpModelInfo(ModelInfoType id) : CBaseModelInfo(id) {} ~CClumpModelInfo() {} void DeleteRwObject(void); RwObject *CreateInstance(void); diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp index c1ae692f..812a8749 100644 --- a/src/modelinfo/ModelInfo.cpp +++ b/src/modelinfo/ModelInfo.cpp @@ -200,6 +200,20 @@ CModelInfo::GetModelInfo(const char *name, int *id) return nil; } +#ifdef MIAMI +CBaseModelInfo* +CModelInfo::GetModelInfo(const char *name, int minIndex, int maxIndex) +{ + CBaseModelInfo *modelinfo; + for(int i = minIndex; i <= maxIndex; i++){ + modelinfo = CModelInfo::ms_modelInfoPtrs[i]; + if(modelinfo && !CGeneral::faststricmp(modelinfo->GetName(), name)) + return modelinfo; + } + return nil; +} +#endif + bool CModelInfo::IsBoatModel(int32 id) { @@ -214,6 +228,7 @@ CModelInfo::IsBikeModel(int32 id) ((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BIKE; } +#ifndef MIAMI void CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level) { @@ -230,6 +245,7 @@ CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level) } } } +#endif void CModelInfo::ConstructMloClumps() diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h index 65cfa4e7..dadc8f8b 100644 --- a/src/modelinfo/ModelInfo.h +++ b/src/modelinfo/ModelInfo.h @@ -42,6 +42,9 @@ public: static CBaseModelInfo *GetModelInfo(int id){ return ms_modelInfoPtrs[id]; } +#ifdef MIAMI + static CBaseModelInfo *GetModelInfo(const char *name, int minIndex, int maxIndex); +#endif static bool IsBoatModel(int32 id); static bool IsBikeModel(int32 id); diff --git a/src/modelinfo/SimpleModelInfo.cpp b/src/modelinfo/SimpleModelInfo.cpp index 2fb2adeb..424fb0e5 100644 --- a/src/modelinfo/SimpleModelInfo.cpp +++ b/src/modelinfo/SimpleModelInfo.cpp @@ -94,6 +94,12 @@ CSimpleModelInfo::IncreaseAlpha(void) m_alpha += 0x10; } +float +CSimpleModelInfo::GetLodDistance(int i) +{ + return m_lodDistances[i] * TheCamera.LODDistMultiplier; +} + float CSimpleModelInfo::GetNearDistance(void) { @@ -119,11 +125,19 @@ CSimpleModelInfo::GetAtomicFromDistance(float dist) if(m_isDamaged) i = m_firstDamaged; for(; i < m_numAtomics; i++) - if(dist < m_lodDistances[i] *TheCamera.LODDistMultiplier) + if(dist < m_lodDistances[i] * TheCamera.LODDistMultiplier) return m_atomics[i]; return nil; } +RpAtomic* +CSimpleModelInfo::GetFirstAtomicFromDistance(float dist) +{ + if(dist < m_lodDistances[0] * TheCamera.LODDistMultiplier) + return m_atomics[0]; + return nil; +} + void CSimpleModelInfo::FindRelatedModel(void) { diff --git a/src/modelinfo/SimpleModelInfo.h b/src/modelinfo/SimpleModelInfo.h index 35d48669..451a9c00 100644 --- a/src/modelinfo/SimpleModelInfo.h +++ b/src/modelinfo/SimpleModelInfo.h @@ -25,7 +25,7 @@ public: uint16 m_noZwrite : 1; CSimpleModelInfo(void) : CBaseModelInfo(MITYPE_SIMPLE) {} - CSimpleModelInfo(ModeInfoType id) : CBaseModelInfo(id) {} + CSimpleModelInfo(ModelInfoType id) : CBaseModelInfo(id) {} ~CSimpleModelInfo() {} void DeleteRwObject(void); RwObject *CreateInstance(void); @@ -36,10 +36,13 @@ public: void IncreaseAlpha(void); void SetAtomic(int n, RpAtomic *atomic); void SetLodDistances(float *dist); - float GetLodDistance(int i) { return m_lodDistances[i]; } + float GetLodDistance(int i); float GetNearDistance(void); float GetLargestLodDistance(void); RpAtomic *GetAtomicFromDistance(float dist); +#ifdef MIAMI + RpAtomic *GetFirstAtomicFromDistance(float dist); // inline +#endif void FindRelatedModel(void); void SetupBigBuilding(void); diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 2dee0397..3c25d827 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -187,8 +187,10 @@ CCivilianPed::CivilianAI(void) void CCivilianPed::ProcessControl(void) { +#ifndef MIAMI if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) return; +#endif CPed::ProcessControl(); diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp index 8bfd807f..7140af76 100644 --- a/src/peds/CopPed.cpp +++ b/src/peds/CopPed.cpp @@ -565,8 +565,10 @@ CCopPed::CopAI(void) void CCopPed::ProcessControl(void) { +#ifndef MIAMI if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) return; +#endif CPed::ProcessControl(); if (bWasPostponed) @@ -715,7 +717,7 @@ CCopPed::ProcessControl(void) return; bool dontShoot = false; - if (GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(this)) { + if (GetIsOnScreenAndNotCulled()) { if (((CTimer::GetFrameCounter() + m_randomSeed) & 0x1F) == 17) { CEntity *foundBuilding = nil; CColPoint foundCol; diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp index 7229ed3f..e85cfc8b 100644 --- a/src/peds/EmergencyPed.cpp +++ b/src/peds/EmergencyPed.cpp @@ -44,8 +44,10 @@ CEmergencyPed::InRange(CPed *victim) void CEmergencyPed::ProcessControl(void) { +#ifndef MIAMI if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) return; +#endif CPed::ProcessControl(); if (bWasPostponed) diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index b1609094..6f584af2 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -9397,8 +9397,10 @@ CPed::ProcessControl(void) CColPoint foundCol; CEntity *foundEnt = nil; +#ifndef MIAMI if (m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) return; +#endif int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump()); if (!bFadeOut) { diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 8dd9d23d..496d8999 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -858,6 +858,7 @@ CPopulation::AddPedInCar(CVehicle* car) void CPopulation::MoveCarsAndPedsOutOfAbandonedZones() { +#ifndef MIAMI eLevelName level; int zone; int frame = CTimer::GetFrameCounter() & 7; @@ -940,6 +941,7 @@ CPopulation::MoveCarsAndPedsOutOfAbandonedZones() } } } +#endif } void diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index cb2cb5b7..40b07558 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -332,6 +332,7 @@ enum Visbility int32 CRenderer::SetupEntityVisibility(CEntity *ent) { +#ifndef MIAMI CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex); CTimeModelInfo *ti; int32 other; @@ -406,7 +407,7 @@ CRenderer::SetupEntityVisibility(CEntity *ent) RpAtomic *a = mi->GetAtomicFromDistance(dist); if(a){ - mi->m_isDamaged = 0; + mi->m_isDamaged = false; if(ent->m_rwObject == nil) ent->CreateRwObject(); assert(ent->m_rwObject); @@ -477,11 +478,164 @@ CRenderer::SetupEntityVisibility(CEntity *ent) ent->bDistanceFade = true; return VIS_OFFSCREEN; // Why this? } +#else + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex); + CTimeModelInfo *ti; + int32 other; + float dist; + + bool request = true; + if(mi->m_type == MITYPE_TIME){ + ti = (CTimeModelInfo*)mi; + other = ti->GetOtherTimeModel(); + if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){ + // don't fade in, or between time objects + if(CANTIMECULL) + ti->m_alpha = 255; + }else{ + // Hide if possible + if(CANTIMECULL) + return VIS_INVISIBLE; + // can't cull, so we'll try to draw this one, but don't request + // it since what we really want is the other one. + request = false; + } + }else{ +// TODO(MIAMI): weapon + if(mi->m_type != MITYPE_SIMPLE){ + if(FindPlayerVehicle() == ent && + TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){ + // Player's vehicle in first person mode + if(TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_FORWARD || + ent->GetModelIndex() == MI_RHINO || + ent->GetModelIndex() == MI_COACH || + TheCamera.m_bInATunnelAndABigVehicle){ + ent->bNoBrightHeadLights = true; + }else{ + m_pFirstPersonVehicle = (CVehicle*)ent; + ent->bNoBrightHeadLights = false; + } + return VIS_OFFSCREEN; + }else{ + // All sorts of Clumps + if(ent->m_rwObject == nil || !ent->bIsVisible) + return VIS_INVISIBLE; +// TODO(MIAMI): occlusion + if(!ent->GetIsOnScreen()) + return VIS_OFFSCREEN; + if(ent->bDrawLast){ + dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude(); + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = false; + return VIS_INVISIBLE; + }else + return VIS_VISIBLE; + } + return VIS_INVISIBLE; + } +// TODO(MIAMI): this is different + if(ent->IsObject() && + ((CObject*)ent)->ObjectCreatedBy == TEMP_OBJECT){ + if(ent->m_rwObject == nil || !ent->bIsVisible) + return VIS_INVISIBLE; + return ent->GetIsOnScreen() ? VIS_VISIBLE : VIS_OFFSCREEN; + } + } + + // Simple ModelInfo + +// TODO(MIAMI): area + + dist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude(); + + if(LOD_DISTANCE < dist && dist < mi->GetLargestLodDistance() + FADE_DISTANCE) + dist += mi->GetLargestLodDistance() - 300.0f; + + if(ent->IsObject() && ent->bRenderDamaged) + mi->m_isDamaged = true; + + RpAtomic *a = mi->GetAtomicFromDistance(dist); + if(a){ + mi->m_isDamaged = false; + if(ent->m_rwObject == nil) + ent->CreateRwObject(); + assert(ent->m_rwObject); + RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject; + // Make sure our atomic uses the right geometry and not + // that of an atomic for another draw distance. + if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) + RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) + mi->IncreaseAlpha(); + if(ent->m_rwObject == nil || !ent->bIsVisible) + return VIS_INVISIBLE; + + if(!ent->GetIsOnScreen()){ + mi->m_alpha = 255; + return VIS_OFFSCREEN; + } + + if(mi->m_alpha != 255){ + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = true; + return VIS_INVISIBLE; + } + + if(mi->m_drawLast || ent->bDrawLast){ + if(CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist)){ + ent->bDistanceFade = false; + return VIS_INVISIBLE; + } + } + return VIS_VISIBLE; + } + + // Object is not loaded, figure out what to do + + if(mi->m_noFade){ + mi->m_isDamaged = false; + // request model + if(dist - STREAM_DISTANCE < mi->GetLargestLodDistance() && request) + return VIS_STREAMME; + return VIS_INVISIBLE; + } + + // We might be fading + + a = mi->GetAtomicFromDistance(dist - FADE_DISTANCE); + mi->m_isDamaged = false; + if(a == nil){ + // request model + if(dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance() && request) + return VIS_STREAMME; + return VIS_INVISIBLE; + } + + if(ent->m_rwObject == nil) + ent->CreateRwObject(); + assert(ent->m_rwObject); + RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject; + if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) + RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) + mi->IncreaseAlpha(); + if(ent->m_rwObject == nil || !ent->bIsVisible) + return VIS_INVISIBLE; + +// TODO(MIAMI): occlusion + if(!ent->GetIsOnScreen()){ + mi->m_alpha = 255; + return VIS_OFFSCREEN; + }else{ + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = true; + return VIS_OFFSCREEN; // Why this? + } +#endif } int32 CRenderer::SetupBigBuildingVisibility(CEntity *ent) { +#ifndef MIAMI CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex); CTimeModelInfo *ti; int32 other; @@ -492,10 +646,10 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) // Hide objects not in time range if possible if(CANTIMECULL) if(!CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())) - return 0; + return VIS_INVISIBLE; // Draw like normal }else if(mi->m_type == MITYPE_VEHICLE) - return ent->IsVisible(); + return ent->IsVisible() ? VIS_VISIBLE : VIS_INVISIBLE; float dist = (ms_vecCameraPosition-ent->GetPosition()).Magnitude(); CSimpleModelInfo *nonLOD = mi->GetRelatedModel(); @@ -507,7 +661,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) // No non-LOD or non-LOD is completely visible. if(nonLOD == nil || nonLOD->GetRwObject() && nonLOD->m_alpha == 255) - return 0; + return VIS_INVISIBLE; // But if it is a time object, we'd rather draw the wrong // non-LOD than the right LOD. @@ -515,7 +669,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) ti = (CTimeModelInfo*)nonLOD; other = ti->GetOtherTimeModel(); if(other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject()) - return 0; + return VIS_INVISIBLE; } } @@ -531,18 +685,18 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) if(!ent->IsVisibleComplex()) - return 0; + return VIS_INVISIBLE; if(mi->m_drawLast){ CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); - ent->bDistanceFade = 0; - return 0; + ent->bDistanceFade = false; + return VIS_INVISIBLE; } - return 1; + return VIS_VISIBLE; } if(mi->m_noFade){ ent->DeleteRwObject(); - return 0; + return VIS_INVISIBLE; } @@ -550,7 +704,7 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) a = mi->GetAtomicFromDistance(dist - FADE_DISTANCE); if(a == nil){ ent->DeleteRwObject(); - return 0; + return VIS_INVISIBLE; } // Fade... @@ -562,7 +716,122 @@ CRenderer::SetupBigBuildingVisibility(CEntity *ent) RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) if(ent->IsVisibleComplex()) CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); - return 0; + return VIS_INVISIBLE; +#else + CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex); + CTimeModelInfo *ti; + int32 other; + +// TODO(MIAMI): area + + bool request = true; + if(mi->m_type == MITYPE_TIME){ + ti = (CTimeModelInfo*)mi; + other = ti->GetOtherTimeModel(); + if(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){ + // don't fade in, or between time objects + if(CANTIMECULL) + ti->m_alpha = 255; + }else{ + // Hide if possible + if(CANTIMECULL){ + ent->DeleteRwObject(); + return VIS_INVISIBLE; + } + // can't cull, so we'll try to draw this one, but don't request + // it since what we really want is the other one. + request = false; + } + }else if(mi->m_type == MITYPE_VEHICLE) + return ent->IsVisible() ? VIS_VISIBLE : VIS_INVISIBLE; + + float dist = (ms_vecCameraPosition-ent->GetPosition()).Magnitude(); + CSimpleModelInfo *nonLOD = mi->GetRelatedModel(); + + // Find out whether to draw below near distance. + // This is only the case if there is a non-LOD which is either not + // loaded or not completely faded in yet. + if(dist < mi->GetNearDistance() && dist < LOD_DISTANCE){ + // No non-LOD or non-LOD is completely visible. + if(nonLOD == nil || + nonLOD->GetRwObject() && nonLOD->m_alpha == 255) + return VIS_INVISIBLE; + + // But if it is a time object, we'd rather draw the wrong + // non-LOD than the right LOD. + if(nonLOD->m_type == MITYPE_TIME){ + ti = (CTimeModelInfo*)nonLOD; + other = ti->GetOtherTimeModel(); + if(other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject()) + return VIS_INVISIBLE; + } + } + + RpAtomic *a = mi->GetFirstAtomicFromDistance(dist); + if(a){ + if(ent->m_rwObject == nil) + ent->CreateRwObject(); + assert(ent->m_rwObject); + RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject; + + // Make sure our atomic uses the right geometry and not + // that of an atomic for another draw distance. + if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) + RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) + mi->IncreaseAlpha(); +// TODO(MIAMI): occlusion + if(!ent->IsVisibleComplex()){ + mi->m_alpha = 255; + return VIS_INVISIBLE; + } + + if(mi->m_alpha != 255){ + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = true; + return VIS_INVISIBLE; + } + + if(mi->m_drawLast){ + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = false; + return VIS_INVISIBLE; + } + return VIS_VISIBLE; + } + + if(mi->m_noFade){ + ent->DeleteRwObject(); + return VIS_INVISIBLE; + } + + + // get faded atomic + a = mi->GetFirstAtomicFromDistance(dist - FADE_DISTANCE); + if(a == nil){ + if(ent->bStreamBIGBuilding && dist-STREAM_DISTANCE < mi->GetLodDistance(0) && request){ + return ent->GetIsOnScreen() ? VIS_STREAMME : VIS_INVISIBLE; + }else{ + ent->DeleteRwObject(); + return VIS_INVISIBLE; + } + } + + // Fade... + if(ent->m_rwObject == nil) + ent->CreateRwObject(); + assert(ent->m_rwObject); + RpAtomic *rwobj = (RpAtomic*)ent->m_rwObject; + if(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj)) + RpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?) + mi->IncreaseAlpha(); +// TODO(MIAMI): occlusion + if(ent->IsVisibleComplex()){ + CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist); + ent->bDistanceFade = true; + }else + mi->m_alpha = 255; + return VIS_INVISIBLE; +#endif } void @@ -709,7 +978,11 @@ CRenderer::ScanWorld(void) } ScanSectorPoly(poly, 3, ScanSectorList); +#ifndef MIAMI ScanBigBuildingList(CWorld::GetBigBuildingList(CCollision::ms_collisionInMemory)); +#else + ScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel)); +#endif ScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_NONE)); } } @@ -954,11 +1227,27 @@ CRenderer::ScanBigBuildingList(CPtrList &list) CPtrNode *node; CEntity *ent; +#ifndef MIAMI for(node = list.first; node; node = node->next){ ent = (CEntity*)node->item; - if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == 1) + if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == VIS_VISIBLE) ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; } +#else + // TODO(MIAMI): some flags and such + for(node = list.first; node; node = node->next){ + ent = (CEntity*)node->item; + switch(SetupBigBuildingVisibility(ent)){ + case VIS_VISIBLE: + ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; + break; + case VIS_STREAMME: + if(!CStreaming::ms_disableStreaming) + CStreaming::RequestModel(ent->GetModelIndex(), 0); + break; + } + } +#endif } void @@ -978,7 +1267,9 @@ CRenderer::ScanSectorList(CPtrList *lists) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); +#ifdef GTA_ZONECULL if(IsEntityCullZoneVisible(ent)) +#endif switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; @@ -1001,12 +1292,14 @@ CRenderer::ScanSectorList(CPtrList *lists) CStreaming::RequestModel(ent->GetModelIndex(), 0); break; } +#ifdef GTA_ZONECULL else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){ if(!CStreaming::ms_disableStreaming) if(SetupEntityVisibility(ent) == VIS_STREAMME) if(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10) CStreaming::RequestModel(ent->GetModelIndex(), 0); } +#endif } } } @@ -1028,7 +1321,9 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); +#ifdef GTA_ZONECULL if(IsEntityCullZoneVisible(ent)) +#endif switch(SetupEntityVisibility(ent)){ case VIS_VISIBLE: ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent; @@ -1053,11 +1348,13 @@ CRenderer::ScanSectorList_Priority(CPtrList *lists) } break; } +#ifdef GTA_ZONECULL else if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){ if(!CStreaming::ms_disableStreaming) if(SetupEntityVisibility(ent) == VIS_STREAMME) CStreaming::RequestModel(ent->GetModelIndex(), 0); } +#endif } } } @@ -1110,7 +1407,10 @@ CRenderer::ScanSectorList_RequestModels(CPtrList *lists) if(ent->m_scanCode == CWorld::GetCurrentScanCode()) continue; // already seen ent->m_scanCode = CWorld::GetCurrentScanCode(); - if(IsEntityCullZoneVisible(ent) && ShouldModelBeStreamed(ent)) +#ifdef GTA_ZONECULL + if(IsEntityCullZoneVisible(ent)) +#endif + if(ShouldModelBeStreamed(ent)) CStreaming::RequestModel(ent->GetModelIndex(), 0); } } @@ -1155,6 +1455,7 @@ CRenderer::ShouldModelBeStreamed(CEntity *ent) return dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance(); } +#ifdef GTA_ZONECULL bool CRenderer::IsEntityCullZoneVisible(CEntity *ent) { @@ -1197,6 +1498,7 @@ CRenderer::IsVehicleCullZoneVisible(CEntity *ent) return !(v->m_pCurGroundEntity && v->m_pCurGroundEntity->bZoneCulled2); return true; } +#endif void CRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset) diff --git a/src/render/Renderer.h b/src/render/Renderer.h index 362741e3..e28995c3 100644 --- a/src/render/Renderer.h +++ b/src/render/Renderer.h @@ -64,8 +64,10 @@ public: static void SortBIGBuildingsForSectorList(CPtrList *list); static bool ShouldModelBeStreamed(CEntity *ent); +#ifdef GTA_ZONECULL static bool IsEntityCullZoneVisible(CEntity *ent); static bool IsVehicleCullZoneVisible(CEntity *ent); +#endif static void RemoveVehiclePedLights(CEntity *ent, bool reset); }; diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index bb074042..c22a060c 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -543,11 +543,13 @@ RestoreForStartLoad() ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().z); CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); CStreaming::RemoveUnusedBuildings(CGame::currLevel); +#ifndef MIAMI CCollision::SortOutCollisionAfterLoad(); CStreaming::RequestBigBuildings(CGame::currLevel); CStreaming::LoadAllRequestedModels(false); CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); CGame::TidyUpMemory(true, false); +#endif if (CloseFile(file)) { return true; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 9db60da0..602eb589 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -229,9 +229,11 @@ CAutomobile::ProcessControl(void) colModel = GetColModel(); bWarnedPeds = false; +#ifndef MIAMI // skip if the collision isn't for the current level if(colModel->level > LEVEL_NONE && colModel->level != CCollision::ms_collisionInMemory) return; +#endif // Improve grip of vehicles in certain cases bool strongGrip1 = false; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 1f80c43e..66aa7d4d 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -109,8 +109,10 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos) void CBoat::ProcessControl(void) { +#ifndef MIAMI if(m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory) return; +#endif bool onLand = m_fDamageImpulse > 0.0f && m_vecDamageNormal.z > 0.1f;