The-Simpsons-Hit-and-Run/game/code/render/RenderManager/RenderManager.cpp

2061 lines
69 KiB
C++

//=============================================================================
// 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 <constants/chunkids.hpp>
#include <raddebug.hpp>
#include <radtime.hpp>
#include <raddebugwatch.hpp>
//========================================
// Project Includes
//========================================
#include <render/RenderManager/RenderLayer.h>
#include <render/Culling/WorldScene.h>
#include <render/RenderManager/RenderManager.h>
#include <render/RenderManager/WorldRenderLayer.h>
#include <render/RenderManager/FrontEndRenderLayer.h>
#include <render/IntersectManager/IntersectManager.h>
#include <render/Loaders/AllWrappers.h>
#include <render/DSG/IntersectDSG.h>
#include <render/DSG/WorldSphereDSG.h>
#include <render/DSG/DSGFactory.h>
#include <render/DSG/LensFlareDSG.h>
#include <render/DSG/animcollisionentitydsg.h>
#include <render/DSG/animentitydSG.h>
#include <render/Enums/RenderEnums.h>
#include <constants/srrchunks.h>
#include <memory/srrmemory.h>
#include <mission/gameplaymanager.h>
#include <worldsim/avatarmanager.h>
#include <worldsim/avatar.h>
#include <worldsim/redbrick/vehicle.h>
#include <worldsim/redbrick/geometryvehicle.h>
#include <worldsim/character/character.h>
#include <debug/profiler.h>
#include <debug/debuginfo.h>
#include <meta/locatorevents.h>
#include <events/eventdata.h>
#include <events/eventenum.h>
#include <events/eventmanager.h>
#include <meta/zoneeventlocator.h>
#include <meta/occlusionlocator.h>
#include <meta/triggervolume.h>
#include <worldsim/character/charactermanager.h>
#include <main/game.h>
#include <main/platform.h>
#include <memory/srrmemory.h>
#include <sound/soundmanager.h>
#include <presentation/presentation.h>
#include <presentation/fmvplayer/fmvplayer.h>
#include <pddi/pddiext.hpp>
#include <p3d/light.hpp>
#ifdef DEBUGWATCH
#include <radmemorymonitor.hpp>
#include <worldsim/worldphysicsmanager.h>
#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<tGeometryLoader*>(&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( i<mpZEL->GetNumLoadZones() && (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;i<mpZEL->GetNumLoadZones()&&alreadyLoaded; )
{
i++;
if(i<mpZEL->GetNumLoadZones())
{
HeapMgr()->PushHeap (GMA_TEMP);
GiveItAFuckinName.SetText(mpZEL->GetLoadZone(i));
HeapMgr()->PopHeap ( GMA_TEMP);
alreadyLoaded= ! mpRenderLayers[RenderEnums::LevelSlot]->DoPreDynaLoad(GiveItAFuckinName);
}
}
if(i<mpZEL->GetNumLoadZones())
{
sprintf(spSomeDamnFile,"ART\\%s",mpZEL->GetLoadZone(i));
(*(int*)pUserData) &= ~RenderEnums::CompletionOnlyMask;
(*(int*)pUserData) |= RenderEnums::DynamicLoadComplete;
(*(int*)pUserData) &= ~RenderEnums::ZoneMask;
(*(int*)pUserData) |= i<<RenderEnums::ZoneShift;
(*(int*)pUserData) &= ~RenderEnums::LayerOnlyMask;
(*(int*)pUserData) |= RenderEnums::LevelSlot;
RedirectChunks(RenderEnums::LevelSlot);
#ifndef RAD_RELEASE
static int loadTag2 = 0;
LoadTag( spSomeDamnFile, loadTag2 );
#endif
#ifdef LOAD_SYNC
HeapMgr()->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<void*>( &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;i<mpZEL->GetNumLoadZones()&&alreadyLoaded; )
{
i++;
if(i<mpZEL->GetNumLoadZones())
{
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(i<mpZEL->GetNumLoadZones())
{
sprintf(spSomeDamnFile,"ART\\%s",mpZEL->GetLoadZone(i));
msLayer &= ~RenderEnums::CompletionOnlyMask;
msLayer |= RenderEnums::DynamicLoadComplete;
msLayer &= ~RenderEnums::ZoneMask;
msLayer |= i<<RenderEnums::ZoneShift;
msLayer &= ~RenderEnums::LayerOnlyMask;
msLayer |= RenderEnums::LevelSlot;
RedirectChunks(RenderEnums::LevelSlot);
BEGIN_PROFILE( "Add Requests Int" );
#ifndef RAD_RELEASE
static int loadTag3 = 0;
LoadTag( spSomeDamnFile, loadTag3 );
#endif
#ifdef LOAD_SYNC
HeapMgr()->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<<RenderEnums::ZoneShift;
rReleasePrintf("Attemptimg to Load a Driving Too Fast Zone.\n");
mbDynaLoading = false;
mbDrivingTooFastLoad = true;
HandleEvent((EventEnum)(EVENT_LOCATOR+LocatorEvent::DYNAMIC_ZONE), mpZEL);
}
else
{
GetEventManager()->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<bool>( pEventData );
#else
bool jumpStage = (bool)( pEventData );
#endif
if( jumpStage )
{
ResetMoodLighting( true );
}
}
break;
case EVENT_LOCATOR + LocatorEvent::LIGHT_CHANGE:
{
EventLocator* pLocator = static_cast<EventLocator*>( 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; i<stopCondition; i++)
{
if(i>numOccluders)
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<void*>( &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; i<mpZEL->GetNumDumpZones(); i++)
{
rReleasePrintf("Dump: %s\n",mpZEL->GetDumpZone(i));
}
for(i=0; i<mpZEL->GetNumLoadZones(); i++)
{
rReleasePrintf("Load: %s\n",mpZEL->GetLoadZone(i));
}
//////////////////////////////////////////////////////////////////////////
// Zone Dumping
//////////////////////////////////////////////////////////////////////////
BEGIN_PROFILE( "Zone/Int Dump" );
BEGIN_PROFILE( "Dump Zones" );
for(i=0; i<mpZEL->GetNumDumpZones(); 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;i<mpZEL->GetNumLoadZones()&&alreadyLoaded; )
{
i++;
if(i<mpZEL->GetNumLoadZones())
{
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(i<mpZEL->GetNumLoadZones())
{
sprintf(spSomeDamnFile,"ART\\%s",mpZEL->GetLoadZone(i));
msLayer &= ~RenderEnums::CompletionOnlyMask;
msLayer |= RenderEnums::DynamicLoadComplete;
msLayer &= ~RenderEnums::ZoneMask;
msLayer |= i<<RenderEnums::ZoneShift;
msLayer &= ~RenderEnums::LayerOnlyMask;
msLayer |= RenderEnums::LevelSlot;
RedirectChunks(RenderEnums::LevelSlot);
BEGIN_PROFILE( "Add Requests Int" );
#ifndef RAD_RELEASE
static int loadTag4 = 0;
LoadTag( spSomeDamnFile, loadTag4 );
#endif
#ifdef LOAD_SYNC
HeapMgr()->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<<RenderEnums::ZoneShift;
rReleasePrintf("Attemptimg to Load a Driving Too Fast Zone.\n");
mbDynaLoading = false;
mbDrivingTooFastLoad = true;
HandleEvent((EventEnum)(EVENT_LOCATOR+LocatorEvent::DYNAMIC_ZONE), mpZEL);
}
else
{
GetEventManager()->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<tLight>("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<tMultiController>("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;
}