DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

RenderWorld_demo.cpp (21769B)


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