Camera.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Game_local.h"
  23. /*
  24. ===============================================================================
  25. idCamera
  26. Base class for cameras
  27. ===============================================================================
  28. */
  29. ABSTRACT_DECLARATION( idEntity, idCamera )
  30. END_CLASS
  31. /*
  32. =====================
  33. idCamera::Spawn
  34. =====================
  35. */
  36. void idCamera::Spawn() {
  37. }
  38. /*
  39. =====================
  40. idCamera::GetRenderView
  41. =====================
  42. */
  43. renderView_t *idCamera::GetRenderView() {
  44. renderView_t *rv = idEntity::GetRenderView();
  45. GetViewParms( rv );
  46. return rv;
  47. }
  48. /***********************************************************************
  49. idCameraView
  50. ***********************************************************************/
  51. const idEventDef EV_Camera_SetAttachments( "<getattachments>", NULL );
  52. CLASS_DECLARATION( idCamera, idCameraView )
  53. EVENT( EV_Activate, idCameraView::Event_Activate )
  54. EVENT( EV_Camera_SetAttachments, idCameraView::Event_SetAttachments )
  55. END_CLASS
  56. /*
  57. ===============
  58. idCameraView::idCameraView
  59. ================
  60. */
  61. idCameraView::idCameraView() {
  62. fov = 90.0f;
  63. attachedTo = NULL;
  64. attachedView = NULL;
  65. }
  66. /*
  67. ===============
  68. idCameraView::Save
  69. ================
  70. */
  71. void idCameraView::Save( idSaveGame *savefile ) const {
  72. savefile->WriteFloat( fov );
  73. savefile->WriteObject( attachedTo );
  74. savefile->WriteObject( attachedView );
  75. }
  76. /*
  77. ===============
  78. idCameraView::Restore
  79. ================
  80. */
  81. void idCameraView::Restore( idRestoreGame *savefile ) {
  82. savefile->ReadFloat( fov );
  83. savefile->ReadObject( reinterpret_cast<idClass *&>( attachedTo ) );
  84. savefile->ReadObject( reinterpret_cast<idClass *&>( attachedView ) );
  85. }
  86. /*
  87. ===============
  88. idCameraView::Event_SetAttachments
  89. ================
  90. */
  91. void idCameraView::Event_SetAttachments( ) {
  92. SetAttachment( &attachedTo, "attachedTo" );
  93. SetAttachment( &attachedView, "attachedView" );
  94. }
  95. /*
  96. ===============
  97. idCameraView::Event_Activate
  98. ================
  99. */
  100. void idCameraView::Event_Activate( idEntity *activator ) {
  101. if (spawnArgs.GetBool("trigger")) {
  102. if (gameLocal.GetCamera() != this) {
  103. if ( g_debugCinematic.GetBool() ) {
  104. gameLocal.Printf( "%d: '%s' start\n", gameLocal.framenum, GetName() );
  105. }
  106. gameLocal.SetCamera(this);
  107. } else {
  108. if ( g_debugCinematic.GetBool() ) {
  109. gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
  110. }
  111. gameLocal.SetCamera(NULL);
  112. }
  113. }
  114. }
  115. /*
  116. =====================
  117. idCameraView::Stop
  118. =====================
  119. */
  120. void idCameraView::Stop() {
  121. if ( g_debugCinematic.GetBool() ) {
  122. gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
  123. }
  124. gameLocal.SetCamera(NULL);
  125. ActivateTargets( gameLocal.GetLocalPlayer() );
  126. }
  127. /*
  128. =====================
  129. idCameraView::Spawn
  130. =====================
  131. */
  132. void idCameraView::SetAttachment( idEntity **e, const char *p ) {
  133. const char *cam = spawnArgs.GetString( p );
  134. if ( strlen ( cam ) ) {
  135. *e = gameLocal.FindEntity( cam );
  136. }
  137. }
  138. /*
  139. =====================
  140. idCameraView::Spawn
  141. =====================
  142. */
  143. void idCameraView::Spawn() {
  144. // if no target specified use ourself
  145. const char *cam = spawnArgs.GetString("cameraTarget");
  146. if ( strlen ( cam ) == 0) {
  147. spawnArgs.Set("cameraTarget", spawnArgs.GetString("name"));
  148. }
  149. fov = spawnArgs.GetFloat("fov", "90");
  150. PostEventMS( &EV_Camera_SetAttachments, 0 );
  151. UpdateChangeableSpawnArgs(NULL);
  152. }
  153. /*
  154. =====================
  155. idCameraView::GetViewParms
  156. =====================
  157. */
  158. void idCameraView::GetViewParms( renderView_t *view ) {
  159. assert( view );
  160. if (view == NULL) {
  161. return;
  162. }
  163. idVec3 dir;
  164. idEntity *ent;
  165. if ( attachedTo ) {
  166. ent = attachedTo;
  167. } else {
  168. ent = this;
  169. }
  170. view->vieworg = ent->GetPhysics()->GetOrigin();
  171. if ( attachedView ) {
  172. dir = attachedView->GetPhysics()->GetOrigin() - view->vieworg;
  173. dir.Normalize();
  174. view->viewaxis = dir.ToMat3();
  175. } else {
  176. view->viewaxis = ent->GetPhysics()->GetAxis();
  177. }
  178. gameLocal.CalcFov( fov, view->fov_x, view->fov_y );
  179. }
  180. /*
  181. ===============================================================================
  182. idCameraAnim
  183. ===============================================================================
  184. */
  185. const idEventDef EV_Camera_Start( "start", NULL );
  186. const idEventDef EV_Camera_Stop( "stop", NULL );
  187. CLASS_DECLARATION( idCamera, idCameraAnim )
  188. EVENT( EV_Thread_SetCallback, idCameraAnim::Event_SetCallback )
  189. EVENT( EV_Camera_Stop, idCameraAnim::Event_Stop )
  190. EVENT( EV_Camera_Start, idCameraAnim::Event_Start )
  191. EVENT( EV_Activate, idCameraAnim::Event_Activate )
  192. END_CLASS
  193. /*
  194. =====================
  195. idCameraAnim::idCameraAnim
  196. =====================
  197. */
  198. idCameraAnim::idCameraAnim() {
  199. threadNum = 0;
  200. offset.Zero();
  201. frameRate = 0;
  202. cycle = 1;
  203. starttime = 0;
  204. activator = NULL;
  205. }
  206. /*
  207. =====================
  208. idCameraAnim::~idCameraAnim
  209. =====================
  210. */
  211. idCameraAnim::~idCameraAnim() {
  212. if ( gameLocal.GetCamera() == this ) {
  213. gameLocal.SetCamera( NULL );
  214. }
  215. }
  216. /*
  217. ===============
  218. idCameraAnim::Save
  219. ================
  220. */
  221. void idCameraAnim::Save( idSaveGame *savefile ) const {
  222. savefile->WriteInt( threadNum );
  223. savefile->WriteVec3( offset );
  224. savefile->WriteInt( frameRate );
  225. savefile->WriteInt( starttime );
  226. savefile->WriteInt( cycle );
  227. activator.Save( savefile );
  228. }
  229. /*
  230. ===============
  231. idCameraAnim::Restore
  232. ================
  233. */
  234. void idCameraAnim::Restore( idRestoreGame *savefile ) {
  235. savefile->ReadInt( threadNum );
  236. savefile->ReadVec3( offset );
  237. savefile->ReadInt( frameRate );
  238. savefile->ReadInt( starttime );
  239. savefile->ReadInt( cycle );
  240. activator.Restore( savefile );
  241. LoadAnim();
  242. }
  243. /*
  244. =====================
  245. idCameraAnim::Spawn
  246. =====================
  247. */
  248. void idCameraAnim::Spawn() {
  249. if ( spawnArgs.GetVector( "old_origin", "0 0 0", offset ) ) {
  250. offset = GetPhysics()->GetOrigin() - offset;
  251. } else {
  252. offset.Zero();
  253. }
  254. // always think during cinematics
  255. cinematic = true;
  256. LoadAnim();
  257. }
  258. /*
  259. ================
  260. idCameraAnim::Load
  261. ================
  262. */
  263. void idCameraAnim::LoadAnim() {
  264. int version;
  265. idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT );
  266. idToken token;
  267. int numFrames;
  268. int numCuts;
  269. int i;
  270. idStr filename;
  271. const char *key;
  272. key = spawnArgs.GetString( "anim" );
  273. if ( !key ) {
  274. gameLocal.Error( "Missing 'anim' key on '%s'", name.c_str() );
  275. }
  276. filename = spawnArgs.GetString( va( "anim %s", key ) );
  277. if ( !filename.Length() ) {
  278. gameLocal.Error( "Missing 'anim %s' key on '%s'", key, name.c_str() );
  279. }
  280. filename.SetFileExtension( MD5_CAMERA_EXT );
  281. if ( !parser.LoadFile( filename ) ) {
  282. gameLocal.Error( "Unable to load '%s' on '%s'", filename.c_str(), name.c_str() );
  283. }
  284. cameraCuts.Clear();
  285. cameraCuts.SetGranularity( 1 );
  286. camera.Clear();
  287. camera.SetGranularity( 1 );
  288. parser.ExpectTokenString( MD5_VERSION_STRING );
  289. version = parser.ParseInt();
  290. if ( version != MD5_VERSION ) {
  291. parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION );
  292. }
  293. // skip the commandline
  294. parser.ExpectTokenString( "commandline" );
  295. parser.ReadToken( &token );
  296. // parse num frames
  297. parser.ExpectTokenString( "numFrames" );
  298. numFrames = parser.ParseInt();
  299. if ( numFrames <= 0 ) {
  300. parser.Error( "Invalid number of frames: %d", numFrames );
  301. }
  302. // parse framerate
  303. parser.ExpectTokenString( "frameRate" );
  304. frameRate = parser.ParseInt();
  305. if ( frameRate <= 0 ) {
  306. parser.Error( "Invalid framerate: %d", frameRate );
  307. }
  308. // parse num cuts
  309. parser.ExpectTokenString( "numCuts" );
  310. numCuts = parser.ParseInt();
  311. if ( ( numCuts < 0 ) || ( numCuts > numFrames ) ) {
  312. parser.Error( "Invalid number of camera cuts: %d", numCuts );
  313. }
  314. // parse the camera cuts
  315. parser.ExpectTokenString( "cuts" );
  316. parser.ExpectTokenString( "{" );
  317. cameraCuts.SetNum( numCuts );
  318. for( i = 0; i < numCuts; i++ ) {
  319. cameraCuts[ i ] = parser.ParseInt();
  320. if ( ( cameraCuts[ i ] < 1 ) || ( cameraCuts[ i ] >= numFrames ) ) {
  321. parser.Error( "Invalid camera cut" );
  322. }
  323. }
  324. parser.ExpectTokenString( "}" );
  325. // parse the camera frames
  326. parser.ExpectTokenString( "camera" );
  327. parser.ExpectTokenString( "{" );
  328. camera.SetNum( numFrames );
  329. for( i = 0; i < numFrames; i++ ) {
  330. parser.Parse1DMatrix( 3, camera[ i ].t.ToFloatPtr() );
  331. parser.Parse1DMatrix( 3, camera[ i ].q.ToFloatPtr() );
  332. camera[ i ].fov = parser.ParseFloat();
  333. }
  334. parser.ExpectTokenString( "}" );
  335. }
  336. /*
  337. ===============
  338. idCameraAnim::Start
  339. ================
  340. */
  341. void idCameraAnim::Start() {
  342. cycle = spawnArgs.GetInt( "cycle" );
  343. if ( !cycle ) {
  344. cycle = 1;
  345. }
  346. if ( g_debugCinematic.GetBool() ) {
  347. gameLocal.Printf( "%d: '%s' start\n", gameLocal.framenum, GetName() );
  348. }
  349. starttime = gameLocal.time;
  350. gameLocal.SetCamera( this );
  351. BecomeActive( TH_THINK );
  352. // if the player has already created the renderview for this frame, have him update it again so that the camera starts this frame
  353. if ( gameLocal.GetLocalPlayer()->GetRenderView()->time[TIME_GROUP2] == gameLocal.fast.time ) {
  354. gameLocal.GetLocalPlayer()->CalculateRenderView();
  355. }
  356. }
  357. /*
  358. =====================
  359. idCameraAnim::Stop
  360. =====================
  361. */
  362. void idCameraAnim::Stop() {
  363. if ( gameLocal.GetCamera() == this ) {
  364. if ( g_debugCinematic.GetBool() ) {
  365. gameLocal.Printf( "%d: '%s' stop\n", gameLocal.framenum, GetName() );
  366. }
  367. BecomeInactive( TH_THINK );
  368. gameLocal.SetCamera( NULL );
  369. if ( threadNum ) {
  370. idThread::ObjectMoveDone( threadNum, this );
  371. threadNum = 0;
  372. }
  373. ActivateTargets( activator.GetEntity() );
  374. }
  375. }
  376. /*
  377. =====================
  378. idCameraAnim::Think
  379. =====================
  380. */
  381. void idCameraAnim::Think() {
  382. }
  383. /*
  384. =====================
  385. idCameraAnim::GetViewParms
  386. =====================
  387. */
  388. void idCameraAnim::GetViewParms( renderView_t *view ) {
  389. int realFrame;
  390. int frame;
  391. int frameTime;
  392. float lerp;
  393. float invlerp;
  394. cameraFrame_t *camFrame;
  395. int i;
  396. int cut;
  397. idQuat q1, q2, q3;
  398. assert( view );
  399. if ( !view ) {
  400. return;
  401. }
  402. if ( camera.Num() == 0 ) {
  403. // we most likely are in the middle of a restore
  404. // FIXME: it would be better to fix it so this doesn't get called during a restore
  405. return;
  406. }
  407. SetTimeState ts( timeGroup );
  408. frameTime = ( gameLocal.time - starttime ) * frameRate;
  409. frame = frameTime / 1000;
  410. lerp = ( frameTime % 1000 ) * 0.001f;
  411. // skip any frames where camera cuts occur
  412. realFrame = frame;
  413. cut = 0;
  414. for( i = 0; i < cameraCuts.Num(); i++ ) {
  415. if ( frame < cameraCuts[ i ] ) {
  416. break;
  417. }
  418. frame++;
  419. cut++;
  420. }
  421. if ( g_debugCinematic.GetBool() ) {
  422. int prevFrameTime = ( gameLocal.previousTime - starttime ) * frameRate;
  423. int prevFrame = prevFrameTime / 1000;
  424. int prevCut;
  425. prevCut = 0;
  426. for( i = 0; i < cameraCuts.Num(); i++ ) {
  427. if ( prevFrame < cameraCuts[ i ] ) {
  428. break;
  429. }
  430. prevFrame++;
  431. prevCut++;
  432. }
  433. if ( prevCut != cut ) {
  434. gameLocal.Printf( "%d: '%s' cut %d\n", gameLocal.framenum, GetName(), cut );
  435. }
  436. }
  437. // clamp to the first frame. also check if this is a one frame anim. one frame anims would end immediately,
  438. // but since they're mainly used for static cams anyway, just stay on it infinitely.
  439. if ( ( frame < 0 ) || ( camera.Num() < 2 ) ) {
  440. view->viewaxis = camera[ 0 ].q.ToQuat().ToMat3();
  441. view->vieworg = camera[ 0 ].t + offset;
  442. view->fov_x = camera[ 0 ].fov;
  443. } else if ( frame > camera.Num() - 2 ) {
  444. if ( cycle > 0 ) {
  445. cycle--;
  446. }
  447. if ( cycle != 0 ) {
  448. // advance start time so that we loop
  449. starttime += ( ( camera.Num() - cameraCuts.Num() ) * 1000 ) / frameRate;
  450. GetViewParms( view );
  451. return;
  452. }
  453. Stop();
  454. if ( gameLocal.GetCamera() != NULL ) {
  455. // we activated another camera when we stopped, so get it's viewparms instead
  456. gameLocal.GetCamera()->GetViewParms( view );
  457. return;
  458. } else {
  459. // just use our last frame
  460. camFrame = &camera[ camera.Num() - 1 ];
  461. view->viewaxis = camFrame->q.ToQuat().ToMat3();
  462. view->vieworg = camFrame->t + offset;
  463. view->fov_x = camFrame->fov;
  464. }
  465. } else if ( lerp == 0.0f ) {
  466. camFrame = &camera[ frame ];
  467. view->viewaxis = camFrame[ 0 ].q.ToMat3();
  468. view->vieworg = camFrame[ 0 ].t + offset;
  469. view->fov_x = camFrame[ 0 ].fov;
  470. } else {
  471. camFrame = &camera[ frame ];
  472. invlerp = 1.0f - lerp;
  473. q1 = camFrame[ 0 ].q.ToQuat();
  474. q2 = camFrame[ 1 ].q.ToQuat();
  475. q3.Slerp( q1, q2, lerp );
  476. view->viewaxis = q3.ToMat3();
  477. view->vieworg = camFrame[ 0 ].t * invlerp + camFrame[ 1 ].t * lerp + offset;
  478. view->fov_x = camFrame[ 0 ].fov * invlerp + camFrame[ 1 ].fov * lerp;
  479. }
  480. gameLocal.CalcFov( view->fov_x, view->fov_x, view->fov_y );
  481. // setup the pvs for this frame
  482. UpdatePVSAreas( view->vieworg );
  483. #if 0
  484. static int lastFrame = 0;
  485. static idVec3 lastFrameVec( 0.0f, 0.0f, 0.0f );
  486. if ( gameLocal.time != lastFrame ) {
  487. gameRenderWorld->DebugBounds( colorCyan, idBounds( view->vieworg ).Expand( 16.0f ), vec3_origin, 1 );
  488. gameRenderWorld->DebugLine( colorRed, view->vieworg, view->vieworg + idVec3( 0.0f, 0.0f, 2.0f ), 10000, false );
  489. gameRenderWorld->DebugLine( colorCyan, lastFrameVec, view->vieworg, 10000, false );
  490. gameRenderWorld->DebugLine( colorYellow, view->vieworg + view->viewaxis[ 0 ] * 64.0f, view->vieworg + view->viewaxis[ 0 ] * 66.0f, 10000, false );
  491. 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 );
  492. lastFrameVec = view->vieworg;
  493. lastFrame = gameLocal.time;
  494. }
  495. #endif
  496. if ( g_showcamerainfo.GetBool() ) {
  497. gameLocal.Printf( "^5Frame: ^7%d/%d\n\n\n", realFrame + 1, camera.Num() - cameraCuts.Num() );
  498. }
  499. }
  500. /*
  501. ===============
  502. idCameraAnim::Event_Activate
  503. ================
  504. */
  505. void idCameraAnim::Event_Activate( idEntity *_activator ) {
  506. activator = _activator;
  507. if ( thinkFlags & TH_THINK ) {
  508. Stop();
  509. } else {
  510. Start();
  511. }
  512. }
  513. /*
  514. ===============
  515. idCameraAnim::Event_Start
  516. ================
  517. */
  518. void idCameraAnim::Event_Start() {
  519. Start();
  520. }
  521. /*
  522. ===============
  523. idCameraAnim::Event_Stop
  524. ================
  525. */
  526. void idCameraAnim::Event_Stop() {
  527. Stop();
  528. }
  529. /*
  530. ================
  531. idCameraAnim::Event_SetCallback
  532. ================
  533. */
  534. void idCameraAnim::Event_SetCallback() {
  535. if ( ( gameLocal.GetCamera() == this ) && !threadNum ) {
  536. threadNum = idThread::CurrentThreadNum();
  537. idThread::ReturnInt( true );
  538. } else {
  539. idThread::ReturnInt( false );
  540. }
  541. }