Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1297 lines
37 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "tier0/platform.h"
  8. #include "sysexternal.h"
  9. #include "cmodel_engine.h"
  10. #include "dispcoll_common.h"
  11. #include "modelloader.h"
  12. #include "common.h"
  13. #include "zone.h"
  14. // UNDONE: Abstract the texture/material lookup stuff and all of this goes away
  15. #include "materialsystem/imaterialsystem.h"
  16. #include "materialsystem/imaterial.h"
  17. #include "materialsystem/imaterialvar.h"
  18. #include "materialsystem/imaterialsystemhardwareconfig.h"
  19. #include "materialsystem/materialsystem_config.h"
  20. #include "vphysics_interface.h"
  21. #include "sys_dll.h"
  22. #include "tier3/tier3.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. IPhysicsSurfaceProps *physprops = NULL;
  26. IPhysicsCollision *physcollision = NULL;
  27. // local forward declarations
  28. void CollisionBSPData_LoadTextures( CCollisionBSPData *pBSPData );
  29. void CollisionBSPData_LoadTexinfo( CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texinfoCount );
  30. void CollisionBSPData_LoadLeafs_Version_0( CCollisionBSPData *pBSPData );
  31. void CollisionBSPData_LoadLeafs_Version_1( CCollisionBSPData *pBSPData );
  32. void CollisionBSPData_LoadLeafs( CCollisionBSPData *pBSPData );
  33. void CollisionBSPData_LoadLeafBrushes( CCollisionBSPData *pBSPData );
  34. void CollisionBSPData_LoadPlanes( CCollisionBSPData *pBSPData );
  35. void CollisionBSPData_LoadBrushes( CCollisionBSPData *pBSPData );
  36. void CollisionBSPData_LoadBrushSides( CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texinfoCount );
  37. void CollisionBSPData_LoadSubmodels( CCollisionBSPData *pBSPData );
  38. void CollisionBSPData_LoadNodes( CCollisionBSPData *pBSPData );
  39. void CollisionBSPData_LoadAreas( CCollisionBSPData *pBSPData );
  40. void CollisionBSPData_LoadAreaPortals( CCollisionBSPData *pBSPData );
  41. void CollisionBSPData_LoadVisibility( CCollisionBSPData *pBSPData );
  42. void CollisionBSPData_LoadEntityString( CCollisionBSPData *pBSPData );
  43. void CollisionBSPData_LoadPhysics( CCollisionBSPData *pBSPData );
  44. void CollisionBSPData_LoadDispInfo( CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texinfoCount );
  45. //=============================================================================
  46. //
  47. // Initialization/Destruction Functions
  48. //
  49. //-----------------------------------------------------------------------------
  50. //-----------------------------------------------------------------------------
  51. bool CollisionBSPData_Init( CCollisionBSPData *pBSPData )
  52. {
  53. pBSPData->numleafs = 1;
  54. pBSPData->map_vis = NULL;
  55. pBSPData->numareas = 1;
  56. pBSPData->numclusters = 1;
  57. pBSPData->map_nullname = "**empty**";
  58. pBSPData->numtextures = 0;
  59. return true;
  60. }
  61. //-----------------------------------------------------------------------------
  62. //-----------------------------------------------------------------------------
  63. void CollisionBSPData_Destroy( CCollisionBSPData *pBSPData )
  64. {
  65. for ( int i = 0; i < pBSPData->numcmodels; i++ )
  66. {
  67. physcollision->VCollideUnload( &pBSPData->map_cmodels[i].vcollisionData );
  68. }
  69. // free displacement data
  70. DispCollTrees_FreeLeafList( pBSPData );
  71. CM_DestroyDispPhysCollide();
  72. DispCollTrees_Free( g_pDispCollTrees );
  73. g_pDispCollTrees = NULL;
  74. g_pDispBounds = NULL;
  75. g_DispCollTreeCount = 0;
  76. if ( pBSPData->map_planes.Base() )
  77. {
  78. pBSPData->map_planes.Detach();
  79. }
  80. if ( pBSPData->map_texturenames )
  81. {
  82. pBSPData->map_texturenames = NULL;
  83. }
  84. if ( pBSPData->map_surfaces.Base() )
  85. {
  86. pBSPData->map_surfaces.Detach();
  87. }
  88. if ( pBSPData->map_areaportals.Base() )
  89. {
  90. pBSPData->map_areaportals.Detach();
  91. }
  92. if ( pBSPData->portalopen.Base() )
  93. {
  94. pBSPData->portalopen.Detach();
  95. }
  96. if ( pBSPData->map_areas.Base() )
  97. {
  98. pBSPData->map_areas.Detach();
  99. }
  100. pBSPData->map_entitystring.Discard();
  101. if ( pBSPData->map_brushes.Base() )
  102. {
  103. pBSPData->map_brushes.Detach();
  104. }
  105. if ( pBSPData->map_dispList.Base() )
  106. {
  107. pBSPData->map_dispList.Detach();
  108. }
  109. if ( pBSPData->map_cmodels.Base() )
  110. {
  111. pBSPData->map_cmodels.Detach();
  112. }
  113. if ( pBSPData->map_leafbrushes.Base() )
  114. {
  115. pBSPData->map_leafbrushes.Detach();
  116. }
  117. if ( pBSPData->map_leafs.Base() )
  118. {
  119. pBSPData->map_leafs.Detach();
  120. }
  121. if ( pBSPData->map_nodes.Base() )
  122. {
  123. pBSPData->map_nodes.Detach();
  124. }
  125. if ( pBSPData->map_brushsides.Base() )
  126. {
  127. pBSPData->map_brushsides.Detach();
  128. }
  129. if ( pBSPData->map_boxbrushes.Base() )
  130. {
  131. pBSPData->map_boxbrushes.Detach();
  132. }
  133. if ( pBSPData->map_vis )
  134. {
  135. pBSPData->map_vis = NULL;
  136. }
  137. pBSPData->numplanes = 0;
  138. pBSPData->numbrushsides = 0;
  139. pBSPData->emptyleaf = pBSPData->solidleaf =0;
  140. pBSPData->numnodes = 0;
  141. pBSPData->numleafs = 0;
  142. pBSPData->numbrushes = 0;
  143. pBSPData->numboxbrushes = 0;
  144. pBSPData->numdisplist = 0;
  145. pBSPData->numleafbrushes = 0;
  146. pBSPData->numareas = 0;
  147. pBSPData->numtextures = 0;
  148. pBSPData->floodvalid = 0;
  149. pBSPData->numareaportals = 0;
  150. pBSPData->numclusters = 0;
  151. pBSPData->numcmodels = 0;
  152. pBSPData->numvisibility = 0;
  153. pBSPData->numentitychars = 0;
  154. pBSPData->numportalopen = 0;
  155. pBSPData->mapPathName[0] = 0;
  156. pBSPData->map_rootnode = NULL;
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Returns the collision tree associated with the ith displacement
  160. //-----------------------------------------------------------------------------
  161. CDispCollTree* CollisionBSPData_GetCollisionTree( int i )
  162. {
  163. if ((i < 0) || (i >= g_DispCollTreeCount))
  164. return 0;
  165. return &g_pDispCollTrees[i];
  166. }
  167. //-----------------------------------------------------------------------------
  168. //-----------------------------------------------------------------------------
  169. void CollisionBSPData_LinkPhysics( void )
  170. {
  171. //
  172. // initialize the physics surface properties -- if necessary!
  173. //
  174. if( !physprops )
  175. {
  176. physprops = ( IPhysicsSurfaceProps* )g_AppSystemFactory( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION, NULL );
  177. physcollision = ( IPhysicsCollision* )g_AppSystemFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL );
  178. if ( !physprops || !physcollision )
  179. {
  180. Sys_Error( "CollisionBSPData_PreLoad: Can't link physics" );
  181. }
  182. }
  183. }
  184. //=============================================================================
  185. //
  186. // Loading Functions
  187. //
  188. //-----------------------------------------------------------------------------
  189. //-----------------------------------------------------------------------------
  190. //-----------------------------------------------------------------------------
  191. void CollisionBSPData_PreLoad( CCollisionBSPData *pBSPData )
  192. {
  193. // initialize the collision bsp data
  194. CollisionBSPData_Init( pBSPData );
  195. }
  196. //-----------------------------------------------------------------------------
  197. //-----------------------------------------------------------------------------
  198. bool CollisionBSPData_Load( const char *pPathName, CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texinfoCount )
  199. {
  200. // This is a table that maps texinfo references to csurface_t
  201. // It is freed after the map has been loaded
  202. // copy map name
  203. Q_strncpy( pBSPData->mapPathName, pPathName, sizeof( pBSPData->mapPathName ) );
  204. //
  205. // load bsp file data
  206. //
  207. COM_TimestampedLog( " CollisionBSPData_LoadTextures" );
  208. CollisionBSPData_LoadTextures( pBSPData );
  209. COM_TimestampedLog( " CollisionBSPData_LoadTexinfo" );
  210. CollisionBSPData_LoadTexinfo( pBSPData, pTexinfo, texinfoCount );
  211. COM_TimestampedLog( " CollisionBSPData_LoadLeafs" );
  212. CollisionBSPData_LoadLeafs( pBSPData );
  213. COM_TimestampedLog( " CollisionBSPData_LoadLeafBrushes" );
  214. CollisionBSPData_LoadLeafBrushes( pBSPData );
  215. COM_TimestampedLog( " CollisionBSPData_LoadPlanes" );
  216. CollisionBSPData_LoadPlanes( pBSPData );
  217. COM_TimestampedLog( " CollisionBSPData_LoadBrushes" );
  218. CollisionBSPData_LoadBrushes( pBSPData );
  219. COM_TimestampedLog( " CollisionBSPData_LoadBrushSides" );
  220. CollisionBSPData_LoadBrushSides( pBSPData, pTexinfo, texinfoCount );
  221. COM_TimestampedLog( " CollisionBSPData_LoadSubmodels" );
  222. CollisionBSPData_LoadSubmodels( pBSPData );
  223. COM_TimestampedLog( " CollisionBSPData_LoadPlanes" );
  224. CollisionBSPData_LoadNodes( pBSPData );
  225. COM_TimestampedLog( " CollisionBSPData_LoadAreas" );
  226. CollisionBSPData_LoadAreas( pBSPData );
  227. COM_TimestampedLog( " CollisionBSPData_LoadAreaPortals" );
  228. CollisionBSPData_LoadAreaPortals( pBSPData );
  229. COM_TimestampedLog( " CollisionBSPData_LoadVisibility" );
  230. CollisionBSPData_LoadVisibility( pBSPData );
  231. COM_TimestampedLog( " CollisionBSPData_LoadEntityString" );
  232. CollisionBSPData_LoadEntityString( pBSPData );
  233. COM_TimestampedLog( " CollisionBSPData_LoadPhysics" );
  234. CollisionBSPData_LoadPhysics( pBSPData );
  235. COM_TimestampedLog( " CollisionBSPData_LoadDispInfo" );
  236. CollisionBSPData_LoadDispInfo( pBSPData, pTexinfo, texinfoCount );
  237. return true;
  238. }
  239. //-----------------------------------------------------------------------------
  240. //-----------------------------------------------------------------------------
  241. void CollisionBSPData_LoadTextures( CCollisionBSPData *pBSPData )
  242. {
  243. CMapLoadHelper lh( LUMP_TEXDATA );
  244. CMapLoadHelper lhStringData( LUMP_TEXDATA_STRING_DATA );
  245. const char *pStringData = ( const char * )lhStringData.LumpBase();
  246. CMapLoadHelper lhStringTable( LUMP_TEXDATA_STRING_TABLE );
  247. if( lhStringTable.LumpSize() % sizeof( int ) )
  248. Sys_Error( "CMod_LoadTextures: funny lump size");
  249. int *pStringTable = ( int * )lhStringTable.LumpBase();
  250. dtexdata_t *in;
  251. int i, count;
  252. IMaterial *material;
  253. in = (dtexdata_t *)lh.LumpBase();
  254. if (lh.LumpSize() % sizeof(*in))
  255. {
  256. Sys_Error( "CMod_LoadTextures: funny lump size");
  257. }
  258. count = lh.LumpSize() / sizeof(*in);
  259. if (count < 1)
  260. {
  261. Sys_Error( "Map with no textures");
  262. }
  263. if (count > MAX_MAP_TEXDATA)
  264. {
  265. Sys_Error( "Map has too many textures");
  266. }
  267. int nSize = count * sizeof(csurface_t);
  268. pBSPData->map_surfaces.Attach( count, (csurface_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Textures" ) ) );
  269. pBSPData->numtextures = count;
  270. pBSPData->map_texturenames = (char *)Hunk_AllocName( lhStringData.LumpSize() * sizeof(char), va( "%s [%s]", lh.GetLoadName(), "Textures" ), false );
  271. memcpy( pBSPData->map_texturenames, pStringData, lhStringData.LumpSize() );
  272. for ( i=0 ; i<count ; i++, in++ )
  273. {
  274. Assert( in->nameStringTableID >= 0 );
  275. Assert( pStringTable[in->nameStringTableID] >= 0 );
  276. const char *pInName = &pStringData[pStringTable[in->nameStringTableID]];
  277. int index = pInName - pStringData;
  278. csurface_t *out = &pBSPData->map_surfaces[i];
  279. out->name = &pBSPData->map_texturenames[index];
  280. out->surfaceProps = 0;
  281. out->flags = 0;
  282. material = materials->FindMaterial( pBSPData->map_surfaces[i].name, TEXTURE_GROUP_WORLD, true );
  283. if ( !IsErrorMaterial( material ) )
  284. {
  285. IMaterialVar *var;
  286. bool varFound;
  287. var = material->FindVar( "$surfaceprop", &varFound, false );
  288. if ( varFound )
  289. {
  290. const char *pProps = var->GetStringValue();
  291. pBSPData->map_surfaces[i].surfaceProps = physprops->GetSurfaceIndex( pProps );
  292. }
  293. }
  294. }
  295. }
  296. //-----------------------------------------------------------------------------
  297. //-----------------------------------------------------------------------------
  298. void CollisionBSPData_LoadTexinfo( CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texinfoCount )
  299. {
  300. for ( int i=0 ; i<texinfoCount; i++ )
  301. {
  302. unsigned short out = pTexinfo[i].texdata;
  303. if ( out >= pBSPData->numtextures )
  304. out = 0;
  305. // HACKHACK: Copy this over for the whole material!!!
  306. pBSPData->map_surfaces[out].flags |= pTexinfo[i].flags;
  307. }
  308. }
  309. //-----------------------------------------------------------------------------
  310. //-----------------------------------------------------------------------------
  311. void CollisionBSPData_LoadLeafs_Version_0( CCollisionBSPData *pBSPData, CMapLoadHelper &lh )
  312. {
  313. int i;
  314. dleaf_version_0_t *in;
  315. int count;
  316. in = (dleaf_version_0_t *)lh.LumpBase();
  317. if (lh.LumpSize() % sizeof(*in))
  318. {
  319. Sys_Error( "CollisionBSPData_LoadLeafs: funny lump size");
  320. }
  321. count = lh.LumpSize() / sizeof(*in);
  322. if (count < 1)
  323. {
  324. Sys_Error( "Map with no leafs");
  325. }
  326. // need to save space for box planes
  327. if (count > MAX_MAP_PLANES)
  328. {
  329. Sys_Error( "Map has too many planes");
  330. }
  331. // Need an extra one for the emptyleaf below
  332. int nSize = (count + 1) * sizeof(cleaf_t);
  333. pBSPData->map_leafs.Attach( count + 1, (cleaf_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Leafs" ) ) );
  334. pBSPData->numleafs = count;
  335. pBSPData->numclusters = 0;
  336. int allcontents = 0;
  337. for ( i=0 ; i<count ; i++, in++ )
  338. {
  339. cleaf_t *out = &pBSPData->map_leafs[i];
  340. out->contents = in->contents;
  341. out->cluster = in->cluster;
  342. out->area = in->area;
  343. out->flags = in->flags;
  344. out->firstleafbrush = in->firstleafbrush;
  345. out->numleafbrushes = in->numleafbrushes;
  346. out->dispCount = 0;
  347. if (out->cluster >= pBSPData->numclusters)
  348. {
  349. pBSPData->numclusters = out->cluster + 1;
  350. }
  351. allcontents |= in->contents;
  352. }
  353. pBSPData->allcontents = allcontents;
  354. if (pBSPData->map_leafs[0].contents != CONTENTS_SOLID)
  355. {
  356. Sys_Error( "Map leaf 0 is not CONTENTS_SOLID");
  357. }
  358. pBSPData->solidleaf = 0;
  359. pBSPData->emptyleaf = pBSPData->numleafs;
  360. memset( &pBSPData->map_leafs[pBSPData->emptyleaf], 0, sizeof(pBSPData->map_leafs[pBSPData->emptyleaf]) );
  361. pBSPData->numleafs++;
  362. }
  363. //-----------------------------------------------------------------------------
  364. //-----------------------------------------------------------------------------
  365. void CollisionBSPData_LoadLeafs_Version_1( CCollisionBSPData *pBSPData, CMapLoadHelper &lh )
  366. {
  367. int i;
  368. dleaf_t *in;
  369. int count;
  370. in = (dleaf_t *)lh.LumpBase();
  371. if (lh.LumpSize() % sizeof(*in))
  372. {
  373. Sys_Error( "CollisionBSPData_LoadLeafs: funny lump size");
  374. }
  375. count = lh.LumpSize() / sizeof(*in);
  376. if (count < 1)
  377. {
  378. Sys_Error( "Map with no leafs");
  379. }
  380. // need to save space for box planes
  381. if (count > MAX_MAP_PLANES)
  382. {
  383. Sys_Error( "Map has too many planes");
  384. }
  385. // Need an extra one for the emptyleaf below
  386. int nSize = (count + 1) * sizeof(cleaf_t);
  387. pBSPData->map_leafs.Attach( count + 1, (cleaf_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Leafs" ) ) );
  388. pBSPData->numleafs = count;
  389. pBSPData->numclusters = 0;
  390. int allcontents = 0;
  391. for ( i=0 ; i<count ; i++, in++ )
  392. {
  393. cleaf_t *out = &pBSPData->map_leafs[i];
  394. out->contents = in->contents;
  395. out->cluster = in->cluster;
  396. out->area = in->area;
  397. out->flags = in->flags;
  398. out->firstleafbrush = in->firstleafbrush;
  399. out->numleafbrushes = in->numleafbrushes;
  400. out->dispCount = 0;
  401. if (out->cluster >= pBSPData->numclusters)
  402. {
  403. pBSPData->numclusters = out->cluster + 1;
  404. }
  405. allcontents |= in->contents;
  406. }
  407. pBSPData->allcontents = allcontents;
  408. if (pBSPData->map_leafs[0].contents != CONTENTS_SOLID)
  409. {
  410. Sys_Error( "Map leaf 0 is not CONTENTS_SOLID");
  411. }
  412. pBSPData->solidleaf = 0;
  413. pBSPData->emptyleaf = pBSPData->numleafs;
  414. memset( &pBSPData->map_leafs[pBSPData->emptyleaf], 0, sizeof(pBSPData->map_leafs[pBSPData->emptyleaf]) );
  415. pBSPData->numleafs++;
  416. }
  417. void CollisionBSPData_LoadLeafs( CCollisionBSPData *pBSPData )
  418. {
  419. pBSPData->allcontents = MASK_ALL;
  420. CMapLoadHelper lh( LUMP_LEAFS );
  421. switch( lh.LumpVersion() )
  422. {
  423. case 0:
  424. CollisionBSPData_LoadLeafs_Version_0( pBSPData, lh );
  425. break;
  426. case 1:
  427. CollisionBSPData_LoadLeafs_Version_1( pBSPData, lh );
  428. break;
  429. default:
  430. Assert( 0 );
  431. Error( "Unknown LUMP_LEAFS version\n" );
  432. break;
  433. }
  434. }
  435. //-----------------------------------------------------------------------------
  436. //-----------------------------------------------------------------------------
  437. void CollisionBSPData_LoadLeafBrushes( CCollisionBSPData *pBSPData )
  438. {
  439. CMapLoadHelper lh( LUMP_LEAFBRUSHES );
  440. int i;
  441. unsigned short *in;
  442. int count;
  443. in = (unsigned short *)lh.LumpBase();
  444. if (lh.LumpSize() % sizeof(*in))
  445. {
  446. Sys_Error( "CMod_LoadLeafBrushes: funny lump size");
  447. }
  448. count = lh.LumpSize() / sizeof(*in);
  449. if (count < 1)
  450. {
  451. Sys_Error( "Map with no planes");
  452. }
  453. // need to save space for box planes
  454. if (count > MAX_MAP_LEAFBRUSHES)
  455. {
  456. Sys_Error( "Map has too many leafbrushes");
  457. }
  458. pBSPData->map_leafbrushes.Attach( count, (unsigned short*)Hunk_AllocName( count * sizeof(unsigned short), va( "%s [%s]", lh.GetLoadName(), "LeafBrushes" ), false ) );
  459. pBSPData->numleafbrushes = count;
  460. for ( i=0 ; i<count ; i++, in++)
  461. {
  462. pBSPData->map_leafbrushes[i] = *in;
  463. }
  464. }
  465. //-----------------------------------------------------------------------------
  466. //-----------------------------------------------------------------------------
  467. void CollisionBSPData_LoadPlanes( CCollisionBSPData *pBSPData )
  468. {
  469. CMapLoadHelper lh( LUMP_PLANES );
  470. int i, j;
  471. dplane_t *in;
  472. int count;
  473. int bits;
  474. in = (dplane_t *)lh.LumpBase();
  475. if (lh.LumpSize() % sizeof(*in))
  476. {
  477. Sys_Error( "CollisionBSPData_LoadPlanes: funny lump size");
  478. }
  479. count = lh.LumpSize() / sizeof(*in);
  480. if (count < 1)
  481. {
  482. Sys_Error( "Map with no planes");
  483. }
  484. // need to save space for box planes
  485. if (count > MAX_MAP_PLANES)
  486. {
  487. Sys_Error( "Map has too many planes");
  488. }
  489. int nSize = count * sizeof(cplane_t);
  490. pBSPData->map_planes.Attach( count, (cplane_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Planes" ) ) );
  491. pBSPData->numplanes = count;
  492. for ( i=0 ; i<count ; i++, in++)
  493. {
  494. cplane_t *out = &pBSPData->map_planes[i];
  495. bits = 0;
  496. for (j=0 ; j<3 ; j++)
  497. {
  498. out->normal[j] = in->normal[j];
  499. if (out->normal[j] < 0)
  500. {
  501. bits |= 1<<j;
  502. }
  503. }
  504. out->dist = in->dist;
  505. out->type = in->type;
  506. out->signbits = bits;
  507. }
  508. }
  509. //-----------------------------------------------------------------------------
  510. //-----------------------------------------------------------------------------
  511. void CollisionBSPData_LoadBrushes( CCollisionBSPData *pBSPData )
  512. {
  513. CMapLoadHelper lh( LUMP_BRUSHES );
  514. dbrush_t *in;
  515. int i, count;
  516. in = (dbrush_t *)lh.LumpBase();
  517. if (lh.LumpSize() % sizeof(*in))
  518. {
  519. Sys_Error( "CMod_LoadBrushes: funny lump size");
  520. }
  521. count = lh.LumpSize() / sizeof(*in);
  522. if (count > MAX_MAP_BRUSHES)
  523. {
  524. Sys_Error( "Map has too many brushes");
  525. }
  526. int nSize = count * sizeof(cbrush_t);
  527. pBSPData->map_brushes.Attach( count, (cbrush_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Brushes" ) ) );
  528. pBSPData->numbrushes = count;
  529. for (i=0 ; i<count ; i++, in++)
  530. {
  531. cbrush_t *out = &pBSPData->map_brushes[i];
  532. out->firstbrushside = in->firstside;
  533. out->numsides = in->numsides;
  534. out->contents = in->contents;
  535. }
  536. }
  537. inline bool IsBoxBrush( const cbrush_t &brush, dbrushside_t *pSides, cplane_t *pPlanes )
  538. {
  539. int countAxial = 0;
  540. if ( brush.numsides == 6 )
  541. {
  542. for ( int i = 0; i < brush.numsides; i++ )
  543. {
  544. cplane_t *plane = pPlanes + pSides[brush.firstbrushside+i].planenum;
  545. if ( plane->type > PLANE_Z )
  546. break;
  547. countAxial++;
  548. }
  549. }
  550. return (countAxial == brush.numsides) ? true : false;
  551. }
  552. inline void ExtractBoxBrush( cboxbrush_t *pBox, const cbrush_t &brush, dbrushside_t *pSides, cplane_t *pPlanes, texinfo_t *pTexinfo, int texinfoCount )
  553. {
  554. // brush.numsides is no longer valid. Assume numsides == 6
  555. pBox->thinMask = 0;
  556. for ( int i = 0; i < 6; i++ )
  557. {
  558. dbrushside_t *side = pSides + i + brush.firstbrushside;
  559. cplane_t *plane = pPlanes + side->planenum;
  560. int t = side->texinfo;
  561. Assert(t<texinfoCount);
  562. int surfaceIndex = (t<0) ? SURFACE_INDEX_INVALID : pTexinfo[t].texdata;
  563. int axis = plane->type;
  564. Assert(fabs(plane->normal[axis])==1.0f);
  565. int maskIndex = axis;
  566. if ( plane->normal[axis] == 1.0f )
  567. {
  568. pBox->maxs[axis] = plane->dist;
  569. pBox->surfaceIndex[axis+3] = surfaceIndex;
  570. maskIndex += 3;
  571. }
  572. else if ( plane->normal[axis] == -1.0f )
  573. {
  574. pBox->mins[axis] = -plane->dist;
  575. pBox->surfaceIndex[axis] = surfaceIndex;
  576. }
  577. else
  578. {
  579. Assert(0);
  580. }
  581. pBox->thinMask |= side->thin << maskIndex;
  582. }
  583. pBox->pad = 0;
  584. }
  585. //-----------------------------------------------------------------------------
  586. //-----------------------------------------------------------------------------
  587. void CollisionBSPData_LoadBrushSides( CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texinfoCount )
  588. {
  589. CMapLoadHelper lh( LUMP_BRUSHSIDES );
  590. int i, j;
  591. dbrushside_t *in;
  592. in = (dbrushside_t *)lh.LumpBase();
  593. if (lh.LumpSize() % sizeof(*in))
  594. {
  595. Sys_Error( "CMod_LoadBrushSides: funny lump size");
  596. }
  597. int inputSideCount = lh.LumpSize() / sizeof(*in);
  598. // need to save space for box planes
  599. if (inputSideCount > MAX_MAP_BRUSHSIDES)
  600. {
  601. Sys_Error( "Map has too many planes");
  602. }
  603. // Brushes are compressed on load to remove any AABB brushes. The brushsides for those are removed
  604. // and those brushes are stored as cboxbrush_t. But the texinfo/surface data needs to be copied
  605. // So the algorithm is:
  606. //
  607. // count box brushes
  608. // count total brush sides
  609. // allocate
  610. // iterate brushes and copy sides or fill out box brushes
  611. // done
  612. //
  613. int boxBrushCount = 0;
  614. int brushSideCount = 0;
  615. for ( i = 0; i < pBSPData->numbrushes; i++ )
  616. {
  617. if ( IsBoxBrush(pBSPData->map_brushes[i], in, pBSPData->map_planes.Base()) )
  618. {
  619. // mark as axial
  620. pBSPData->map_brushes[i].numsides = NUMSIDES_BOXBRUSH;
  621. boxBrushCount++;
  622. }
  623. else
  624. {
  625. brushSideCount += pBSPData->map_brushes[i].numsides;
  626. }
  627. }
  628. int nSize = brushSideCount * sizeof(cbrushside_t);
  629. pBSPData->map_brushsides.Attach( brushSideCount, (cbrushside_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "BrushSides" ), false ) );
  630. pBSPData->map_boxbrushes.Attach( boxBrushCount, (cboxbrush_t*)Hunk_AllocName( boxBrushCount*sizeof(cboxbrush_t), va( "%s [%s]", lh.GetLoadName(), "BrushSides" ), false ) );
  631. pBSPData->numbrushsides = brushSideCount;
  632. pBSPData->numboxbrushes = boxBrushCount;
  633. int outBoxBrush = 0;
  634. int outBrushSide = 0;
  635. for ( i = 0; i < pBSPData->numbrushes; i++ )
  636. {
  637. cbrush_t *pBrush = &pBSPData->map_brushes[i];
  638. if ( pBrush->IsBox() )
  639. {
  640. // fill out the box brush - extract from the input sides
  641. cboxbrush_t *pBox = &pBSPData->map_boxbrushes[outBoxBrush];
  642. ExtractBoxBrush( pBox, *pBrush, in, pBSPData->map_planes.Base(), pTexinfo, texinfoCount );
  643. pBrush->SetBox(outBoxBrush);
  644. outBoxBrush++;
  645. }
  646. else
  647. {
  648. // copy each side into the output array
  649. int firstInputSide = pBrush->firstbrushside;
  650. pBrush->firstbrushside = outBrushSide;
  651. for ( j = 0; j < pBrush->numsides; j++ )
  652. {
  653. cbrushside_t * RESTRICT pSide = &pBSPData->map_brushsides[outBrushSide];
  654. dbrushside_t * RESTRICT pInputSide = in + firstInputSide + j;
  655. pSide->plane = &pBSPData->map_planes[pInputSide->planenum];
  656. int t = pInputSide->texinfo;
  657. if (t >= texinfoCount)
  658. {
  659. Sys_Error( "Bad brushside texinfo");
  660. }
  661. // BUGBUG: Why is vbsp writing out -1 as the texinfo id? (TEXINFO_NODE ?)
  662. pSide->surfaceIndex = (t < 0) ? SURFACE_INDEX_INVALID : pTexinfo[t].texdata;
  663. pSide->bBevel = pInputSide->bevel;
  664. pSide->bThin = pInputSide->thin;
  665. outBrushSide++;
  666. }
  667. }
  668. }
  669. Assert( outBrushSide == pBSPData->numbrushsides && outBoxBrush == pBSPData->numboxbrushes );
  670. }
  671. //-----------------------------------------------------------------------------
  672. //-----------------------------------------------------------------------------
  673. void CollisionBSPData_LoadSubmodels( CCollisionBSPData *pBSPData )
  674. {
  675. CMapLoadHelper lh( LUMP_MODELS );
  676. dmodel_t *in;
  677. int i, j, count;
  678. in = (dmodel_t *)lh.LumpBase();
  679. if (lh.LumpSize() % sizeof(*in))
  680. Sys_Error("CMod_LoadSubmodels: funny lump size");
  681. count = lh.LumpSize() / sizeof(*in);
  682. if (count < 1)
  683. Sys_Error( "Map with no models" );
  684. if (count > MAX_MAP_MODELS)
  685. Sys_Error( "Map has too many models" );
  686. int nSize = count * sizeof(cmodel_t);
  687. pBSPData->map_cmodels.Attach( count, (cmodel_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Submodels" ) ) );
  688. pBSPData->numcmodels = count;
  689. for ( i=0 ; i<count ; i++, in++ )
  690. {
  691. cmodel_t *out = &pBSPData->map_cmodels[i];
  692. for (j=0 ; j<3 ; j++)
  693. { // spread the mins / maxs by a pixel
  694. out->mins[j] = in->mins[j] - 1;
  695. out->maxs[j] = in->maxs[j] + 1;
  696. out->origin[j] = in->origin[j];
  697. }
  698. out->headnode = in->headnode;
  699. }
  700. }
  701. //-----------------------------------------------------------------------------
  702. //-----------------------------------------------------------------------------
  703. void CollisionBSPData_LoadNodes( CCollisionBSPData *pBSPData )
  704. {
  705. CMapLoadHelper lh( LUMP_NODES );
  706. dnode_t *in;
  707. int i, j, count;
  708. in = (dnode_t *)lh.LumpBase();
  709. if (lh.LumpSize() % sizeof(*in))
  710. Sys_Error( "CollisionBSPData_LoadNodes: funny lump size");
  711. count = lh.LumpSize() / sizeof(*in);
  712. if (count < 1)
  713. Sys_Error( "Map has no nodes");
  714. if (count > MAX_MAP_NODES)
  715. Sys_Error( "Map has too many nodes");
  716. // 6 extra for box hull
  717. int nSize = ( count + 6 ) * sizeof(cnode_t);
  718. pBSPData->map_nodes.Attach( count + 6, (cnode_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Nodes" ) ) );
  719. pBSPData->numnodes = count;
  720. pBSPData->map_rootnode = pBSPData->map_nodes.Base();
  721. for (i=0; i<count; i++, in++)
  722. {
  723. cnode_t *out = &pBSPData->map_nodes[i];
  724. out->plane = &pBSPData->map_planes[ in->planenum ];
  725. for (j=0; j<2; j++)
  726. {
  727. out->children[j] = in->children[j];
  728. }
  729. }
  730. }
  731. //-----------------------------------------------------------------------------
  732. //-----------------------------------------------------------------------------
  733. void CollisionBSPData_LoadAreas( CCollisionBSPData *pBSPData )
  734. {
  735. CMapLoadHelper lh( LUMP_AREAS );
  736. int i;
  737. darea_t *in;
  738. int count;
  739. in = (darea_t *)lh.LumpBase();
  740. if (lh.LumpSize() % sizeof(*in))
  741. {
  742. Sys_Error( "CMod_LoadAreas: funny lump size");
  743. }
  744. count = lh.LumpSize() / sizeof(*in);
  745. if (count > MAX_MAP_AREAS)
  746. {
  747. Sys_Error( "Map has too many areas");
  748. }
  749. int nSize = count * sizeof(carea_t);
  750. pBSPData->map_areas.Attach( count, (carea_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "Areas" ) ) );
  751. pBSPData->numareas = count;
  752. for ( i=0 ; i<count ; i++, in++)
  753. {
  754. carea_t *out = &pBSPData->map_areas[i];
  755. out->numareaportals = in->numareaportals;
  756. out->firstareaportal = in->firstareaportal;
  757. out->floodvalid = 0;
  758. out->floodnum = 0;
  759. }
  760. }
  761. //-----------------------------------------------------------------------------
  762. //-----------------------------------------------------------------------------
  763. void CollisionBSPData_LoadAreaPortals( CCollisionBSPData *pBSPData )
  764. {
  765. CMapLoadHelper lh( LUMP_AREAPORTALS );
  766. dareaportal_t *in;
  767. int count;
  768. in = (dareaportal_t *)lh.LumpBase();
  769. if (lh.LumpSize() % sizeof(*in))
  770. {
  771. Sys_Error( "CMod_LoadAreaPortals: funny lump size");
  772. }
  773. count = lh.LumpSize() / sizeof(*in);
  774. if (count > MAX_MAP_AREAPORTALS)
  775. {
  776. Sys_Error( "Map has too many area portals");
  777. }
  778. // Need to add one more in owing to 1-based instead of 0-based data!
  779. ++count;
  780. pBSPData->numportalopen = count;
  781. pBSPData->portalopen.Attach( count, (bool*)Hunk_AllocName( pBSPData->numportalopen * sizeof(bool), va( "%s [%s]", lh.GetLoadName(), "AreaPortals" ), false ) );
  782. for ( int i=0; i < pBSPData->numportalopen; i++ )
  783. {
  784. pBSPData->portalopen[i] = false;
  785. }
  786. pBSPData->numareaportals = count;
  787. int nSize = count * sizeof(dareaportal_t);
  788. pBSPData->map_areaportals.Attach( count, (dareaportal_t*)Hunk_AllocName( nSize, va( "%s [%s]", lh.GetLoadName(), "AreaPortals" ) ) );
  789. Assert( nSize >= lh.LumpSize() );
  790. memcpy( pBSPData->map_areaportals.Base(), in, lh.LumpSize() );
  791. }
  792. //-----------------------------------------------------------------------------
  793. //-----------------------------------------------------------------------------
  794. void CollisionBSPData_LoadVisibility( CCollisionBSPData *pBSPData )
  795. {
  796. CMapLoadHelper lh( LUMP_VISIBILITY );
  797. pBSPData->numvisibility = lh.LumpSize();
  798. if (lh.LumpSize() > MAX_MAP_VISIBILITY)
  799. Sys_Error( "Map has too large visibility lump");
  800. int visDataSize = lh.LumpSize();
  801. if ( visDataSize == 0 )
  802. {
  803. pBSPData->map_vis = NULL;
  804. }
  805. else
  806. {
  807. pBSPData->map_vis = (dvis_t *) Hunk_AllocName( visDataSize, va( "%s [%s]", lh.GetLoadName(), "Visibility" ), false );
  808. memcpy( pBSPData->map_vis, lh.LumpBase(), visDataSize );
  809. }
  810. }
  811. //-----------------------------------------------------------------------------
  812. //-----------------------------------------------------------------------------
  813. void CollisionBSPData_LoadEntityString( CCollisionBSPData *pBSPData )
  814. {
  815. CMapLoadHelper lh( LUMP_ENTITIES );
  816. pBSPData->numentitychars = lh.LumpSize();
  817. MEM_ALLOC_CREDIT();
  818. pBSPData->map_entitystring.Init( lh.GetDiskName(), lh.LumpOffset(), lh.LumpSize(), lh.LumpBase() );
  819. }
  820. //-----------------------------------------------------------------------------
  821. //-----------------------------------------------------------------------------
  822. void CollisionBSPData_LoadPhysics( CCollisionBSPData *pBSPData )
  823. {
  824. CMapLoadHelper lh( LUMP_PHYSCOLLIDE );
  825. if ( !lh.LumpSize() )
  826. return;
  827. byte *ptr = lh.LumpBase();
  828. byte *basePtr = ptr;
  829. dphysmodel_t physModel;
  830. // physics data is variable length. The last physmodel is a NULL pointer
  831. // with modelIndex -1, dataSize -1
  832. do
  833. {
  834. memcpy( &physModel, ptr, sizeof(physModel) );
  835. ptr += sizeof(physModel);
  836. if ( physModel.dataSize > 0 )
  837. {
  838. cmodel_t *pModel = &pBSPData->map_cmodels[ physModel.modelIndex ];
  839. physcollision->VCollideLoad( &pModel->vcollisionData, physModel.solidCount, (const char *)ptr, physModel.dataSize + physModel.keydataSize );
  840. ptr += physModel.dataSize;
  841. ptr += physModel.keydataSize;
  842. }
  843. // avoid infinite loop on badly formed file
  844. if ( (int)(ptr - basePtr) > lh.LumpSize() )
  845. break;
  846. } while ( physModel.dataSize > 0 );
  847. }
  848. //-----------------------------------------------------------------------------
  849. //-----------------------------------------------------------------------------
  850. void CollisionBSPData_LoadDispInfo( CCollisionBSPData *pBSPData, texinfo_t *pTexinfo, int texinfoCount )
  851. {
  852. // How many displacements in the map?
  853. CMapLoadHelper lhDispInfo( LUMP_DISPINFO );
  854. int coreDispCount = lhDispInfo.LumpSize() / sizeof( ddispinfo_t );
  855. if ( coreDispCount == 0 )
  856. return;
  857. //
  858. // get the vertex data
  859. //
  860. CMapLoadHelper lhv( LUMP_VERTEXES );
  861. dvertex_t *pVerts = ( dvertex_t* )lhv.LumpBase();
  862. if ( lhv.LumpSize() % sizeof( dvertex_t ) )
  863. Sys_Error( "CMod_LoadDispInfo: bad vertex lump size!" );
  864. //
  865. // get the edge data
  866. //
  867. CMapLoadHelper lhe( LUMP_EDGES );
  868. dedge_t *pEdges = ( dedge_t* )lhe.LumpBase();
  869. if ( lhe.LumpSize() % sizeof( dedge_t ) )
  870. Sys_Error( "CMod_LoadDispInfo: bad edge lump size!" );
  871. //
  872. // get surf edges data
  873. //
  874. CMapLoadHelper lhs( LUMP_SURFEDGES );
  875. int *pSurfEdges = ( int* )lhs.LumpBase();
  876. if ( lhs.LumpSize() % sizeof( int ) )
  877. Sys_Error( "CMod_LoadDispInfo: bad surf edge lump size!" );
  878. //
  879. // get face data
  880. //
  881. int face_lump_to_load = LUMP_FACES;
  882. if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE &&
  883. CMapLoadHelper::LumpSize( LUMP_FACES_HDR ) > 0 )
  884. {
  885. face_lump_to_load = LUMP_FACES_HDR;
  886. }
  887. CMapLoadHelper lhf( face_lump_to_load );
  888. dface_t *pFaces = ( dface_t* )lhf.LumpBase();
  889. if ( lhf.LumpSize() % sizeof( dface_t ) )
  890. Sys_Error( "CMod_LoadDispInfo: bad face lump size!" );
  891. int faceCount = lhf.LumpSize() / sizeof( dface_t );
  892. dface_t *pFaceList = pFaces;
  893. if ( !pFaceList )
  894. return;
  895. // allocate displacement collision trees
  896. g_DispCollTreeCount = coreDispCount;
  897. g_pDispCollTrees = DispCollTrees_Alloc( g_DispCollTreeCount );
  898. g_pDispBounds = (alignedbbox_t *)Hunk_AllocName( g_DispCollTreeCount * sizeof(alignedbbox_t), va( "%s [%s]", lhDispInfo.GetLoadName(), "DispInfo" ), false );
  899. // Build the inverse mapping from disp index to face
  900. int nMemSize = coreDispCount * sizeof(unsigned short);
  901. unsigned short *pDispIndexToFaceIndex = (unsigned short*)stackalloc( nMemSize );
  902. memset( pDispIndexToFaceIndex, 0xFF, nMemSize );
  903. int i;
  904. for ( i = 0; i < faceCount; ++i, ++pFaces )
  905. {
  906. // check face for displacement data
  907. if ( pFaces->dispinfo == -1 )
  908. continue;
  909. // get the current displacement build surface
  910. if ( pFaces->dispinfo >= coreDispCount )
  911. continue;
  912. pDispIndexToFaceIndex[pFaces->dispinfo] = (unsigned short)i;
  913. }
  914. // Load one dispinfo from disk at a time and set it up.
  915. int iCurVert = 0;
  916. int iCurTri = 0;
  917. int iCurMultiBlend = 0;
  918. CDispVert tempVerts[MAX_DISPVERTS];
  919. CDispTri tempTris[MAX_DISPTRIS];
  920. CDispMultiBlend tempMultiBlend[MAX_DISPVERTS];
  921. int nSize = 0;
  922. int nCacheSize = 0;
  923. int nPowerCount[3] = { 0, 0, 0 };
  924. CMapLoadHelper lhDispVerts( LUMP_DISP_VERTS );
  925. CMapLoadHelper lhDispTris( LUMP_DISP_TRIS );
  926. CMapLoadHelper lhDispMultiBLend( LUMP_DISP_MULTIBLEND );
  927. for ( i = 0; i < coreDispCount; ++i )
  928. {
  929. // Find the face associated with this dispinfo
  930. unsigned short nFaceIndex = pDispIndexToFaceIndex[i];
  931. if ( nFaceIndex == 0xFFFF )
  932. continue;
  933. // Load up the dispinfo and create the CCoreDispInfo from it.
  934. ddispinfo_t dispInfo;
  935. lhDispInfo.LoadLumpElement( i, sizeof(ddispinfo_t), &dispInfo );
  936. // Read in the vertices.
  937. int nVerts = NUM_DISP_POWER_VERTS( dispInfo.power );
  938. lhDispVerts.LoadLumpData( iCurVert * sizeof(CDispVert), nVerts*sizeof(CDispVert), tempVerts );
  939. iCurVert += nVerts;
  940. // Read in the tris.
  941. int nTris = NUM_DISP_POWER_TRIS( dispInfo.power );
  942. lhDispTris.LoadLumpData( iCurTri * sizeof( CDispTri ), nTris*sizeof( CDispTri), tempTris );
  943. iCurTri += nTris;
  944. int nFlags = 0;
  945. if ( ( dispInfo.minTess & DISP_INFO_FLAG_HAS_MULTIBLEND ) != 0 )
  946. {
  947. lhDispMultiBLend.LoadLumpData( iCurMultiBlend * sizeof( CDispMultiBlend ), nVerts * sizeof( CDispMultiBlend ), tempMultiBlend );
  948. iCurMultiBlend += nVerts;
  949. nFlags = DISP_INFO_FLAG_HAS_MULTIBLEND;
  950. }
  951. CCoreDispInfo coreDisp;
  952. CCoreDispSurface *pDispSurf = coreDisp.GetSurface();
  953. pDispSurf->SetPointStart( dispInfo.startPosition );
  954. pDispSurf->SetContents( dispInfo.contents );
  955. coreDisp.InitDispInfo( dispInfo.power, dispInfo.minTess, dispInfo.smoothingAngle, tempVerts, tempTris, nFlags, tempMultiBlend );
  956. // Hook the disp surface to the face
  957. pFaces = &pFaceList[ nFaceIndex ];
  958. pDispSurf->SetHandle( nFaceIndex );
  959. // get points
  960. if ( pFaces->numedges > 4 )
  961. continue;
  962. Vector surfPoints[4];
  963. pDispSurf->SetPointCount( pFaces->numedges );
  964. int j;
  965. for ( j = 0; j < pFaces->numedges; j++ )
  966. {
  967. int eIndex = pSurfEdges[pFaces->firstedge+j];
  968. if ( eIndex < 0 )
  969. {
  970. VectorCopy( pVerts[pEdges[-eIndex].v[1]].point, surfPoints[j] );
  971. }
  972. else
  973. {
  974. VectorCopy( pVerts[pEdges[eIndex].v[0]].point, surfPoints[j] );
  975. }
  976. }
  977. for ( j = 0; j < 4; j++ )
  978. {
  979. pDispSurf->SetPoint( j, surfPoints[j] );
  980. }
  981. pDispSurf->FindSurfPointStartIndex();
  982. pDispSurf->AdjustSurfPointData();
  983. //
  984. // generate the collision displacement surfaces
  985. //
  986. CDispCollTree *pDispTree = &g_pDispCollTrees[i];
  987. pDispTree->SetPower( 0 );
  988. //
  989. // check for null faces, should have been taken care of in vbsp!!!
  990. //
  991. int pointCount = pDispSurf->GetPointCount();
  992. if ( pointCount != 4 )
  993. continue;
  994. coreDisp.Create();
  995. // new collision
  996. pDispTree->Create( &coreDisp );
  997. g_pDispBounds[i].Init(pDispTree->m_mins, pDispTree->m_maxs, pDispTree->m_iCounter, pDispTree->GetContents());
  998. nSize += pDispTree->GetMemorySize();
  999. nCacheSize += pDispTree->GetCacheMemorySize();
  1000. nPowerCount[pDispTree->GetPower()-2]++;
  1001. // Surface props.
  1002. texinfo_t *pTex = &pTexinfo[pFaces->texinfo];
  1003. if ( pTex->texdata >= 0 )
  1004. {
  1005. IMaterial *pMaterial = materials->FindMaterial( pBSPData->map_surfaces[pTex->texdata].name, TEXTURE_GROUP_WORLD, true );
  1006. if ( !IsErrorMaterial( pMaterial ) )
  1007. {
  1008. IMaterialVar *pVar;
  1009. bool bVarFound;
  1010. pVar = pMaterial->FindVar( "$surfaceprop", &bVarFound, false );
  1011. if ( bVarFound )
  1012. {
  1013. const char *pProps = pVar->GetStringValue();
  1014. int nPropIndex = physprops->GetSurfaceIndex( pProps );
  1015. pDispTree->SetSurfaceProps( 0, nPropIndex );
  1016. pDispTree->SetSurfaceProps( 1, nPropIndex );
  1017. pDispTree->SetSurfaceProps( 2, nPropIndex );
  1018. pDispTree->SetSurfaceProps( 3, nPropIndex );
  1019. }
  1020. pVar = pMaterial->FindVar( "$surfaceprop2", &bVarFound, false );
  1021. if ( bVarFound )
  1022. {
  1023. const char *pProps = pVar->GetStringValue();
  1024. pDispTree->SetSurfaceProps( 1, physprops->GetSurfaceIndex( pProps ) );
  1025. }
  1026. pVar = pMaterial->FindVar( "$surfaceprop3", &bVarFound, false );
  1027. if ( bVarFound )
  1028. {
  1029. const char *pProps = pVar->GetStringValue();
  1030. pDispTree->SetSurfaceProps( 2, physprops->GetSurfaceIndex( pProps ) );
  1031. }
  1032. pVar = pMaterial->FindVar( "$surfaceprop4", &bVarFound, false );
  1033. if ( bVarFound )
  1034. {
  1035. const char *pProps = pVar->GetStringValue();
  1036. pDispTree->SetSurfaceProps( 3, physprops->GetSurfaceIndex( pProps ) );
  1037. }
  1038. }
  1039. pDispTree->SetTexinfoFlags( pBSPData->map_surfaces[pTex->texdata].flags );
  1040. }
  1041. }
  1042. CMapLoadHelper lhDispPhys( LUMP_PHYSDISP );
  1043. dphysdisp_t *pDispPhys = (dphysdisp_t *)lhDispPhys.LumpBase();
  1044. // create the vphysics collision models for each displacement
  1045. CM_CreateDispPhysCollide( pDispPhys, lhDispPhys.LumpSize() );
  1046. }
  1047. //=============================================================================
  1048. //
  1049. // Collision Count Functions
  1050. //
  1051. #ifdef COUNT_COLLISIONS
  1052. //-----------------------------------------------------------------------------
  1053. //-----------------------------------------------------------------------------
  1054. void CollisionCounts_Init( CCollisionCounts *pCounts )
  1055. {
  1056. pCounts->m_PointContents = 0;
  1057. pCounts->m_Traces = 0;
  1058. pCounts->m_BrushTraces = 0;
  1059. pCounts->m_DispTraces = 0;
  1060. pCounts->m_Stabs = 0;
  1061. }
  1062. #endif