123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- /*
- ===============================================================================
- idCamera
- Base class for cameras
- ===============================================================================
- */
- ABSTRACT_DECLARATION( idEntity, idCamera )
- END_CLASS
- /*
- =====================
- idCamera::Spawn
- =====================
- */
- void idCamera::Spawn( void ) {
- }
- /*
- =====================
- idCamera::GetRenderView
- =====================
- */
- renderView_t *idCamera::GetRenderView() {
- renderView_t *rv = idEntity::GetRenderView();
- GetViewParms( rv );
- return rv;
- }
- /***********************************************************************
- idCameraView
- ***********************************************************************/
- const idEventDef EV_Camera_SetAttachments( "<getattachments>", NULL );
- CLASS_DECLARATION( idCamera, idCameraView )
- EVENT( EV_Activate, idCameraView::Event_Activate )
- EVENT( EV_Camera_SetAttachments, idCameraView::Event_SetAttachments )
- END_CLASS
- /*
- ===============
- idCameraView::idCameraView
- ================
- */
- idCameraView::idCameraView() {
- fov = 90.0f;
- attachedTo = NULL;
- attachedView = NULL;
- }
- /*
- ===============
- idCameraView::Save
- ================
- */
- void idCameraView::Save( idSaveGame *savefile ) const {
- savefile->WriteFloat( fov );
- savefile->WriteObject( attachedTo );
- savefile->WriteObject( attachedView );
- }
- /*
- ===============
- idCameraView::Restore
- ================
- */
- void idCameraView::Restore( idRestoreGame *savefile ) {
- savefile->ReadFloat( fov );
- savefile->ReadObject( reinterpret_cast<idClass *&>( attachedTo ) );
- savefile->ReadObject( reinterpret_cast<idClass *&>( attachedView ) );
- }
- /*
- ===============
- idCameraView::Event_SetAttachments
- ================
- */
- void idCameraView::Event_SetAttachments( ) {
- SetAttachment( &attachedTo, "attachedTo" );
- SetAttachment( &attachedView, "attachedView" );
- }
- /*
- ===============
- idCameraView::Event_Activate
- ================
- */
- void idCameraView::Event_Activate( idEntity *activator ) {
- if (spawnArgs.GetBool("trigger")) {
- if (gameLocal.GetCamera() != this) {
- if ( g_debugCinematic.GetBool() ) {
- gameLocal.Printf( "%d: '%s' start\n", gameLocal.framenum, GetName() );
- }
- gameLocal.SetCamera(this);
- } else {
- if ( g_debugCinematic.GetBool() ) {
- gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
- }
- gameLocal.SetCamera(NULL);
- }
- }
- }
- /*
- =====================
- idCameraView::Stop
- =====================
- */
- void idCameraView::Stop( void ) {
- if ( g_debugCinematic.GetBool() ) {
- gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
- }
- gameLocal.SetCamera(NULL);
- ActivateTargets( gameLocal.GetLocalPlayer() );
- }
- /*
- =====================
- idCameraView::Spawn
- =====================
- */
- void idCameraView::SetAttachment( idEntity **e, const char *p ) {
- const char *cam = spawnArgs.GetString( p );
- if ( strlen ( cam ) ) {
- *e = gameLocal.FindEntity( cam );
- }
- }
- /*
- =====================
- idCameraView::Spawn
- =====================
- */
- void idCameraView::Spawn( void ) {
- // if no target specified use ourself
- const char *cam = spawnArgs.GetString("cameraTarget");
- if ( strlen ( cam ) == 0) {
- spawnArgs.Set("cameraTarget", spawnArgs.GetString("name"));
- }
- fov = spawnArgs.GetFloat("fov", "90");
- PostEventMS( &EV_Camera_SetAttachments, 0 );
- UpdateChangeableSpawnArgs(NULL);
- }
- /*
- =====================
- idCameraView::GetViewParms
- =====================
- */
- void idCameraView::GetViewParms( renderView_t *view ) {
- assert( view );
-
- if (view == NULL) {
- return;
- }
- idVec3 dir;
- idEntity *ent;
- if ( attachedTo ) {
- ent = attachedTo;
- } else {
- ent = this;
- }
- view->vieworg = ent->GetPhysics()->GetOrigin();
- if ( attachedView ) {
- dir = attachedView->GetPhysics()->GetOrigin() - view->vieworg;
- dir.Normalize();
- view->viewaxis = dir.ToMat3();
- } else {
- view->viewaxis = ent->GetPhysics()->GetAxis();
- }
-
- gameLocal.CalcFov( fov, view->fov_x, view->fov_y );
- }
- /*
- ===============================================================================
- idCameraAnim
- ===============================================================================
- */
- const idEventDef EV_Camera_Start( "start", NULL );
- const idEventDef EV_Camera_Stop( "stop", NULL );
- CLASS_DECLARATION( idCamera, idCameraAnim )
- EVENT( EV_Thread_SetCallback, idCameraAnim::Event_SetCallback )
- EVENT( EV_Camera_Stop, idCameraAnim::Event_Stop )
- EVENT( EV_Camera_Start, idCameraAnim::Event_Start )
- EVENT( EV_Activate, idCameraAnim::Event_Activate )
- END_CLASS
- /*
- =====================
- idCameraAnim::idCameraAnim
- =====================
- */
- idCameraAnim::idCameraAnim() {
- threadNum = 0;
- offset.Zero();
- frameRate = 0;
- cycle = 1;
- starttime = 0;
- activator = NULL;
- }
- /*
- =====================
- idCameraAnim::~idCameraAnim
- =====================
- */
- idCameraAnim::~idCameraAnim() {
- if ( gameLocal.GetCamera() == this ) {
- gameLocal.SetCamera( NULL );
- }
- }
- /*
- ===============
- idCameraAnim::Save
- ================
- */
- void idCameraAnim::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( threadNum );
- savefile->WriteVec3( offset );
- savefile->WriteInt( frameRate );
- savefile->WriteInt( starttime );
- savefile->WriteInt( cycle );
- activator.Save( savefile );
- }
- /*
- ===============
- idCameraAnim::Restore
- ================
- */
- void idCameraAnim::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( threadNum );
- savefile->ReadVec3( offset );
- savefile->ReadInt( frameRate );
- savefile->ReadInt( starttime );
- savefile->ReadInt( cycle );
- activator.Restore( savefile );
- LoadAnim();
- }
- /*
- =====================
- idCameraAnim::Spawn
- =====================
- */
- void idCameraAnim::Spawn( void ) {
- if ( spawnArgs.GetVector( "old_origin", "0 0 0", offset ) ) {
- offset = GetPhysics()->GetOrigin() - offset;
- } else {
- offset.Zero();
- }
- // always think during cinematics
- cinematic = true;
- LoadAnim();
- }
- /*
- ================
- idCameraAnim::Load
- ================
- */
- void idCameraAnim::LoadAnim( void ) {
- int version;
- idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT );
- idToken token;
- int numFrames;
- int numCuts;
- int i;
- idStr filename;
- const char *key;
- key = spawnArgs.GetString( "anim" );
- if ( !key ) {
- gameLocal.Error( "Missing 'anim' key on '%s'", name.c_str() );
- }
- filename = spawnArgs.GetString( va( "anim %s", key ) );
- if ( !filename.Length() ) {
- gameLocal.Error( "Missing 'anim %s' key on '%s'", key, name.c_str() );
- }
- filename.SetFileExtension( MD5_CAMERA_EXT );
- if ( !parser.LoadFile( filename ) ) {
- gameLocal.Error( "Unable to load '%s' on '%s'", filename.c_str(), name.c_str() );
- }
- cameraCuts.Clear();
- cameraCuts.SetGranularity( 1 );
- camera.Clear();
- camera.SetGranularity( 1 );
- parser.ExpectTokenString( MD5_VERSION_STRING );
- version = parser.ParseInt();
- if ( version != MD5_VERSION ) {
- parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION );
- }
- // skip the commandline
- parser.ExpectTokenString( "commandline" );
- parser.ReadToken( &token );
- // parse num frames
- parser.ExpectTokenString( "numFrames" );
- numFrames = parser.ParseInt();
- if ( numFrames <= 0 ) {
- parser.Error( "Invalid number of frames: %d", numFrames );
- }
- // parse framerate
- parser.ExpectTokenString( "frameRate" );
- frameRate = parser.ParseInt();
- if ( frameRate <= 0 ) {
- parser.Error( "Invalid framerate: %d", frameRate );
- }
- // parse num cuts
- parser.ExpectTokenString( "numCuts" );
- numCuts = parser.ParseInt();
- if ( ( numCuts < 0 ) || ( numCuts > numFrames ) ) {
- parser.Error( "Invalid number of camera cuts: %d", numCuts );
- }
- // parse the camera cuts
- parser.ExpectTokenString( "cuts" );
- parser.ExpectTokenString( "{" );
- cameraCuts.SetNum( numCuts );
- for( i = 0; i < numCuts; i++ ) {
- cameraCuts[ i ] = parser.ParseInt();
- if ( ( cameraCuts[ i ] < 1 ) || ( cameraCuts[ i ] >= numFrames ) ) {
- parser.Error( "Invalid camera cut" );
- }
- }
- parser.ExpectTokenString( "}" );
- // parse the camera frames
- parser.ExpectTokenString( "camera" );
- parser.ExpectTokenString( "{" );
- camera.SetNum( numFrames );
- for( i = 0; i < numFrames; i++ ) {
- parser.Parse1DMatrix( 3, camera[ i ].t.ToFloatPtr() );
- parser.Parse1DMatrix( 3, camera[ i ].q.ToFloatPtr() );
- camera[ i ].fov = parser.ParseFloat();
- }
- parser.ExpectTokenString( "}" );
- #if 0
- if ( !gameLocal.GetLocalPlayer() ) {
- return;
- }
- idDebugGraph gGraph;
- idDebugGraph tGraph;
- idDebugGraph qGraph;
- idDebugGraph dtGraph;
- idDebugGraph dqGraph;
- gGraph.SetNumSamples( numFrames );
- tGraph.SetNumSamples( numFrames );
- qGraph.SetNumSamples( numFrames );
- dtGraph.SetNumSamples( numFrames );
- dqGraph.SetNumSamples( numFrames );
- gameLocal.Printf( "\n\ndelta vec:\n" );
- float diff_t, last_t, t;
- float diff_q, last_q, q;
- diff_t = last_t = 0.0f;
- diff_q = last_q = 0.0f;
- for( i = 1; i < numFrames; i++ ) {
- t = ( camera[ i ].t - camera[ i - 1 ].t ).Length();
- q = ( camera[ i ].q.ToQuat() - camera[ i - 1 ].q.ToQuat() ).Length();
- diff_t = t - last_t;
- diff_q = q - last_q;
- gGraph.AddValue( ( i % 10 ) == 0 );
- tGraph.AddValue( t );
- qGraph.AddValue( q );
- dtGraph.AddValue( diff_t );
- dqGraph.AddValue( diff_q );
- gameLocal.Printf( "%d: %.8f : %.8f, %.8f : %.8f\n", i, t, diff_t, q, diff_q );
- last_t = t;
- last_q = q;
- }
- gGraph.Draw( colorBlue, 300.0f );
- tGraph.Draw( colorOrange, 60.0f );
- dtGraph.Draw( colorYellow, 6000.0f );
- qGraph.Draw( colorGreen, 60.0f );
- dqGraph.Draw( colorCyan, 6000.0f );
- #endif
- }
- /*
- ===============
- idCameraAnim::Start
- ================
- */
- void idCameraAnim::Start( void ) {
- cycle = spawnArgs.GetInt( "cycle" );
- if ( !cycle ) {
- cycle = 1;
- }
- if ( g_debugCinematic.GetBool() ) {
- gameLocal.Printf( "%d: '%s' start\n", gameLocal.framenum, GetName() );
- }
- starttime = gameLocal.time;
- gameLocal.SetCamera( this );
- BecomeActive( TH_THINK );
- // if the player has already created the renderview for this frame, have him update it again so that the camera starts this frame
- if ( gameLocal.GetLocalPlayer()->GetRenderView()->time == gameLocal.time ) {
- gameLocal.GetLocalPlayer()->CalculateRenderView();
- }
- }
- /*
- =====================
- idCameraAnim::Stop
- =====================
- */
- void idCameraAnim::Stop( void ) {
- if ( gameLocal.GetCamera() == this ) {
- if ( g_debugCinematic.GetBool() ) {
- gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
- }
- BecomeInactive( TH_THINK );
- gameLocal.SetCamera( NULL );
- if ( threadNum ) {
- idThread::ObjectMoveDone( threadNum, this );
- threadNum = 0;
- }
- ActivateTargets( activator.GetEntity() );
- }
- }
- /*
- =====================
- idCameraAnim::Think
- =====================
- */
- void idCameraAnim::Think( void ) {
- int frame;
- int frameTime;
- if ( thinkFlags & TH_THINK ) {
- // check if we're done in the Think function when the cinematic is being skipped (idCameraAnim::GetViewParms isn't called when skipping cinematics).
- if ( !gameLocal.skipCinematic ) {
- return;
- }
- if ( camera.Num() < 2 ) {
- // 1 frame anims never end
- return;
- }
- if ( frameRate == USERCMD_HZ ) {
- frameTime = gameLocal.time - starttime;
- frame = frameTime / gameLocal.msec;
- } else {
- frameTime = ( gameLocal.time - starttime ) * frameRate;
- frame = frameTime / 1000;
- }
-
- if ( frame > camera.Num() + cameraCuts.Num() - 2 ) {
- if ( cycle > 0 ) {
- cycle--;
- }
- if ( cycle != 0 ) {
- // advance start time so that we loop
- starttime += ( ( camera.Num() - cameraCuts.Num() ) * 1000 ) / frameRate;
- } else {
- Stop();
- }
- }
- }
- }
- /*
- =====================
- idCameraAnim::GetViewParms
- =====================
- */
- void idCameraAnim::GetViewParms( renderView_t *view ) {
- int realFrame;
- int frame;
- int frameTime;
- float lerp;
- float invlerp;
- cameraFrame_t *camFrame;
- int i;
- int cut;
- idQuat q1, q2, q3;
- assert( view );
- if ( !view ) {
- return;
- }
- if ( camera.Num() == 0 ) {
- // we most likely are in the middle of a restore
- // FIXME: it would be better to fix it so this doesn't get called during a restore
- return;
- }
- if ( frameRate == USERCMD_HZ ) {
- frameTime = gameLocal.time - starttime;
- frame = frameTime / gameLocal.msec;
- lerp = 0.0f;
- } else {
- frameTime = ( gameLocal.time - starttime ) * frameRate;
- frame = frameTime / 1000;
- lerp = ( frameTime % 1000 ) * 0.001f;
- }
- // skip any frames where camera cuts occur
- realFrame = frame;
- cut = 0;
- for( i = 0; i < cameraCuts.Num(); i++ ) {
- if ( frame < cameraCuts[ i ] ) {
- break;
- }
- frame++;
- cut++;
- }
- if ( g_debugCinematic.GetBool() ) {
- int prevFrameTime = ( gameLocal.time - starttime - gameLocal.msec ) * frameRate;
- int prevFrame = prevFrameTime / 1000;
- int prevCut;
- prevCut = 0;
- for( i = 0; i < cameraCuts.Num(); i++ ) {
- if ( prevFrame < cameraCuts[ i ] ) {
- break;
- }
- prevFrame++;
- prevCut++;
- }
- if ( prevCut != cut ) {
- gameLocal.Printf( "%d: '%s' cut %d\n", gameLocal.framenum, GetName(), cut );
- }
- }
- // clamp to the first frame. also check if this is a one frame anim. one frame anims would end immediately,
- // but since they're mainly used for static cams anyway, just stay on it infinitely.
- if ( ( frame < 0 ) || ( camera.Num() < 2 ) ) {
- view->viewaxis = camera[ 0 ].q.ToQuat().ToMat3();
- view->vieworg = camera[ 0 ].t + offset;
- view->fov_x = camera[ 0 ].fov;
- } else if ( frame > camera.Num() - 2 ) {
- if ( cycle > 0 ) {
- cycle--;
- }
- if ( cycle != 0 ) {
- // advance start time so that we loop
- starttime += ( ( camera.Num() - cameraCuts.Num() ) * 1000 ) / frameRate;
- GetViewParms( view );
- return;
- }
- Stop();
- if ( gameLocal.GetCamera() != NULL ) {
- // we activated another camera when we stopped, so get it's viewparms instead
- gameLocal.GetCamera()->GetViewParms( view );
- return;
- } else {
- // just use our last frame
- camFrame = &camera[ camera.Num() - 1 ];
- view->viewaxis = camFrame->q.ToQuat().ToMat3();
- view->vieworg = camFrame->t + offset;
- view->fov_x = camFrame->fov;
- }
- } else if ( lerp == 0.0f ) {
- camFrame = &camera[ frame ];
- view->viewaxis = camFrame[ 0 ].q.ToMat3();
- view->vieworg = camFrame[ 0 ].t + offset;
- view->fov_x = camFrame[ 0 ].fov;
- } else {
- camFrame = &camera[ frame ];
- invlerp = 1.0f - lerp;
- q1 = camFrame[ 0 ].q.ToQuat();
- q2 = camFrame[ 1 ].q.ToQuat();
- q3.Slerp( q1, q2, lerp );
- view->viewaxis = q3.ToMat3();
- view->vieworg = camFrame[ 0 ].t * invlerp + camFrame[ 1 ].t * lerp + offset;
- view->fov_x = camFrame[ 0 ].fov * invlerp + camFrame[ 1 ].fov * lerp;
- }
- gameLocal.CalcFov( view->fov_x, view->fov_x, view->fov_y );
- // setup the pvs for this frame
- UpdatePVSAreas( view->vieworg );
-
- #if 0
- static int lastFrame = 0;
- static idVec3 lastFrameVec( 0.0f, 0.0f, 0.0f );
- if ( gameLocal.time != lastFrame ) {
- gameRenderWorld->DebugBounds( colorCyan, idBounds( view->vieworg ).Expand( 16.0f ), vec3_origin, gameLocal.msec );
- gameRenderWorld->DebugLine( colorRed, view->vieworg, view->vieworg + idVec3( 0.0f, 0.0f, 2.0f ), 10000, false );
- gameRenderWorld->DebugLine( colorCyan, lastFrameVec, view->vieworg, 10000, false );
- gameRenderWorld->DebugLine( colorYellow, view->vieworg + view->viewaxis[ 0 ] * 64.0f, view->vieworg + view->viewaxis[ 0 ] * 66.0f, 10000, false );
- gameRenderWorld->DebugLine( colorOrange, view->vieworg + view->viewaxis[ 0 ] * 64.0f, view->vieworg + view->viewaxis[ 0 ] * 64.0f + idVec3( 0.0f, 0.0f, 2.0f ), 10000, false );
- lastFrameVec = view->vieworg;
- lastFrame = gameLocal.time;
- }
- #endif
- if ( g_showcamerainfo.GetBool() ) {
- gameLocal.Printf( "^5Frame: ^7%d/%d\n\n\n", realFrame + 1, camera.Num() - cameraCuts.Num() );
- }
- }
- /*
- ===============
- idCameraAnim::Event_Activate
- ================
- */
- void idCameraAnim::Event_Activate( idEntity *_activator ) {
- activator = _activator;
- if ( thinkFlags & TH_THINK ) {
- Stop();
- } else {
- Start();
- }
- }
- /*
- ===============
- idCameraAnim::Event_Start
- ================
- */
- void idCameraAnim::Event_Start( void ) {
- Start();
- }
- /*
- ===============
- idCameraAnim::Event_Stop
- ================
- */
- void idCameraAnim::Event_Stop( void ) {
- Stop();
- }
- /*
- ================
- idCameraAnim::Event_SetCallback
- ================
- */
- void idCameraAnim::Event_SetCallback( void ) {
- if ( ( gameLocal.GetCamera() == this ) && !threadNum ) {
- threadNum = idThread::CurrentThreadNum();
- idThread::ReturnInt( true );
- } else {
- idThread::ReturnInt( false );
- }
- }
|