Team Fortress 2 Source Code as on 22/4/2020
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.

1306 lines
36 KiB

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