1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 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.
23
24 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.
25
26 ===========================================================================
27 */
28
29 #include "sys/platform.h"
30 #include "idlib/geometry/JointTransform.h"
31 #include "framework/DeclSkin.h"
32 #include "framework/DemoFile.h"
33 #include "framework/EventLoop.h"
34 #include "framework/Session.h"
35 #include "renderer/GuiModel.h"
36 #include "renderer/ModelManager.h"
37 #include "renderer/RenderWorld_local.h"
38 #include "ui/UserInterface.h"
39 #include "sound/sound.h"
40
41 #include "renderer/tr_local.h"
42
43 //#define WRITE_GUIS
44
45 typedef struct {
46 int version;
47 int sizeofRenderEntity;
48 int sizeofRenderLight;
49 char mapname[256];
50 } demoHeader_t;
51
52
53 /*
54 ==============
55 StartWritingDemo
56 ==============
57 */
StartWritingDemo(idDemoFile * demo)58 void idRenderWorldLocal::StartWritingDemo( idDemoFile *demo ) {
59 int i;
60
61 // FIXME: we should track the idDemoFile locally, instead of snooping into session for it
62
63 WriteLoadMap();
64
65 // write the door portal state
66 for ( i = 0 ; i < numInterAreaPortals ; i++ ) {
67 if ( doublePortals[i].blockingBits ) {
68 SetPortalState( i+1, doublePortals[i].blockingBits );
69 }
70 }
71
72 // clear the archive counter on all defs
73 for ( i = 0 ; i < lightDefs.Num() ; i++ ) {
74 if ( lightDefs[i] ) {
75 lightDefs[i]->archived = false;
76 }
77 }
78 for ( i = 0 ; i < entityDefs.Num() ; i++ ) {
79 if ( entityDefs[i] ) {
80 entityDefs[i]->archived = false;
81 }
82 }
83 }
84
StopWritingDemo()85 void idRenderWorldLocal::StopWritingDemo() {
86 // writeDemo = NULL;
87 }
88
89 /*
90 ==============
91 ProcessDemoCommand
92 ==============
93 */
ProcessDemoCommand(idDemoFile * readDemo,renderView_t * renderView,int * demoTimeOffset)94 bool idRenderWorldLocal::ProcessDemoCommand( idDemoFile *readDemo, renderView_t *renderView, int *demoTimeOffset ) {
95 bool newMap = false;
96
97 if ( !readDemo ) {
98 return false;
99 }
100
101 int dc;
102 qhandle_t h;
103
104 if ( !readDemo->ReadInt( dc ) ) {
105 // a demoShot may not have an endFrame, but it is still valid
106 return false;
107 }
108
109 switch( (demoCommand_t)dc ) {
110 case DC_LOADMAP:
111 // read the initial data
112 demoHeader_t header;
113
114 readDemo->ReadInt( header.version );
115 readDemo->ReadInt( header.sizeofRenderEntity );
116 readDemo->ReadInt( header.sizeofRenderLight );
117 for ( int i = 0; i < 256; i++ )
118 readDemo->ReadChar( header.mapname[i] );
119 // the internal version value got replaced by DS_VERSION at toplevel
120 if ( header.version != 4 ) {
121 common->Error( "Demo version mismatch.\n" );
122 }
123
124 if ( r_showDemo.GetBool() ) {
125 common->Printf( "DC_LOADMAP: %s\n", header.mapname );
126 }
127 InitFromMap( header.mapname );
128
129 newMap = true; // we will need to set demoTimeOffset
130
131 break;
132
133 case DC_RENDERVIEW:
134 readDemo->ReadInt( renderView->viewID );
135 readDemo->ReadInt( renderView->x );
136 readDemo->ReadInt( renderView->y );
137 readDemo->ReadInt( renderView->width );
138 readDemo->ReadInt( renderView->height );
139 readDemo->ReadFloat( renderView->fov_x );
140 readDemo->ReadFloat( renderView->fov_y );
141 readDemo->ReadVec3( renderView->vieworg );
142 readDemo->ReadMat3( renderView->viewaxis );
143 readDemo->ReadBool( renderView->cramZNear );
144 readDemo->ReadBool( renderView->forceUpdate );
145 // binary compatibility with win32 padded structures
146 char tmp;
147 int i;
148 readDemo->ReadChar( tmp );
149 readDemo->ReadChar( tmp );
150 readDemo->ReadInt( renderView->time );
151 for ( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ )
152 readDemo->ReadFloat( renderView->shaderParms[i] );
153
154 renderView->globalMaterial = NULL;
155 if ( !readDemo->ReadInt( i ) ) {
156 return false;
157 }
158
159 if ( r_showDemo.GetBool() ) {
160 common->Printf( "DC_RENDERVIEW: %i\n", renderView->time );
161 }
162
163 // possibly change the time offset if this is from a new map
164 if ( newMap && demoTimeOffset ) {
165 *demoTimeOffset = renderView->time - eventLoop->Milliseconds();
166 }
167 return false;
168
169 case DC_UPDATE_ENTITYDEF:
170 ReadRenderEntity();
171 break;
172 case DC_DELETE_ENTITYDEF:
173 if ( !readDemo->ReadInt( h ) ) {
174 return false;
175 }
176 if ( r_showDemo.GetBool() ) {
177 common->Printf( "DC_DELETE_ENTITYDEF: %i\n", h );
178 }
179 FreeEntityDef( h );
180 break;
181 case DC_UPDATE_LIGHTDEF:
182 ReadRenderLight();
183 break;
184 case DC_DELETE_LIGHTDEF:
185 if ( !readDemo->ReadInt( h ) ) {
186 return false;
187 }
188 if ( r_showDemo.GetBool() ) {
189 common->Printf( "DC_DELETE_LIGHTDEF: %i\n", h );
190 }
191 FreeLightDef( h );
192 break;
193
194 case DC_CAPTURE_RENDER:
195 if ( r_showDemo.GetBool() ) {
196 common->Printf( "DC_CAPTURE_RENDER\n" );
197 }
198 renderSystem->CaptureRenderToImage( readDemo->ReadHashString() );
199 break;
200
201 case DC_CROP_RENDER:
202 if ( r_showDemo.GetBool() ) {
203 common->Printf( "DC_CROP_RENDER\n" );
204 }
205 int size[3];
206 readDemo->ReadInt( size[0] );
207 readDemo->ReadInt( size[1] );
208 readDemo->ReadInt( size[2] );
209 renderSystem->CropRenderSize( size[0], size[1], size[2] != 0 );
210 break;
211
212 case DC_UNCROP_RENDER:
213 if ( r_showDemo.GetBool() ) {
214 common->Printf( "DC_UNCROP\n" );
215 }
216 renderSystem->UnCrop();
217 break;
218
219 case DC_GUI_MODEL:
220 if ( r_showDemo.GetBool() ) {
221 common->Printf( "DC_GUI_MODEL\n" );
222 }
223 tr.demoGuiModel->ReadFromDemo( readDemo );
224 break;
225
226 case DC_DEFINE_MODEL:
227 {
228 idRenderModel *model = renderModelManager->AllocModel();
229 model->ReadFromDemoFile( session->readDemo );
230 // add to model manager, so we can find it
231 renderModelManager->AddModel( model );
232
233 // save it in the list to free when clearing this map
234 localModels.Append( model );
235
236 if ( r_showDemo.GetBool() ) {
237 common->Printf( "DC_DEFINE_MODEL\n" );
238 }
239 break;
240 }
241 case DC_SET_PORTAL_STATE:
242 {
243 int data[2];
244 readDemo->ReadInt( data[0] );
245 readDemo->ReadInt( data[1] );
246 SetPortalState( data[0], data[1] );
247 if ( r_showDemo.GetBool() ) {
248 common->Printf( "DC_SET_PORTAL_STATE: %i %i\n", data[0], data[1] );
249 }
250 }
251
252 break;
253 case DC_END_FRAME:
254 return true;
255
256 default:
257 common->Error( "Bad token in demo stream" );
258 }
259
260 return false;
261 }
262
263 /*
264 ================
265 WriteLoadMap
266 ================
267 */
WriteLoadMap()268 void idRenderWorldLocal::WriteLoadMap() {
269
270 // only the main renderWorld writes stuff to demos, not the wipes or
271 // menu renders
272 if ( this != session->rw ) {
273 return;
274 }
275
276 session->writeDemo->WriteInt( DS_RENDER );
277 session->writeDemo->WriteInt( DC_LOADMAP );
278
279 demoHeader_t header;
280 strncpy( header.mapname, mapName.c_str(), sizeof( header.mapname ) - 1 );
281 header.version = 4;
282 header.sizeofRenderEntity = sizeof( renderEntity_t );
283 header.sizeofRenderLight = sizeof( renderLight_t );
284 session->writeDemo->WriteInt( header.version );
285 session->writeDemo->WriteInt( header.sizeofRenderEntity );
286 session->writeDemo->WriteInt( header.sizeofRenderLight );
287 for ( int i = 0; i < 256; i++ )
288 session->writeDemo->WriteChar( header.mapname[i] );
289
290 if ( r_showDemo.GetBool() ) {
291 common->Printf( "write DC_DELETE_LIGHTDEF: %s\n", mapName.c_str() );
292 }
293 }
294
295 /*
296 ================
297 WriteVisibleDefs
298
299 ================
300 */
WriteVisibleDefs(const viewDef_t * viewDef)301 void idRenderWorldLocal::WriteVisibleDefs( const viewDef_t *viewDef ) {
302 // only the main renderWorld writes stuff to demos, not the wipes or
303 // menu renders
304 if ( this != session->rw ) {
305 return;
306 }
307
308 // make sure all necessary entities and lights are updated
309 for ( viewEntity_t *viewEnt = viewDef->viewEntitys ; viewEnt ; viewEnt = viewEnt->next ) {
310 idRenderEntityLocal *ent = viewEnt->entityDef;
311
312 if ( ent->archived ) {
313 // still up to date
314 continue;
315 }
316
317 // write it out
318 WriteRenderEntity( ent->index, &ent->parms );
319 ent->archived = true;
320 }
321
322 for ( viewLight_t *viewLight = viewDef->viewLights ; viewLight ; viewLight = viewLight->next ) {
323 idRenderLightLocal *light = viewLight->lightDef;
324
325 if ( light->archived ) {
326 // still up to date
327 continue;
328 }
329 // write it out
330 WriteRenderLight( light->index, &light->parms );
331 light->archived = true;
332 }
333 }
334
335
336 /*
337 ================
338 WriteRenderView
339 ================
340 */
WriteRenderView(const renderView_t * renderView)341 void idRenderWorldLocal::WriteRenderView( const renderView_t *renderView ) {
342 int i;
343
344 // only the main renderWorld writes stuff to demos, not the wipes or
345 // menu renders
346 if ( this != session->rw ) {
347 return;
348 }
349
350 // write the actual view command
351 session->writeDemo->WriteInt( DS_RENDER );
352 session->writeDemo->WriteInt( DC_RENDERVIEW );
353 session->writeDemo->WriteInt( renderView->viewID );
354 session->writeDemo->WriteInt( renderView->x );
355 session->writeDemo->WriteInt( renderView->y );
356 session->writeDemo->WriteInt( renderView->width );
357 session->writeDemo->WriteInt( renderView->height );
358 session->writeDemo->WriteFloat( renderView->fov_x );
359 session->writeDemo->WriteFloat( renderView->fov_y );
360 session->writeDemo->WriteVec3( renderView->vieworg );
361 session->writeDemo->WriteMat3( renderView->viewaxis );
362 session->writeDemo->WriteBool( renderView->cramZNear );
363 session->writeDemo->WriteBool( renderView->forceUpdate );
364 // binary compatibility with old win32 version writing padded structures directly to disk
365 session->writeDemo->WriteUnsignedChar( 0 );
366 session->writeDemo->WriteUnsignedChar( 0 );
367 session->writeDemo->WriteInt( renderView->time );
368 for ( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ )
369 session->writeDemo->WriteFloat( renderView->shaderParms[i] );
370 session->writeDemo->WriteInt( 0 ); //renderView->globalMaterial
371
372 if ( r_showDemo.GetBool() ) {
373 common->Printf( "write DC_RENDERVIEW: %i\n", renderView->time );
374 }
375 }
376
377 /*
378 ================
379 WriteFreeEntity
380 ================
381 */
WriteFreeEntity(qhandle_t handle)382 void idRenderWorldLocal::WriteFreeEntity( qhandle_t handle ) {
383
384 // only the main renderWorld writes stuff to demos, not the wipes or
385 // menu renders
386 if ( this != session->rw ) {
387 return;
388 }
389
390 session->writeDemo->WriteInt( DS_RENDER );
391 session->writeDemo->WriteInt( DC_DELETE_ENTITYDEF );
392 session->writeDemo->WriteInt( handle );
393
394 if ( r_showDemo.GetBool() ) {
395 common->Printf( "write DC_DELETE_ENTITYDEF: %i\n", handle );
396 }
397 }
398
399 /*
400 ================
401 WriteFreeLightEntity
402 ================
403 */
WriteFreeLight(qhandle_t handle)404 void idRenderWorldLocal::WriteFreeLight( qhandle_t handle ) {
405
406 // only the main renderWorld writes stuff to demos, not the wipes or
407 // menu renders
408 if ( this != session->rw ) {
409 return;
410 }
411
412 session->writeDemo->WriteInt( DS_RENDER );
413 session->writeDemo->WriteInt( DC_DELETE_LIGHTDEF );
414 session->writeDemo->WriteInt( handle );
415
416 if ( r_showDemo.GetBool() ) {
417 common->Printf( "write DC_DELETE_LIGHTDEF: %i\n", handle );
418 }
419 }
420
421 /*
422 ================
423 WriteRenderLight
424 ================
425 */
WriteRenderLight(qhandle_t handle,const renderLight_t * light)426 void idRenderWorldLocal::WriteRenderLight( qhandle_t handle, const renderLight_t *light ) {
427
428 // only the main renderWorld writes stuff to demos, not the wipes or
429 // menu renders
430 if ( this != session->rw ) {
431 return;
432 }
433
434 session->writeDemo->WriteInt( DS_RENDER );
435 session->writeDemo->WriteInt( DC_UPDATE_LIGHTDEF );
436 session->writeDemo->WriteInt( handle );
437
438 session->writeDemo->WriteMat3( light->axis );
439 session->writeDemo->WriteVec3( light->origin );
440 session->writeDemo->WriteInt( light->suppressLightInViewID );
441 session->writeDemo->WriteInt( light->allowLightInViewID );
442 session->writeDemo->WriteBool( light->noShadows );
443 session->writeDemo->WriteBool( light->noSpecular );
444 session->writeDemo->WriteBool( light->pointLight );
445 session->writeDemo->WriteBool( light->parallel );
446 session->writeDemo->WriteVec3( light->lightRadius );
447 session->writeDemo->WriteVec3( light->lightCenter );
448 session->writeDemo->WriteVec3( light->target );
449 session->writeDemo->WriteVec3( light->right );
450 session->writeDemo->WriteVec3( light->up );
451 session->writeDemo->WriteVec3( light->start );
452 session->writeDemo->WriteVec3( light->end );
453 session->writeDemo->WriteInt( light->prelightModel ? 1 : 0 );
454 session->writeDemo->WriteInt( light->lightId );
455 session->writeDemo->WriteInt( light->shader ? 1 : 0);
456 for ( int i = 0; i < MAX_ENTITY_SHADER_PARMS; i++)
457 session->writeDemo->WriteFloat( light->shaderParms[i] );
458 session->writeDemo->WriteInt( light->referenceSound ? 1 : 0 );
459
460 if ( light->prelightModel ) {
461 session->writeDemo->WriteHashString( light->prelightModel->Name() );
462 }
463 if ( light->shader ) {
464 session->writeDemo->WriteHashString( light->shader->GetName() );
465 }
466 if ( light->referenceSound ) {
467 int index = light->referenceSound->Index();
468 session->writeDemo->WriteInt( index );
469 }
470
471 if ( r_showDemo.GetBool() ) {
472 common->Printf( "write DC_UPDATE_LIGHTDEF: %i\n", handle );
473 }
474 }
475
476 /*
477 ================
478 ReadRenderLight
479 ================
480 */
ReadRenderLight()481 void idRenderWorldLocal::ReadRenderLight( ) {
482 renderLight_t light;
483 int index, i;
484 int prelightModel, shader, referenceSound;
485
486 session->readDemo->ReadInt( index );
487 if ( index < 0 ) {
488 common->Error( "ReadRenderLight: index < 0 " );
489 }
490
491 session->readDemo->ReadMat3( light.axis );
492 session->readDemo->ReadVec3( light.origin );
493 session->readDemo->ReadInt( light.suppressLightInViewID );
494 session->readDemo->ReadInt( light.allowLightInViewID );
495 session->readDemo->ReadBool( light.noShadows );
496 session->readDemo->ReadBool( light.noSpecular );
497 session->readDemo->ReadBool( light.pointLight );
498 session->readDemo->ReadBool( light.parallel );
499 session->readDemo->ReadVec3( light.lightRadius );
500 session->readDemo->ReadVec3( light.lightCenter );
501 session->readDemo->ReadVec3( light.target );
502 session->readDemo->ReadVec3( light.right );
503 session->readDemo->ReadVec3( light.up );
504 session->readDemo->ReadVec3( light.start );
505 session->readDemo->ReadVec3( light.end );
506 session->readDemo->ReadInt( prelightModel );
507 session->readDemo->ReadInt( light.lightId );
508 session->readDemo->ReadInt( shader );
509 for ( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++)
510 session->readDemo->ReadFloat( light.shaderParms[i] );
511 session->readDemo->ReadInt( referenceSound );
512 if ( prelightModel )
513 light.prelightModel = renderModelManager->FindModel( session->readDemo->ReadHashString() );
514 else
515 light.prelightModel = NULL;
516 if ( shader )
517 light.shader = declManager->FindMaterial( session->readDemo->ReadHashString() );
518 else
519 light.shader = NULL;
520 if ( referenceSound ) {
521 session->readDemo->ReadInt( i );
522 light.referenceSound = session->sw->EmitterForIndex( i );
523 } else {
524 light.referenceSound = NULL;
525 }
526
527 UpdateLightDef( index, &light );
528
529 if ( r_showDemo.GetBool() ) {
530 common->Printf( "DC_UPDATE_LIGHTDEF: %i\n", index );
531 }
532 }
533
534 /*
535 ================
536 WriteRenderEntity
537 ================
538 */
WriteRenderEntity(qhandle_t handle,const renderEntity_t * ent)539 void idRenderWorldLocal::WriteRenderEntity( qhandle_t handle, const renderEntity_t *ent ) {
540
541 // only the main renderWorld writes stuff to demos, not the wipes or
542 // menu renders
543 if ( this != session->rw ) {
544 return;
545 }
546
547 session->writeDemo->WriteInt( DS_RENDER );
548 session->writeDemo->WriteInt( DC_UPDATE_ENTITYDEF );
549 session->writeDemo->WriteInt( handle );
550
551 session->writeDemo->WriteInt( ent->hModel ? 1 : 0);
552 session->writeDemo->WriteInt( ent->entityNum );
553 session->writeDemo->WriteInt( ent->bodyId );
554 session->writeDemo->WriteVec3( ent->bounds[0] );
555 session->writeDemo->WriteVec3( ent->bounds[1] );
556 session->writeDemo->WriteInt( 0 ); //ent->callback
557 session->writeDemo->WriteInt( 0 ); //ent->callbackData
558 session->writeDemo->WriteInt( ent->suppressSurfaceInViewID );
559 session->writeDemo->WriteInt( ent->suppressShadowInViewID );
560 session->writeDemo->WriteInt( ent->suppressShadowInLightID );
561 session->writeDemo->WriteInt( ent->allowSurfaceInViewID );
562 session->writeDemo->WriteVec3( ent->origin );
563 session->writeDemo->WriteMat3( ent->axis );
564 session->writeDemo->WriteInt( ent->customShader ? 1 : 0 );
565 session->writeDemo->WriteInt( ent->referenceShader ? 1 : 0 );
566 session->writeDemo->WriteInt( ent->customSkin ? 1 : 0 );
567 session->writeDemo->WriteInt( ent->referenceSound ? 1 : 0 );
568 for ( int i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ )
569 session->writeDemo->WriteFloat( ent->shaderParms[i] );
570 for ( int i = 0; i < MAX_RENDERENTITY_GUI; i++ )
571 session->writeDemo->WriteInt( ent->gui[i] ? 1 : 0 );
572 session->writeDemo->WriteInt( 0 ); //ent->remoteRenderView
573 session->writeDemo->WriteInt( ent->numJoints );
574 session->writeDemo->WriteInt( 0 ); //ent->joints
575 session->writeDemo->WriteFloat( ent->modelDepthHack );
576 session->writeDemo->WriteBool( ent->noSelfShadow );
577 session->writeDemo->WriteBool( ent->noShadow );
578 session->writeDemo->WriteBool( ent->noDynamicInteractions );
579 session->writeDemo->WriteBool( ent->weaponDepthHack );
580 session->writeDemo->WriteInt( ent->forceUpdate );
581
582 if ( ent->customShader ) {
583 session->writeDemo->WriteHashString( ent->customShader->GetName() );
584 }
585 if ( ent->customSkin ) {
586 session->writeDemo->WriteHashString( ent->customSkin->GetName() );
587 }
588 if ( ent->hModel ) {
589 session->writeDemo->WriteHashString( ent->hModel->Name() );
590 }
591 if ( ent->referenceShader ) {
592 session->writeDemo->WriteHashString( ent->referenceShader->GetName() );
593 }
594 if ( ent->referenceSound ) {
595 int index = ent->referenceSound->Index();
596 session->writeDemo->WriteInt( index );
597 }
598 if ( ent->numJoints ) {
599 for ( int i = 0; i < ent->numJoints; i++) {
600 float *data = ent->joints[i].ToFloatPtr();
601 for ( int j = 0; j < 12; ++j)
602 session->writeDemo->WriteFloat( data[j] );
603 }
604 }
605
606 /*
607 if ( ent->decals ) {
608 ent->decals->WriteToDemoFile( session->readDemo );
609 }
610 if ( ent->overlay ) {
611 ent->overlay->WriteToDemoFile( session->writeDemo );
612 }
613 */
614
615 #ifdef WRITE_GUIS
616 if ( ent->gui ) {
617 ent->gui->WriteToDemoFile( session->writeDemo );
618 }
619 if ( ent->gui2 ) {
620 ent->gui2->WriteToDemoFile( session->writeDemo );
621 }
622 if ( ent->gui3 ) {
623 ent->gui3->WriteToDemoFile( session->writeDemo );
624 }
625 #endif
626
627 // RENDERDEMO_VERSION >= 2 ( Doom3 1.2 )
628 session->writeDemo->WriteInt( ent->timeGroup );
629 session->writeDemo->WriteInt( ent->xrayIndex );
630
631 if ( r_showDemo.GetBool() ) {
632 common->Printf( "write DC_UPDATE_ENTITYDEF: %i = %s\n", handle, ent->hModel ? ent->hModel->Name() : "NULL" );
633 }
634 }
635
636 /*
637 ================
638 ReadRenderEntity
639 ================
640 */
ReadRenderEntity()641 void idRenderWorldLocal::ReadRenderEntity() {
642 renderEntity_t ent;
643 int index, i, tmp, hModel, customShader, referenceShader;
644 int customSkin, referenceSound, gui[MAX_RENDERENTITY_GUI];
645
646 session->readDemo->ReadInt( index );
647 if ( index < 0 ) {
648 common->Error( "ReadRenderEntity: index < 0" );
649 }
650
651 session->readDemo->ReadInt( hModel );
652 session->readDemo->ReadInt( ent.entityNum );
653 session->readDemo->ReadInt( ent.bodyId );
654 session->readDemo->ReadVec3( ent.bounds[0] );
655 session->readDemo->ReadVec3( ent.bounds[1] );
656 session->readDemo->ReadInt( tmp ); //ent.callback
657 session->readDemo->ReadInt( tmp ); //ent.callbackData
658 session->readDemo->ReadInt( ent.suppressSurfaceInViewID );
659 session->readDemo->ReadInt( ent.suppressShadowInViewID );
660 session->readDemo->ReadInt( ent.suppressShadowInLightID );
661 session->readDemo->ReadInt( ent.allowSurfaceInViewID );
662 session->readDemo->ReadVec3( ent.origin );
663 session->readDemo->ReadMat3( ent.axis );
664 session->readDemo->ReadInt( customShader );
665 session->readDemo->ReadInt( referenceShader );
666 session->readDemo->ReadInt( customSkin );
667 session->readDemo->ReadInt( referenceSound );
668 for ( i = 0; i < MAX_ENTITY_SHADER_PARMS; i++ ) {
669 session->readDemo->ReadFloat( ent.shaderParms[i] );
670 }
671 for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
672 session->readDemo->ReadInt( gui[i] );
673 }
674 session->readDemo->ReadInt( tmp ); //ent.remoteRenderView
675 session->readDemo->ReadInt( ent.numJoints );
676 session->readDemo->ReadInt( tmp ); //ent.joints
677 session->readDemo->ReadFloat( ent.modelDepthHack );
678 session->readDemo->ReadBool( ent.noSelfShadow );
679 session->readDemo->ReadBool( ent.noShadow );
680 session->readDemo->ReadBool( ent.noDynamicInteractions );
681 session->readDemo->ReadBool( ent.weaponDepthHack );
682 session->readDemo->ReadInt( ent.forceUpdate );
683 ent.callback = NULL;
684 if ( customShader )
685 ent.customShader = declManager->FindMaterial( session->readDemo->ReadHashString() );
686 else
687 ent.customShader = NULL;
688 if ( customSkin )
689 ent.customSkin = declManager->FindSkin( session->readDemo->ReadHashString() );
690 else
691 ent.customSkin = NULL;
692 if ( hModel )
693 ent.hModel = renderModelManager->FindModel( session->readDemo->ReadHashString() );
694 else
695 ent.hModel = NULL;
696 if ( referenceShader )
697 ent.referenceShader = declManager->FindMaterial( session->readDemo->ReadHashString() );
698 else
699 ent.referenceShader = NULL;
700 if ( referenceSound ) {
701 session->readDemo->ReadInt( tmp );
702 ent.referenceSound = session->sw->EmitterForIndex( tmp );
703 } else {
704 ent.referenceSound = NULL;
705 }
706 ent.remoteRenderView = NULL;
707 if ( ent.numJoints ) {
708 ent.joints = (idJointMat *)Mem_Alloc16( ent.numJoints * sizeof( ent.joints[0] ) );
709 for ( int i = 0; i < ent.numJoints; i++) {
710 float *data = ent.joints[i].ToFloatPtr();
711 for ( int j = 0; j < 12; ++j)
712 session->readDemo->ReadFloat( data[j] );
713 }
714 } else {
715 ent.joints = NULL;
716 }
717 ent.callbackData = NULL;
718
719 /*
720 if ( ent.decals ) {
721 ent.decals = idRenderModelDecal::Alloc();
722 ent.decals->ReadFromDemoFile( session->readDemo );
723 }
724 if ( ent.overlay ) {
725 ent.overlay = idRenderModelOverlay::Alloc();
726 ent.overlay->ReadFromDemoFile( session->readDemo );
727 }
728 */
729
730 for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
731 if ( gui[ i ] ) {
732 ent.gui[ i ] = uiManager->Alloc();
733 #ifdef WRITE_GUIS
734 ent.gui[ i ]->ReadFromDemoFile( session->readDemo );
735 #endif
736 } else {
737 ent.gui[ i ] = NULL;
738 }
739 }
740
741 // >= Doom3 v1.2 only
742 if ( session->renderdemoVersion >= 2 ) {
743 session->readDemo->ReadInt( ent.timeGroup );
744 session->readDemo->ReadInt( ent.xrayIndex );
745 } else {
746 ent.timeGroup = 0;
747 ent.xrayIndex = 0;
748 }
749
750 UpdateEntityDef( index, &ent );
751
752 if ( r_showDemo.GetBool() ) {
753 common->Printf( "DC_UPDATE_ENTITYDEF: %i = %s\n", index, ent.hModel ? ent.hModel->Name() : "NULL" );
754 }
755 }
756