//============================================================================= // Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. // // File: RenderManager.cpp // // Description: Implementation for RenderManager class. // // History: + Stolen and cleaned up from Penthouse -- Darwin Chau // + Stolen from Darwin and Tailored // to RenderFlow from GameFlow -- Devin [4/17/2002] // + Stolen from Devin and Tailored // to RenderManager from RenderFlow -- Devin [4/17/2002] // //============================================================================= //If you want only level 1, do this. //#define MS8_PANIC //I got yer synchronous loads right here! //#define LOAD_SYNC //======================================== // System Includes //======================================== #include #include #include #include //======================================== // Project Includes //======================================== #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include
#include
#include #include #include #include #include #include #ifdef DEBUGWATCH #include #include #endif //****************************************************************************** // // Global Data, Local Data, Local Classes // //****************************************************************************** // // Static pointer to instance of this singleton. // RenderManager* RenderManager::mspInstance = NULL; #ifndef RAD_RELEASE char gZoneLoadID[256]; const char* ZONE_STRING = "%s : %d"; void LoadTag( const char* zone, int& index ) { char name[ 9 ] = ""; strncpy( name, &zone[4], strlen( zone ) - 8 ); name[8] = '\0'; sprintf( gZoneLoadID, ZONE_STRING, name, index ); SetMemoryIdentification( gZoneLoadID ); index++; } void FinishedZone() { strcat( gZoneLoadID, " - FINSIHED" ); SetMemoryIdentification( gZoneLoadID ); } #endif // // Static list of items to load per level, per mission // static char* sLevelLoadList[] = { "ART\\L1_TERRA.P3D", //L1 "ART\\L2_TERRA.P3D", //L2 "ART\\L3_TERRA.p3d", //L3 "ART\\L4_TERRA.P3D", //L4 "ART\\L5_TERRA.P3D", //L5 "ART\\L6_TERRA.P3D", //L6 "ART\\L7_TERRA.P3D", //L7 "ART\\B00.P3D", //SUPER_SPRINT "ART\\B01.P3D", //SUPER_SPRINT "ART\\B02.P3D", //SUPER_SPRINT "ART\\B03.P3D", //SUPER_SPRINT "ART\\B04.P3D", //SUPER_SPRINT "ART\\B05.P3D", //SUPER_SPRINT "ART\\B06.P3D", //SUPER_SPRINT "ART\\B07.P3D" //SUPER_SPRINT }; static char* sIntersectLoadList[] = { "ART\\L1_INTER.P3D", //L1 "ART\\L2_INTER.P3D", //L2 "ART\\L3_INTER.p3d", //L3 "ART\\L4_INTER.P3D", //L4 "ART\\L5_INTER.P3D", //L5 "ART\\L6_INTER.P3D", //L6 "ART\\L7_INTER.P3D", //L7 "", "", "", "", "", "", "", "" }; static char* sMissionLoadList[] = { "everground.p3d" //L1M1 }; bool ENABLE_MOTION_BLUR = true; float BLUR_SCALE = 0.9f; float BLUR_START = 33.33f; float MAX_BLUR = 0.15f; // Blur alpha will never go over this level // Blur gradient is slope in the linear blur equation // So max blur will be reached at 15 fps, scaled linearly from 30 fps float BLUR_GRADIENT = MAX_BLUR / ( 66.66f - 33.33f ); // Vlad wants the PS2 to use a minimum amount of fixed blurring all the time #ifdef RAD_PS2 //float MIN_PS2_BLUR = 0.075f; float MIN_PS2_BLUR = 0.15f; float MIN_PS2_BLUR_CHEAT = 0.8f; #endif #if defined( RAD_PS2) || defined( RAD_XBOX ) #define USE_BLUR #endif //****************************************************************************** // // Public Member Functions : RenderManager Interface // //****************************************************************************** //============================================================================== // RenderManager::DumpAllLoadedData //============================================================================== // // Description: . // // Parameters: // // Return: None. // // Constraints: // //============================================================================== void RenderManager::DumpAllLoadedData ( ) { mpRenderLayers[RenderEnums::LevelSlot]->Freeze(); // mpRenderLayers[RenderEnums::LevelSlot]->NullifyGuts(); mpRenderLayers[RenderEnums::LevelSlot]->Kill(); // this can release some objects, need to do it now or // we'll die next time a frame is rendered since heaps have probably been // blown away LensFlareDSG::ReadFrameBufferIntensities(); // // This will cause a lag when dumping level data GC Lot Check Violation // FlushDelList(); // // Clean Reinit // // mpRenderLayers[RenderEnums::LevelSlot]->DoPreStaticLoad(); // mpRenderLayers[RenderEnums::InteriorSlot]->DoPreStaticLoad(); // // Kill the Default Pure3D inventory; // this is where the first level load went // p3d::inventory->RemoveSectionElements(tName::MakeUID("Default")); p3d::inventory->DeleteSection(tName::MakeUID("Default")); AllWrappers::GetInstance()->ClearGlobalEntities(); AllWrappers::GetInstance()->mLoader( AllWrappers::msGeometry ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msStaticEntity ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msStaticPhys ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msTreeDSG ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msFenceEntity ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msIntersectDSG ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msAnimCollEntity).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msAnimEntity ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msDynaPhys ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msInstStatPhys ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msInstStatEntity).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msLocator ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msWorldSphere ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msRoadSegment ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msPathSegment ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msBillboard ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msLensFlare ).ModRegdListener( this, RenderEnums::BogusUserData ); AllWrappers::GetInstance()->mLoader( AllWrappers::msAnimDynaPhys ).ModRegdListener( this, RenderEnums::BogusUserData ); } //============================================================================== // RenderManager::LoadAllNeededData //============================================================================== // // Description: Loads data unique to a Level,Mission tuple. // // Parameters: Level and Mission specifier // // Return: Bool: was the layer that got wiped out marked as dead? // // Constraints: // //============================================================================== void RenderManager::SetLoadData ( RenderEnums::LayerEnum isLayer, RenderEnums::LevelEnum isLevel, RenderEnums::MissionEnum isMission ) { //Valid Layer? rAssert( isLayer < RenderEnums::numLayers ); rAssert( isLevel < RenderEnums::MAX_LEVEL ); rAssert( isMission < RenderEnums::numMissions ); msLayer = isLayer; msLevel = isLevel; msMission = isMission; mCurWorldLayer = msLayer; } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::RedirectChunks( int ChunkDestinationMask ) { AllWrappers::GetInstance()->mLoader( AllWrappers::msStaticEntity ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::StaticEntityGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msStaticPhys ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::StaticPhysGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msTreeDSG ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::TreeDSGGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msFenceEntity ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::FenceGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msGeometry ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::IgnoreGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msIntersectDSG ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::IntersectGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msAnimCollEntity).ModRegdListener( this, ChunkDestinationMask | RenderEnums::AnimCollGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msAnimEntity ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::AnimGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msDynaPhys ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::DynaPhysGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msInstStatPhys ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::StaticPhysGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msInstStatEntity).ModRegdListener( this, ChunkDestinationMask | RenderEnums::StaticEntityGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msLocator ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::LocatorGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msWorldSphere ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::WorldSphereGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msRoadSegment ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::RoadSegmentGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msPathSegment ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::PathSegmentGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msBillboard ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::StaticEntityGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msLensFlare ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::StaticEntityGuts ); AllWrappers::GetInstance()->mLoader( AllWrappers::msAnimDynaPhys ).ModRegdListener( this, ChunkDestinationMask | RenderEnums::DynaPhysGuts ); } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::FlushDelList() { radTime64 start = radTimeGetMicroseconds64(); while(mEntityDeletionList.mUseSize) { mEntityDeletionList[0]->Release(); mEntityDeletionList.Remove(0); } radTime64 end = radTimeGetMicroseconds64(); unsigned deleteTime = (unsigned) (end - start); rTunePrintf("RenderManager::FlushDelList Delete time: %.3fms\n", deleteTime / 1000.0F); } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::MunchDelList(unsigned us) { radTime64 start = radTimeGetMicroseconds64(); while(mEntityDeletionList.mUseSize) { mEntityDeletionList[0]->Release(); mEntityDeletionList.Remove(0); radTime64 elapsed = radTimeGetMicroseconds64() - start; if(elapsed > us) { break; // too spikey, delete some more next frame } } } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== bool RenderManager::LoadAllNeededData ( ) { mbLoadZonesDumped = false; mDoneInitialLoad = false; //MS7 //static int sFuckinCompilerWontShutUp = isLayer; switch( msLayer ) { case RenderEnums::LevelSlot: if( mpRenderLayers[msLayer]->IsDead() ) { #if 0 int TheEnum = RenderEnums::LevelSlot | RenderEnums::GeometryGuts; rDebugPrintf( "Wrapper Init: Layer:%X GutsID: %X\n", (TheEnum & RenderEnums::LayerOnlyMask), (TheEnum & RenderEnums::GutsOnlyMask)); #endif mpRenderLayers[msLayer]->DoPreStaticLoad(); HeapMgr()->PushHeap (GMA_LEVEL_ZONE); (dynamic_cast(&AllWrappers::GetInstance()->mLoader( AllWrappers::msGeometry )))->SetOptimize(true); RedirectChunks(RenderEnums::LevelSlot); AllWrappers::GetInstance()->mLoader( AllWrappers::msWorldSphere ).ModRegdListener( this, RenderEnums::LevelSlot | RenderEnums::GlobalWSphereGuts ); ////////////////////////////////////////////////////////////////////////// // SRR2_LOAD_ASYNC ////////////////////////////////////////////////////////////////////////// tName LevelName(sLevelLoadList[msLevel]); mpRenderLayers[RenderEnums::LevelSlot]->DoPreDynaLoad(LevelName); AllWrappers::GetInstance()->mLoader( AllWrappers::msBillboard ).ModRegdListener( this, RenderEnums::IgnoreGuts ); #ifndef RAD_RELEASE static int loadTag1 = 0; LoadTag( sLevelLoadList[msLevel], loadTag1 ); #endif #ifdef LOAD_SYNC HeapMgr()->DumpHeapStats( true ); GetLoadingManager()->LoadSync( FILEHANDLER_PURE3D, sLevelLoadList[msLevel], GMA_LEVEL_ZONE ); HeapMgr()->DumpHeapStats( true ); #else GetLoadingManager()->AddRequest( FILEHANDLER_PURE3D, sLevelLoadList[msLevel], GMA_LEVEL_ZONE, this, &msLayer); #endif ////////////////////////////////////////////////////////////////////////// //intesects rolled into zone files //GetLoadingManager()->AddRequest( FILEHANDLER_PURE3D, sIntersectLoadList[msLevel], GMA_LEVEL_ZONE, sLevelLoadList[msLevel]); msLayer &= ~RenderEnums::AllIntersectLoadingComplete; msLayer |= RenderEnums::AllRenderLoadingComplete; // GetLoadingManager()->ProcessRequests( this, &msLayer ); //mbDynaLoading = true; mbDynaLoading = false; mbDrivingTooFastLoad = false; HeapMgr()->PopHeap (GMA_LEVEL_ZONE); #ifdef LOAD_SYNC GetLoadingManager()->AddCallback( this, &msLayer ); #endif return true; } break; default: break; } return false; } //============================================================================== // RenderManager::ContextUpdate //============================================================================== // // Description: Called (responsibly) from managing Context // // Parameters: None. // // Return: None. // // Constraints: // //============================================================================== void RenderManager::ContextUpdate( unsigned int iElapsedTime ) { // On the PS2, use a minimum blur all the time #ifdef RAD_PS2 ApplyPS2Blur(); #endif GetIntersectManager()->mbSameFrame = false; #ifdef DEBUGWATCH unsigned int t0 = radTimeGetMicroseconds(); #endif BEGIN_PROFILE( "Rendering" ); BEGIN_PROFILE( "Swap Buffers" ); p3d::context->SwapBuffers(); END_PROFILE( "Swap Buffers" ); #if defined( RAD_XBOX ) || defined ( RAD_GAMECUBE ) LoadingManager* lm = GetLoadingManager(); PresentationManager* pm = GetPresentationManager(); p3d::display->SetForceVSync( lm && !lm->IsLoading(), !(pm && pm->GetFMVPlayer()->IsPlaying())); #endif #ifdef LOAD_SYNC FlushDelList(); #else MunchDelList(2000); // work on the DelList for up to 2000 microseconds, then return #endif BEGIN_PROFILE( "Lens Flare Frame Buffer Read" ); LensFlareDSG::ReadFrameBufferIntensities(); END_PROFILE( "Lens Flare Frame Buffer Read" ); #ifdef DEBUGWATCH mDebugSwapTime = radTimeGetMicroseconds()-t0; t0 = radTimeGetMicroseconds(); #endif if( mMood.mTransition >= 0.0f ) { TransitionMoodLighting( iElapsedTime ); } BEGIN_PROFILE( "Begin Frame" ); p3d::context->BeginFrame(); END_PROFILE( "Begin Frame" ); // Render Stuff; call your Render shots, Tex. for( int i=RenderEnums::numLayers-1; i>-1; i-- ) { #ifdef DEBUGINFO_ENABLED // We need to render the debug info just before we render the GUI layer //since rendering that layer changes the world matrix. if( i == RenderEnums::GUI ) { DEBUGINFO_RENDER(); } #endif if( mpRenderLayers[i]->IsRenderReady() ) { BEGIN_PROFILE( "Layers" ); mpRenderLayers[i]->Render(); END_PROFILE( "Layers" ); } } END_PROFILE( "Rendering" ); #ifdef DEBUGWATCH t0 = radTimeGetMicroseconds(); #endif #ifndef FINAL BEGIN_PROFILE( "Dump Stats" ); HeapMgr()->DumpHeapStats(); HeapMgr()->DumpArtStats(); END_PROFILE( "Dump Stats" ); #endif RENDER_PROFILER(); //MEMTRACK_RENDER(); //HEAPSTACKS_RENDER(); SOUNDDEBUG_RENDER(); #ifdef USE_BLUR ((pddiExtFramebufferEffects*)p3d::pddi->GetExtension( PDDI_EXT_FRAMEBUFFER_EFFECTS ))->EnableMotionBlur( mEnableMotionBlur || ENABLE_MOTION_BLUR, mBlurAlpha, BLUR_SCALE, false ); ((pddiExtFramebufferEffects*)p3d::pddi->GetExtension( PDDI_EXT_FRAMEBUFFER_EFFECTS ))->SetQuality( pddiExtFramebufferEffects::Smallest ); if ( mEnableMotionBlur || ENABLE_MOTION_BLUR ) { ((pddiExtFramebufferEffects*)p3d::pddi->GetExtension( PDDI_EXT_FRAMEBUFFER_EFFECTS ))->RenderMotionBlur(); } #endif if ( CommandLineOptions::Get( CLO_DEMO_TEST ) || GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_DEMO_TEST ) ) { char buffy[32]; sprintf( buffy, "Demo Count: %d", GetGame()->GetDemoCount() ); const int LEFT = 35; const int TOP = 45; const pddiColour WHITE(128,128,128); p3d::pddi->DrawString( buffy, LEFT , 80 + TOP, WHITE ); static unsigned int time = 0; time = GetGame()->GetTime(); time += iElapsedTime; unsigned int hours = time / 3600000; unsigned int deltaTime = time % 3600000; unsigned int minutes = deltaTime / 60000; deltaTime = deltaTime % 60000; unsigned int seconds = deltaTime / 1000; deltaTime = deltaTime % 1000; sprintf( buffy, "Time: %d:%d:%d.%d", hours, minutes, seconds, deltaTime ); p3d::pddi->DrawString( buffy, LEFT , 100 + TOP, WHITE ); if ( GetGameplayManager() ) { sprintf( buffy, "Level %d", GetGameplayManager()->GetCurrentLevelIndex() ); p3d::pddi->DrawString( buffy, LEFT , 120 + TOP, WHITE ); } GetGame()->SetTime( time ); } p3d::context->EndFrame( false ); #ifdef DEBUGWATCH mDebugRenderTime = radTimeGetMicroseconds()-t0; if(mDebugDumpAllZones) { mDebugDumpAllZones = false; mpLayer( RenderEnums::LevelSlot )->DumpAllDynaLoads(1, mEntityDeletionList ); GetWorldPhysicsManager()->FreeAllCollisionAreaIndicies(); FlushDelList(); ::radMemoryMonitorSuspend(); } #endif //unsigned int time1 = radTimeGetMicroseconds(); //rReleasePrintf( "Render Loop: %d micro's\n", time1-time0 ); } //****************************************************************************** // // Public Member Functions : Instance Interface // //****************************************************************************** //============================================================================== // RenderManager::CreateInstance //============================================================================== // // Description: Create the RenderManager controller if needed. // // Parameters: None. // // Return: Pointer to the created RenderManager controller. // // Constraints: This is a singleton so only one instance is allowed. // //============================================================================== RenderManager* RenderManager::CreateInstance() { MEMTRACK_PUSH_GROUP( "RenderManager" ); rAssert( mspInstance == NULL ); mspInstance = new(GMA_PERSISTENT) RenderManager(); MEMTRACK_POP_GROUP( "RenderManager" ); return mspInstance; } //============================================================================== // RenderManager::GetInstance //============================================================================== // // Description: Get the RenderManager controller if exists. // // Parameters: None. // // Return: Pointer to the created RenderManager controller. // // Constraints: This is a singleton so only one instance is allowed. // //============================================================================== RenderManager* RenderManager::GetInstance() { rAssert( mspInstance != NULL ); return mspInstance; } //============================================================================== // RenderManager::DestroyInstance //============================================================================== // // Description: Destroy the RenderManager controller. // // Parameters: None. // // Return: None. // //============================================================================== void RenderManager::DestroyInstance() { // // Make sure this doesn't get called twice. // rAssert( mspInstance != NULL ); delete mspInstance; mspInstance = NULL; } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== WorldScene* RenderManager::pWorldScene() { // return ((WorldRenderLayer*)mpRenderLayers[RenderEnums::LevelSlot])->pWorldScene(); return ((WorldRenderLayer*)mpRenderLayers[mCurWorldLayer])->pWorldScene(); } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== WorldRenderLayer* RenderManager::pWorldRenderLayer() { return ((WorldRenderLayer*)mpRenderLayers[mCurWorldLayer]); } //======================================================================== // RenderManager::OnChunkLoaded //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::OnChunkLoaded ( tEntity* ipEntity, int iUserData, unsigned iChunkID ) { if( (iUserData == RenderEnums::BogusUserData) || (iUserData == (int)(RenderEnums::IgnoreGuts)) )// ignore bogus idata -go to hell, compiler! With your trite, meaningless warnings return; rAssert( ipEntity != NULL ); rAssert( (iUserData & RenderEnums::LayerOnlyMask) < RenderEnums::numLayers && (iUserData & RenderEnums::LayerOnlyMask) > -1 ); /*rDebugPrintf( "Chunk: Layer:%X GutsID: %X\n", (iUserData & RenderEnums::LayerOnlyMask), (iUserData & RenderEnums::GutsOnlyMask));*/ IntersectDSG* pIDSG = NULL; // if( (iUserData & RenderEnums::CompletionOnlyMask) == RenderEnums::AllRenderLoadingComplete ) // { // return; // } switch( iChunkID ) { case SRR2::ChunkID::LENS_FLARE_DSG: case SRR2::ChunkID::INSTA_ENTITY_DSG: case SRR2::ChunkID::ENTITY_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::StaticEntityGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((StaticEntityDSG*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::INSTA_STATIC_PHYS_DSG: case SRR2::ChunkID::STATIC_PHYS_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::StaticPhysGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((StaticPhysDSG*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::DYNA_PHYS_DSG: case SRR2::ChunkID::INSTA_ANIM_DYNA_PHYS_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::DynaPhysGuts: { int renderLayer = iUserData & RenderEnums::LayerOnlyMask; DynaPhysDSG* pDynaPhys = static_cast< DynaPhysDSG* >( ipEntity ); rAssert( dynamic_cast< DynaPhysDSG* >( ipEntity ) != NULL ); mpRenderLayers[ renderLayer ]->AddGuts( pDynaPhys ); pDynaPhys->SetRenderLayer( static_cast< RenderEnums::LayerEnum >( renderLayer ) ); } break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::TREE_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::TreeDSGGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((SpatialTree*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::FENCE_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::FenceGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((FenceEntityDSG*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::INTERSECT_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::IntersectGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((IntersectDSG*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::ANIM_DSG: switch ( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::AnimGuts: { // mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((AnimEntityDSG*)ipEntity); int renderLayer = iUserData & RenderEnums::LayerOnlyMask; AnimEntityDSG* pAnimDSG = static_cast< AnimEntityDSG* >( ipEntity ); rAssert( dynamic_cast< AnimEntityDSG* >( ipEntity ) != NULL ); mpRenderLayers[ renderLayer ]->AddGuts( pAnimDSG ); pAnimDSG->SetRenderLayer( static_cast< RenderEnums::LayerEnum > (renderLayer) ); } break; default: rAssert( false ); break; } break; case SRR2::ChunkID::ANIM_COLL_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::AnimCollGuts: { // mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((AnimCollisionEntityDSG*)ipEntity); int renderLayer = iUserData & RenderEnums::LayerOnlyMask; AnimCollisionEntityDSG* pAnimCollDSG = static_cast< AnimCollisionEntityDSG* >( ipEntity ); rAssert( dynamic_cast< AnimCollisionEntityDSG* >( ipEntity ) != NULL ); mpRenderLayers[ renderLayer ]->AddGuts( pAnimCollDSG ); pAnimCollDSG->SetRenderLayer( static_cast< RenderEnums::LayerEnum > (renderLayer) ); break; } default: //Unexpected GutsEnum rAssert(false); break; } break; case Pure3D::Mesh::MESH: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::GeometryGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((tGeometry*)ipEntity); break; case RenderEnums::DrawableGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((tDrawable*)ipEntity); break; case RenderEnums::IntersectGuts: pIDSG = GetDSGFactory()->CreateIntersectDSG( (tGeometry*)ipEntity ); mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts( pIDSG ); break; case RenderEnums::IgnoreGuts: break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::LOCATOR: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::LocatorGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((TriggerVolume*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::ROAD_SEGMENT: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::RoadSegmentGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((RoadSegment*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::PED_PATH_SEGMENT: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::PathSegmentGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((PathSegment*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; case SRR2::ChunkID::WORLD_SPHERE_DSG: switch( iUserData & RenderEnums::GutsOnlyMask ) { case RenderEnums::GlobalWSphereGuts: ((WorldSphereDSG*)ipEntity)->Activate(); case RenderEnums::WorldSphereGuts: mpRenderLayers[iUserData & RenderEnums::LayerOnlyMask]->AddGuts((WorldSphereDSG*)ipEntity); break; default: //Unexpected GutsEnum rAssert(false); break; } break; default: //Unexpected ChunkID rAssert(false); break; } } //======================================================================== // RenderManager::OnProcessRequestsComplete( void* pUserData ); //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::OnProcessRequestsComplete( void* pUserData ) { rAssert( pUserData != NULL ); // // When done queued loading, Ignore any new geo's loaded through the // LoaderWrappers // //AllWrappers::GetInstance()->mLoader( AllWrappers::msGeometry ).ModRegdListener( this, RenderEnums::LevelSlot | RenderEnums::IgnoreGuts ); GetEventManager()->TriggerEvent( EVENT_DYNAMIC_ZONE_LOAD_ENDED ); #ifndef RAD_RELEASE FinishedZone(); #endif //*** ////////////////////////////////////////////////////////////////////////// // Dynamic Loading ////////////////////////////////////////////////////////////////////////// if( ((*(int*)pUserData) & RenderEnums::CompletionOnlyMask) == RenderEnums::DynamicLoadComplete ) { tName GiveItAFuckinName; static char spSomeDamnFile[128]; int i = ((*(int*)pUserData) & RenderEnums::ZoneMask) >> RenderEnums::ZoneShift; mpRenderLayers[(*(int*)pUserData) & RenderEnums::LayerOnlyMask]->DoPostDynaLoad(); bool alreadyLoaded=true; if( iGetNumLoadZones() && (msLayer & RenderEnums::LevelSlot) ) { rReleasePrintf("Zone Loading Ended: %s\n",mpZEL->GetLoadZone(i)); //HeapMgr()->DumpHeapStats(true); tUID tempUID = tName::MakeUID(mpZEL->GetLoadZone(i)); GetEventManager()->TriggerEvent( EVENT_NAMED_DYNAMIC_ZONE_LOAD_ENDED, &tempUID ); if( mbLoadZonesDumped ) { mbLoadZonesDumped = false; // // Do no further loading; it's been "cancelled". // This is to cover the load resumption logged as bug 10575. // Essentially, the dump would get queued before a zone finished loading // (through a mission reset). Then, on completion, it would dump the load // (with the doPost above) and start loading all the other zones listed in the ZEL. // mZELs.mUseSize = 0; i = mpZEL->GetNumLoadZones(); rReleasePrintf("***All LoadZones Dumped; ZEL's cancelled.***\n"); } for(i;iGetNumLoadZones()&&alreadyLoaded; ) { i++; if(iGetNumLoadZones()) { HeapMgr()->PushHeap (GMA_TEMP); GiveItAFuckinName.SetText(mpZEL->GetLoadZone(i)); HeapMgr()->PopHeap ( GMA_TEMP); alreadyLoaded= ! mpRenderLayers[RenderEnums::LevelSlot]->DoPreDynaLoad(GiveItAFuckinName); } } if(iGetNumLoadZones()) { sprintf(spSomeDamnFile,"ART\\%s",mpZEL->GetLoadZone(i)); (*(int*)pUserData) &= ~RenderEnums::CompletionOnlyMask; (*(int*)pUserData) |= RenderEnums::DynamicLoadComplete; (*(int*)pUserData) &= ~RenderEnums::ZoneMask; (*(int*)pUserData) |= i<DumpHeapStats( true ); GetLoadingManager()->LoadSync( FILEHANDLER_PURE3D, spSomeDamnFile, GMA_LEVEL_ZONE, mpZEL->GetLoadZone(i) ); HeapMgr()->DumpHeapStats( true ); GetLoadingManager()->AddCallback( this, (int*)pUserData ); #else GetLoadingManager()->AddRequest( FILEHANDLER_PURE3D, spSomeDamnFile, GMA_LEVEL_ZONE, mpZEL->GetLoadZone(i), NULL, this, (int*)pUserData); #endif } else { if(mpZEL->IsInteriorLoad()) { InteriorLoadedEventData data; data.interiorName = mpZEL->GetNameObject(); data.sectionName = mpZEL->GetInteriorSection(); data.first = mbFirstDynamicZone; GetEventManager()->TriggerEvent( EVENT_INTERIOR_LOADED, reinterpret_cast( &data ) ); } if( mbFirstDynamicZone ) { mbFirstDynamicZone = false; GetEventManager()->TriggerEvent( EVENT_FIRST_DYNAMIC_ZONE_END ); } /* ////////////////////////////////////////////////////////////////////////// // Find a Zone to load ////////////////////////////////////////////////////////////////////////// BEGIN_PROFILE( "Find Load Zone" ); i=-1; for(i;iGetNumLoadZones()&&alreadyLoaded; ) { i++; if(iGetNumLoadZones()) { HeapMgr()->PushHeap (GMA_TEMP); GiveItAFuckinName.SetText(mpZEL->GetLoadZone(i)); HeapMgr()->PopHeap ( GMA_TEMP ); alreadyLoaded= ! mpRenderLayers[RenderEnums::LevelSlot]->DoPreDynaLoad(GiveItAFuckinName); } } END_PROFILE( "Find Load Zone" ); ////////////////////////////////////////////////////////////////////////// // Zone Loading ////////////////////////////////////////////////////////////////////////// if(iGetNumLoadZones()) { sprintf(spSomeDamnFile,"ART\\%s",mpZEL->GetLoadZone(i)); msLayer &= ~RenderEnums::CompletionOnlyMask; msLayer |= RenderEnums::DynamicLoadComplete; msLayer &= ~RenderEnums::ZoneMask; msLayer |= i<DumpHeapStats( true ); GetLoadingManager()->LoadSync( FILEHANDLER_PURE3D, spSomeDamnFile, GMA_LEVEL_ZONE, mpZEL->GetLoadZone(i) ); HeapMgr()->DumpHeapStats( true ); #else GetLoadingManager()->AddRequest( FILEHANDLER_PURE3D, spSomeDamnFile, GMA_LEVEL_ZONE, mpZEL->GetLoadZone(i), NULL, this, &msLayer); #endif END_PROFILE( "Add Requests Int" ); rReleasePrintf("ZoneLoadingStart--===--%s--===--\n", spSomeDamnFile); mbDynaLoading = true; #ifdef LOAD_SYNC GetLoadingManager()->AddCallback( this, &msLayer ); #endif return; } */ // // If other loading sets were queued while loading // if( mZELs.mUseSize != 0 ) { mpZEL = mZELs[0]; mZELs.RemoveKeepOrder(0); (*(int*)pUserData) &= ~RenderEnums::ZoneMask; (*(int*)pUserData) |= 0<TriggerEvent( EVENT_ALL_DYNAMIC_ZONE_END ); rReleasePrintf("ZoneLoadingEnded Verified\n"); mbDynaLoading = false; AllWrappers::GetInstance()->mLoader( AllWrappers::msBillboard ).ModRegdListener( this, RenderEnums::IgnoreGuts ); } } } } } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::DoPostLevelLoad() { ////////////////////////////////////////////////////////////////////////// // PreDynamic Loading ////////////////////////////////////////////////////////////////////////// // if( ((*(int*)pUserData) & RenderEnums::CompletionOnlyMask) == RenderEnums::AllRenderLoadingComplete ) { // mpRenderLayers[(*(int*)pUserData) & RenderEnums::LayerOnlyMask]->DoPostStaticLoad(); //// mpRenderLayers[(*(int*)pUserData) & RenderEnums::LayerOnlyMask]->Resurrect(); //mpRenderLayers[(*(int*)pUserData) & RenderEnums::LayerOnlyMask]->FreezeCorpse(); mpRenderLayers[RenderEnums::LevelSlot]->DoPostDynaLoad(); mpRenderLayers[RenderEnums::LevelSlot]->FreezeCorpse(); // // When done queued loading, Ignore any new geo's loaded through the // LoaderWrappers // AllWrappers::GetInstance()->mLoader( AllWrappers::msGeometry ).ModRegdListener( this, RenderEnums::LevelSlot | RenderEnums::IgnoreGuts ); mDoneInitialLoad = true; mbDynaLoading = false; AllWrappers::GetInstance()->mLoader( AllWrappers::msBillboard ).ModRegdListener( this, RenderEnums::IgnoreGuts ); } } bool RenderManager::DoneInitialLoad() { return mDoneInitialLoad; } //============================================================================= // RenderManager::mpLayer //============================================================================= // Description: Comment // // Parameters: ( RenderEnums::LayerEnum isLayer ) // // Return: RenderLayer // //============================================================================= RenderLayer* RenderManager::mpLayer( RenderEnums::LayerEnum isLayer ) { //Valid Layer? rAssert( isLayer < RenderEnums::numLayers ); // // Walk (talk?) like an egyptian // return mpRenderLayers[isLayer]; } //============================================================================= // RenderManager::FreezeAllLayers //============================================================================= // Description: Comment // // Parameters: () // // Return: void // //============================================================================= void RenderManager::FreezeAllLayers() { for( unsigned int i = 0; i < RenderEnums::numLayers; i++ ) { mpRenderLayers[ i ]->Freeze(); } } /*============================================================================= Description: Freeze the layers, except for the presentation layer. The trick here however is that the layer remembers it's previous state because some layers could have already been frozen (such as interior/exterior layers) and we don't want them to thaw after the presentation. So match this call will a call to ThawFromPresentation(). =============================================================================*/ void RenderManager::FreezeForPresentation( void ) { for( unsigned int i = 0; i < RenderEnums::numLayers; ++i ) { if( i != RenderEnums::GUI ) // exclude GUI layer { mpRenderLayers[ i ]->Chill(); } } } /*============================================================================= Description: Thaws all layers. The idea is that we'll freeze all the layers for playing an FMV, then thaw the presentation layer. After the movie we need to thaw all the layers and then freeze the presentation layer. I'm not sure this will work so well for cases where we had a layer frozen for another reason before the movie started. =============================================================================*/ void RenderManager::ThawFromPresentation( void ) { for( unsigned int i = 0; i < RenderEnums::numLayers; ++i ) { if( i != RenderEnums::GUI ) // exclude GUI layer { mpRenderLayers[ i ]->Warm(); } } } //======================================================================== // RenderManager:: //======================================================================== // // Description: // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::HandleEvent( EventEnum id, void* pEventData ) { BEGIN_PROFILE( "RenderManager HandleEvent" ); switch(id) { case EVENT_MISSION_RESET: { #if defined( RAD_XBOX ) || defined( RAD_WIN32 ) // XBox seems to like this syntax better. bool jumpStage = reinterpret_cast( pEventData ); #else bool jumpStage = (bool)( pEventData ); #endif if( jumpStage ) { ResetMoodLighting( true ); } } break; case EVENT_LOCATOR + LocatorEvent::LIGHT_CHANGE: { EventLocator* pLocator = static_cast( pEventData ); rAssert( pLocator ); tColour lightMod( pLocator->GetData() ); if ( pLocator->GetPlayerEntered() ) { SetLightMod( lightMod ); ++(mMood.mVolumeCount); } else { --(mMood.mVolumeCount); if( mMood.mVolumeCount == 0 ) { ResetMoodLighting(); } } if( mMood.mVolumeCount < 0 ) { mMood.mVolumeCount = 0; } } break; case EVENT_LOCATOR+LocatorEvent::OCCLUSION_ZONE: { OcclusionLocator* pOccLocator = ((OcclusionLocator*)pEventData); SpatialTreeIter& rTreeWalker = pWorldScene()->mStaticTreeWalker; SphereSP occSphere; rmt::Sphere sphere; BoxPts occBox; rmt::Box3D box; if(pOccLocator->GetPlayerEntered()) { if(mbInVsibilityVolume) { rTreeWalker.AndTree(0x00000000); mbIgnoreVisibilityClear = true; } mbInVsibilityVolume = true; tMark curMark = SpatialTreeIter::msFilterInvisible; int numOccluders = pOccLocator->GetNumOccTriggers(); int stopCondition = pOccLocator->GetNumTriggers(); for(int i=1; inumOccluders) curMark = SpatialTreeIter::msFilterVisible; else curMark = SpatialTreeIter::msFilterInvisible; if(pOccLocator->GetTriggerVolume(i)->GetType() == TriggerVolume::SPHERE ) { pOccLocator->GetTriggerVolume(i)->GetBoundingSphere(&sphere); occSphere.SetTo( sphere.centre, sphere.radius ); rTreeWalker.MarkSubTrees(occSphere, curMark ); } else { pOccLocator->GetTriggerVolume(i)->GetBoundingBox(&box); occBox.mBounds.mMin.SetTo(box.low); occBox.mBounds.mMax.SetTo(box.high); rTreeWalker.MarkSubTrees(occBox, curMark ); } } } else { if(mbIgnoreVisibilityClear) { mbIgnoreVisibilityClear = false; } else { mbInVsibilityVolume = false; rTreeWalker.AndTree(0x00000000); } } } break; case EVENT_ALL_DYNAMIC_ZONES_DUMPED: { if(mbDynaLoading) mbLoadZonesDumped = true; break; } case EVENT_FIRST_DYNAMIC_ZONE_START: mbFirstDynamicZone = true; case EVENT_LOCATOR+LocatorEvent::DYNAMIC_ZONE: { ZoneEventLocator* pZEL = (ZoneEventLocator*)pEventData; //HeapMgr()->DumpHeapStats(true); /* if(!(pZEL->GetPlayerEntered())) { int j; for( j=pZEL->GetNumLWSActivates()-1; j>-1; j-- ) { pWorldRenderLayer()->DeactivateWS(tName::MakeUID(pZEL->GetLWSActivates(j))); } for( j=pZEL->GetNumLWSDeactivates()-1; j>-1; j-- ) { pWorldRenderLayer()->ActivateWS(tName::MakeUID(pZEL->GetLWSDeactivates(j))); } }*/ if(pZEL->GetPlayerEntered()||mbDrivingTooFastLoad) { if(pZEL->IsInteriorLoad()) { InteriorLoadedEventData data; data.interiorName = pZEL->GetUID(); data.sectionName = tEntity::MakeUID(pZEL->GetInteriorSection()); data.first = mbFirstDynamicZone; GetEventManager()->TriggerEvent( EVENT_INTERIOR_LOAD_START, reinterpret_cast( &data ) ); } int j; for( j=pZEL->GetNumLWSActivates()-1; j>-1; j-- ) { pWorldRenderLayer()->ActivateWS(tName::MakeUID(pZEL->GetLWSActivates(j))); } for( j=pZEL->GetNumLWSDeactivates()-1; j>-1; j-- ) { pWorldRenderLayer()->DeactivateWS(tName::MakeUID(pZEL->GetLWSDeactivates(j))); } if(pZEL->GetNumLoadZones()==0 && pZEL->GetNumDumpZones()==0) { END_PROFILE( "RenderManager HandleEvent" ); rReleasePrintf("Nothin to Load, skipping zone\n"); return; } //If we're already Loading if(mbDynaLoading == true) { rReleasePrintf("Driving TOO FAST: Adding to queue.\n"); mZELs.Add((ZoneEventLocator*&)pEventData); END_PROFILE( "RenderManager HandleEvent" ); return; } mbDrivingTooFastLoad = false; mpZEL = (ZoneEventLocator*)pEventData; //If we're not currently loading static char spSomeDamnFile[128]; int i; bool alreadyLoaded = true; tName GiveItAFuckinName; rReleasePrintf("Encountered Dynamic Zone:\n"); for(i=0; iGetNumDumpZones(); i++) { rReleasePrintf("Dump: %s\n",mpZEL->GetDumpZone(i)); } for(i=0; iGetNumLoadZones(); i++) { rReleasePrintf("Load: %s\n",mpZEL->GetLoadZone(i)); } ////////////////////////////////////////////////////////////////////////// // Zone Dumping ////////////////////////////////////////////////////////////////////////// BEGIN_PROFILE( "Zone/Int Dump" ); BEGIN_PROFILE( "Dump Zones" ); for(i=0; iGetNumDumpZones(); i++) { HeapMgr()->PushHeap (GMA_TEMP); GiveItAFuckinName.SetText(mpZEL->GetDumpZone(i)); HeapMgr()->PopHeap ( GMA_TEMP); //mpRenderLayers[msLayer & RenderEnums::LayerOnlyMask]->DumpDynaLoad(GiveItAFuckinName); mpRenderLayers[RenderEnums::LevelSlot]->DumpDynaLoad(GiveItAFuckinName, mEntityDeletionList); } BEGIN_PROFILE( "Trigger IntDump Event" ); if(mpZEL->IsInteriorDump()) { GetEventManager()->TriggerEvent( EVENT_INTERIOR_DUMPED ); } END_PROFILE( "Trigger IntDump Event" ); END_PROFILE( "Dump Zones" ); //MunchDelList(50); END_PROFILE( "Zone/Int Dump" ); ////////////////////////////////////////////////////////////////////////// // Find a Zone to load ////////////////////////////////////////////////////////////////////////// BEGIN_PROFILE( "Find Load Zone" ); i=-1; for(i;iGetNumLoadZones()&&alreadyLoaded; ) { i++; if(iGetNumLoadZones()) { HeapMgr()->PushHeap (GMA_TEMP); GiveItAFuckinName.SetText(mpZEL->GetLoadZone(i)); HeapMgr()->PopHeap ( GMA_TEMP ); alreadyLoaded= ! mpRenderLayers[RenderEnums::LevelSlot]->DoPreDynaLoad(GiveItAFuckinName); } } END_PROFILE( "Find Load Zone" ); ////////////////////////////////////////////////////////////////////////// // Zone Loading ////////////////////////////////////////////////////////////////////////// if(iGetNumLoadZones()) { sprintf(spSomeDamnFile,"ART\\%s",mpZEL->GetLoadZone(i)); msLayer &= ~RenderEnums::CompletionOnlyMask; msLayer |= RenderEnums::DynamicLoadComplete; msLayer &= ~RenderEnums::ZoneMask; msLayer |= i<DumpHeapStats( true ); GetLoadingManager()->LoadSync( FILEHANDLER_PURE3D, spSomeDamnFile, GMA_LEVEL_ZONE, mpZEL->GetLoadZone(i) ); HeapMgr()->DumpHeapStats( true ); #else GetLoadingManager()->AddRequest( FILEHANDLER_PURE3D, spSomeDamnFile, GMA_LEVEL_ZONE, mpZEL->GetLoadZone(i), NULL, this, &msLayer); #endif END_PROFILE( "Add Requests Int" ); rReleasePrintf("ZoneLoadingStart--===--%s--===--\n", spSomeDamnFile); mbDynaLoading = true; #ifdef LOAD_SYNC GetLoadingManager()->AddCallback( this, &msLayer ); #endif } else { rReleasePrintf("Nothing to load in that Zone, checking for others...\n"); if( mZELs.mUseSize != 0 ) { mpZEL = mZELs[0]; mZELs.RemoveKeepOrder(0); msLayer &= ~RenderEnums::ZoneMask; msLayer |= i<TriggerEvent( EVENT_ALL_DYNAMIC_ZONE_END ); rReleasePrintf("ZoneLoadingEnded Verified\n"); mbDynaLoading = false; AllWrappers::GetInstance()->mLoader( AllWrappers::msBillboard ).ModRegdListener( this, RenderEnums::IgnoreGuts ); } } } } break; default: break; } END_PROFILE( "RenderManager HandleEvent" ); } //****************************************************************************** // // Private Member Functions // //****************************************************************************** //======================================================================== // RenderManager::InitLayers //======================================================================== // // Description: Initialize all Layers // // Parameters: None. // // Return: None. // // Constraints: None. // //======================================================================== void RenderManager::InitLayers() { MEMTRACK_PUSH_GROUP( "RenderManager" ); HeapMgr()->PushHeap (GMA_PERSISTENT); for( int i=RenderEnums::numLayers-1; i>-1; i-- ) { switch(i) { case RenderEnums::LevelSlot: mpRenderLayers[i] = new WorldRenderLayer(); break; case RenderEnums::GUI: mpRenderLayers[i] = new FrontEndRenderLayer(); mpRenderLayers[i]->DoAllSetups(); break; case RenderEnums::PresentationSlot: mpRenderLayers[ i ] = new RenderLayer(); mpRenderLayers[ i ]->SetBeginView( false ); mpRenderLayers[ i ]->DoAllSetups(); break; default: mpRenderLayers[i] = new RenderLayer(); mpRenderLayers[i]->DoAllSetups(); break; } mpRenderLayers[i]->SetUpViewCam(); } HeapMgr()->PopHeap (GMA_PERSISTENT); MEMTRACK_POP_GROUP( "RenderManager" ); } void RenderManager::InitLevel() { /* for( unsigned int i = 0; i < RenderEnums::numLayers-1; i++ ) { mpRenderLayers[ i ]->DoPostStaticLoad(); } mpRenderLayers[ RenderEnums::LevelSlot ]->Resurrect(); for( unsigned int i = 0; i < GetGameplayManager()->GetNumPlayers(); i++ ) { mpRenderLayers[RenderEnums::LevelSlot]->AddGuts((tDrawable*)(GetAvatarManager( )->GetAvatarForPlayer( i )->GetVehicle() ) ); mpRenderLayers[RenderEnums::LevelSlot]->AddGuts((tDrawable*)(GetAvatarManager( )->GetAvatarForPlayer( i )->GetCharacter()->GetDrawablePose() ) ); } //Find and attach a light to the view //MS7, this should go somewhere else. tLight* sun = p3d::find("sun"); rAssert( sun ); for( unsigned int i = 0; i < mpRenderLayers[RenderEnums::LevelSlot]->GetNumViews(); i++ ) { mpRenderLayers[RenderEnums::LevelSlot]->pView( i )->AddLight( sun ); } //Get the clouds too! mClouds = p3d::find("CloudController"); rAssert( mClouds ); */ } void RenderManager::SetLevelLayerLights( tLightGroup* SunGroup ) { HeapMgr()->PushHeap( GMA_LEVEL_OTHER ); if ( mMood.mOriginals != 0 ) { delete [] mMood.mOriginals; mMood.mOriginals = 0; } mMood.mSunGroup = SunGroup; if ( SunGroup != NULL ) { // Mood lighting is enabled, set the new parameters rAssert( SunGroup ); mMood.mVolumeCount = 0; mMood.mTransition = -1.0f; mMood.mSrcModulus.Set( 0xff, 0xff, 0xff ); mMood.mDstModulus.Set( 0xff, 0xff, 0xff ); mMood.mOriginals = new tColour[ SunGroup->GetNumLights() ]; rAssert( mMood.mOriginals ); for( int j = 0; j < SunGroup->GetNumLights(); ++j ) { mMood.mOriginals[ j ] = SunGroup->GetLight( j )->GetColour(); } RenderLayer* rl = mpLayer( RenderEnums::LevelSlot ); rAssert( rl ); for( unsigned int i = 0; i < rl->GetNumViews(); ++i ) { for(int j = 0; j < SunGroup->GetNumLights(); ++j ) { rl->pView( i )->AddLight( SunGroup->GetLight(j) ); } } } HeapMgr()->PopHeap( GMA_LEVEL_OTHER ); } void RenderManager::ClearLevelLayerLights() { delete [] mMood.mOriginals; mMood.mOriginals = 0; mMood.mSunGroup = 0; } //============================================================================== // RenderManager::RenderManager //============================================================================== // // Description: Constructor. // // Parameters: None. // // Return: N/A. // //==============================================================================// RenderManager::RenderManager() : //MS7: Cary mClouds( NULL ), #ifdef DEBUGWATCH mDebugDumpAllZones( false ), #endif mEnableMotionBlur( false ), mBlurAlpha( 0 ) { mEntityDeletionList.Allocate(5000); #ifdef DEBUGWATCH radDbgWatchAddUnsignedInt( &mDebugRenderTime, "Debug Render All Layers micros", "RenderManager", NULL, NULL ); radDbgWatchAddUnsignedInt( &mDebugSwapTime, "Debug Render Swap micros", "RenderManager", NULL, NULL ); radDbgWatchAddBoolean( &mDebugDumpAllZones, "Dump All Zones", "RenderManager", NULL, NULL ); #ifdef RAD_PS2 radDbgWatchAddFloat( &MIN_PS2_BLUR, "Minimum PS2 motion blur", "RenderManager", NULL, NULL ); #endif // radDbgWatchAddFloat( &BLUR_ALPHA, "Blur Alpha", "RenderManager", NULL, NULL, 0.0f, 1.0f ); radDbgWatchAddFloat( &BLUR_SCALE, "Blur Scale", "RenderManager", NULL, NULL, 0.0f, 1.0f ); radDbgWatchAddFloat( &MAX_BLUR, "Blur max", "RenderManager", NULL, NULL, 0.0f, 1.0f ); radDbgWatchAddBoolean( &ENABLE_MOTION_BLUR, "Enable Blur", "RenderManager" ); // radDbgWatchAddFloat( &BLUR_ALPHA, "Blur Alpha", "RenderManager", NULL, NULL, 0.0f, 1.0f ); radDbgWatchAddFloat( &BLUR_SCALE, "Blur Scale", "RenderManager", NULL, NULL, 0.0f, 1.0f ); #endif InitLayers(); mDoneInitialLoad = false; mbLoadZonesDumped = false; mbIgnoreVisibilityClear = false; mbInVsibilityVolume = false; mZELs.Allocate(10); } //============================================================================== // RenderManager::~RenderManager //============================================================================== // // Description: Destructor. // // Parameters: None. // // Return: N/A. // //==============================================================================// RenderManager::~RenderManager() { #ifdef DEBUGWATCH radDbgWatchDelete(&mDebugRenderTime); radDbgWatchDelete(&mDebugSwapTime); // radDbgWatchDelete(&BLUR_ALPHA); radDbgWatchDelete(&BLUR_SCALE); radDbgWatchDelete(&MAX_BLUR); radDbgWatchDelete(&ENABLE_MOTION_BLUR ); #endif } RenderManager::MoodLighting::MoodLighting() : mSunGroup( 0 ), mSrcModulus( 0xffffffff ), mDstModulus( 0xffffffff ), mOriginals( 0 ), mTransition( -1.0f ) { } RenderManager::MoodLighting::~MoodLighting() { delete mOriginals; mOriginals = 0; mSunGroup = 0; } tColour RenderManager::MoodLighting::CalculateModulus( void ) { int red = rmt::Clamp( mSrcModulus.Red() - int( ( mSrcModulus.Red() - mDstModulus.Red() ) * mTransition ), 0, 0xFF ); int green = rmt::Clamp( mSrcModulus.Green() - int( ( mSrcModulus.Green() - mDstModulus.Green() ) * mTransition ), 0, 0xFF ); int blue = rmt::Clamp( mSrcModulus.Blue() - int( ( mSrcModulus.Blue() - mDstModulus.Blue() ) * mTransition ), 0, 0xFF ); int alpha = rmt::Clamp( mSrcModulus.Alpha() - int( ( mSrcModulus.Alpha() - mDstModulus.Alpha() ) * mTransition ), 0, 0xFF ); return tColour( red, green, blue, alpha ); } void RenderManager::SetLightMod( const tColour& LightMod ) { if( LightMod.c != mMood.mDstModulus.c ) { mMood.mSrcModulus = mMood.CalculateModulus(); mMood.mDstModulus = LightMod; mMood.mTransition = 0.0f; } } void RenderManager::TransitionMoodLighting( unsigned int ElapsedTime ) { // Check for no mood lighting (supersprint doesnt have any) if ( mMood.mSunGroup == NULL ) return; const float TIME_RATIO = ( 1.0f / 1000.0f ) / 1.0f; // Transition over 1 second. float deltaTransition = (float)ElapsedTime * TIME_RATIO; mMood.mTransition += deltaTransition; if( mMood.mTransition > 1.0f ) { mMood.mTransition = 1.0f; } tColour curMod = mMood.CalculateModulus(); for( int i = 0; i < mMood.mSunGroup->GetNumLights(); ++i ) { tLight* l = mMood.mSunGroup->GetLight( i ); if( curMod.c == 0xffffffff ) { l->SetColour( mMood.mOriginals[ i ] ); } else { int red = ( ( mMood.mOriginals[ i ].Red() * curMod.Red() ) + 0x80 ) >> 8; int green = ( ( mMood.mOriginals[ i ].Green() * curMod.Green() ) + 0x80 ) >> 8; int blue = ( ( mMood.mOriginals[ i ].Blue() * curMod.Blue() ) + 0x80 ) >> 8; int alpha = ( ( mMood.mOriginals[ i ].Alpha() * curMod.Alpha() ) + 0x80 ) >> 8; l->SetColour( tColour( red, green, blue ) ); } } if( mMood.mTransition == 1.0f ) { mMood.mSrcModulus = mMood.mDstModulus; mMood.mTransition = -1.0f; } } void RenderManager::ResetMoodLighting( bool Immediate ) { if ( mMood.mSunGroup == NULL ) return; mMood.mVolumeCount = 0; if( Immediate ) { mMood.mTransition = -1.0f; mMood.mSrcModulus.c = 0xFFFFFFFF; mMood.mDstModulus.c = 0xFFFFFFFF; for( int i = 0; i < mMood.mSunGroup->GetNumLights(); ++i ) { tLight* l = mMood.mSunGroup->GetLight( i ); l->SetColour( mMood.mOriginals[ i ] ); } } else { mMood.mSrcModulus = mMood.CalculateModulus(); mMood.mDstModulus.c = 0xFFFFFFFF; mMood.mTransition = 0.0f; } } #ifdef RAD_PS2 // Bump up the blur to a minimum level on the PS2 void RenderManager::ApplyPS2Blur() { // We only want blur in game, not in the frontend. if ( mpRenderLayers[ RenderEnums::LevelSlot ]->IsRenderReady() ) { float blurThreshold = GetCheatInputSystem()->IsCheatEnabled( CHEAT_ID_TRIPPY ) ? MIN_PS2_BLUR_CHEAT : MIN_PS2_BLUR; if ( mBlurAlpha < blurThreshold ) { mBlurAlpha = blurThreshold; } } else { mBlurAlpha = 0; } } #endif void RenderManager::AdjustBlurByFrameRate( unsigned int elapsedTime ) { // Lets adjust the blur effect if the framerate gets too bad // Blurring effect is scaled linearly // it kicks in at BLUR_START // So y = m(x - x1) + y1 // blur_alpha = blur_gradient ( elapsedtime - blur_start ) float blur; // We only want blur in game, not in the frontend. if ( mpRenderLayers[ RenderEnums::LevelSlot ]->IsRenderReady() ) { float alpha = BLUR_GRADIENT * ( elapsedTime - BLUR_START ); blur = rmt::Clamp( alpha, 0.0f, MAX_BLUR ); } else { blur = 0; } if ( blur > mBlurAlpha ) mBlurAlpha = blur; } //============================================================================== // AvgTimeCounter::AvgTimeCounter //============================================================================== // // Description: Ctor. // // Intialize the AvgTimeCounter class with idealized initial values // i.e. first run it will report an average milliseconds elapsed of 17 // // Return: N/A. // //==============================================================================// RenderManager::AvgTimeCounter::AvgTimeCounter(): mCurrentArrayIndex( 0 ) { const unsigned int IDEAL_ELAPSED_TIME = 17; // Division replaced by a bit shift if array is a power of two right? mElapsedTimeCount.Allocate( ELAPSED_TIME_ARRAY_SIZE ); for ( int i = 0 ; i < ELAPSED_TIME_ARRAY_SIZE ; i++ ) { // Fill with the idealized time, i.e. a rock solid 60fps. mElapsedTimeCount.Add( IDEAL_ELAPSED_TIME ); } mElapsedTimeSum = IDEAL_ELAPSED_TIME * ELAPSED_TIME_ARRAY_SIZE; } //============================================================================== // AvgTimeCounter::Tick //============================================================================== // // Description: Call this function every frame to update the average fps count // // // // // Return: N/A. // //==============================================================================// void RenderManager::AvgTimeCounter::Tick( unsigned int elapsedTime ) { // New frame // Adjust the sum mElapsedTimeSum -= mElapsedTimeCount[ mCurrentArrayIndex ]; mElapsedTimeSum += elapsedTime; // update the mElapsedTimeCount array mElapsedTimeCount[ mCurrentArrayIndex ] = elapsedTime; mCurrentArrayIndex++; // Wrap around to the start of the array if ( mCurrentArrayIndex >= mElapsedTimeCount.mUseSize ) mCurrentArrayIndex = 0; } unsigned int RenderManager::AvgTimeCounter::GetAverageTimePerFrame()const { return mElapsedTimeSum / ELAPSED_TIME_ARRAY_SIZE; }