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.

779 lines
22 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "vbsp.h"
  9. #include "utilmatlib.h"
  10. #include "physdll.h"
  11. #include <assert.h>
  12. #include <malloc.h>
  13. #include "tier1/strtools.h"
  14. #include "materialpatch.h"
  15. #include "keyvalues.h"
  16. void LoadSurfaceProperties( void );
  17. IPhysicsSurfaceProps *physprops = NULL;
  18. int nummiptex;
  19. textureref_t textureref[MAX_MAP_TEXTURES];
  20. bool g_bHasWater = false;
  21. extern qboolean onlyents;
  22. dtexdata_t *GetTexData( int index )
  23. {
  24. if ( index < 0 )
  25. return NULL;
  26. Assert( !onlyents );
  27. return &dtexdata[ index ];
  28. }
  29. static qboolean StringIsTrue( const char *str )
  30. {
  31. if( Q_strcasecmp( str, "true" ) == 0 )
  32. {
  33. return true;
  34. }
  35. if( Q_strcasecmp( str, "1" ) == 0 )
  36. {
  37. return true;
  38. }
  39. return false;
  40. }
  41. int FindMiptex (const char *name)
  42. {
  43. int i;
  44. MaterialSystemMaterial_t matID;
  45. const char *propVal, *propVal2;
  46. int opacity;
  47. bool found;
  48. for (i=0 ; i<nummiptex ; i++)
  49. {
  50. if (!strcmp (name, textureref[i].name))
  51. {
  52. return i;
  53. }
  54. }
  55. if (nummiptex == MAX_MAP_TEXTURES)
  56. Error ("Too many unique textures, max %d", MAX_MAP_TEXTURES);
  57. strcpy (textureref[i].name, name);
  58. textureref[i].lightmapWorldUnitsPerLuxel = 0.0f;
  59. textureref[i].flags = 0;
  60. textureref[i].contents = 0;
  61. matID = FindOriginalMaterial( name, &found );
  62. if( matID == MATERIAL_NOT_FOUND )
  63. {
  64. return 0;
  65. }
  66. if (!found)
  67. Warning("Material not found!: %s\n", name );
  68. // HANDLE ALL OF THE STUFF THAT ISN'T RENDERED WITH THE MATERIAL THAT IS ONE IT.
  69. // can't have portals
  70. if ( ( propVal = GetMaterialVar( matID, "%noPortal" ) ) &&
  71. StringIsTrue( propVal ) )
  72. {
  73. textureref[i].flags |= SURF_NOPORTAL;
  74. }
  75. // can't have paint
  76. if ( ( propVal = GetMaterialVar( matID, "%noPaint" ) ) &&
  77. StringIsTrue( propVal ) )
  78. {
  79. textureref[i].flags |= SURF_NOPAINT;
  80. }
  81. // handle sky
  82. if( ( propVal = GetMaterialVar( matID, "%compileSky" ) ) &&
  83. StringIsTrue( propVal ) )
  84. {
  85. textureref[i].flags |= SURF_SKY | SURF_NOLIGHT;
  86. }
  87. else if( ( propVal = GetMaterialVar( matID, "%compile2DSky" ) ) &&
  88. StringIsTrue( propVal ) )
  89. {
  90. textureref[i].flags |= SURF_SKY | SURF_SKY2D | SURF_NOLIGHT;
  91. }
  92. // handle hint brushes
  93. else if ( ( propVal = GetMaterialVar( matID, "%compileHint" ) ) &&
  94. StringIsTrue( propVal ) )
  95. {
  96. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT | SURF_HINT;
  97. }
  98. // handle skip faces
  99. else if ( ( propVal = GetMaterialVar( matID, "%compileSkip" ) ) &&
  100. StringIsTrue( propVal ) )
  101. {
  102. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT | SURF_SKIP;
  103. }
  104. // handle origin brushes
  105. else if ( ( propVal = GetMaterialVar( matID, "%compileOrigin" ) ) &&
  106. StringIsTrue( propVal ) )
  107. {
  108. textureref[i].contents |= CONTENTS_ORIGIN | CONTENTS_DETAIL;
  109. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT;
  110. }
  111. // handle clip brushes
  112. else if ( ( propVal = GetMaterialVar( matID, "%compileClip" ) ) &&
  113. StringIsTrue( propVal ) )
  114. {
  115. textureref[i].contents |= CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP;
  116. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT;
  117. }
  118. else if ( ( propVal = GetMaterialVar( matID, "%playerClip" ) ) &&
  119. StringIsTrue( propVal ) )
  120. {
  121. textureref[i].contents |= CONTENTS_PLAYERCLIP;
  122. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT;
  123. }
  124. // handle npc clip brushes
  125. else if ( ( propVal = GetMaterialVar( matID, "%compileNpcClip" ) ) &&
  126. StringIsTrue( propVal ) )
  127. {
  128. textureref[i].contents |= CONTENTS_MONSTERCLIP;
  129. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT;
  130. }
  131. // handle surface lights which are meant to
  132. else if ( ( propVal = GetMaterialVar( matID, "%compileNoChop" ) ) &&
  133. StringIsTrue( propVal ) )
  134. {
  135. textureref[i].flags |= SURF_NOCHOP;
  136. }
  137. // handle triggers
  138. else if ( ( propVal = GetMaterialVar( matID, "%compileTrigger" ) ) &&
  139. StringIsTrue( propVal ) )
  140. {
  141. textureref[i].flags |= ( SURF_NOLIGHT | SURF_TRIGGER );
  142. if ( g_NodrawTriggers )
  143. {
  144. textureref[i].flags |= SURF_NODRAW;
  145. }
  146. }
  147. // handle nolight surfs (except water)
  148. else if ( (( propVal = GetMaterialVar( matID, "%compileNoLight" ) ) && StringIsTrue( propVal )) &&
  149. !(( propVal2 = GetMaterialVar( matID, "%compileWater" ) ) && StringIsTrue( propVal2 ) ) )
  150. {
  151. textureref[i].flags |= SURF_NOLIGHT;
  152. }
  153. // Handle grenade clip.
  154. else if ( ( propVal = GetMaterialVar( matID, "%compilegrenadeclip" ) ) && StringIsTrue( propVal ) )
  155. {
  156. textureref[i].contents |= CONTENTS_DETAIL;
  157. textureref[i].contents |= CONTENTS_GRENADECLIP;
  158. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT;
  159. }
  160. else
  161. {
  162. // HANDLE ALL OF THE STUFF THAT IS RENDERED WITH THE MATERIAL THAT IS ON IT.
  163. // Handle ladders.
  164. if ( ( propVal = GetMaterialVar( matID, "%compileLadder" ) ) && StringIsTrue( propVal ) )
  165. {
  166. textureref[i].contents |= CONTENTS_LADDER;
  167. }
  168. // Handle team-specific textures.
  169. if ( propVal = GetMaterialVar( matID, "%compileTeam" ) )
  170. {
  171. int val = atoi( propVal );
  172. if ( val == 1 )
  173. {
  174. textureref[i].contents |= CONTENTS_TEAM1;
  175. }
  176. else if ( val == 2 )
  177. {
  178. textureref[i].contents |= CONTENTS_TEAM2;
  179. }
  180. }
  181. // Handle hot surfaces (ice won't stick to them). We're piggybacking on SURF_NOPORTAL for now.
  182. if ( ( propVal = GetMaterialVar( matID, "%hotSurface" ) ) && StringIsTrue( propVal ) )
  183. {
  184. textureref[i].flags |= SURF_NOPORTAL;
  185. }
  186. if ( ( propVal = GetMaterialVar( matID, "%compilePassBullets" ) ) && StringIsTrue( propVal ) )
  187. {
  188. // change contents to grate, so bullets pass through
  189. // NOTE: This has effects on visibility too!
  190. textureref[i].contents &= ~CONTENTS_SOLID;
  191. textureref[i].contents |= CONTENTS_GRATE;
  192. }
  193. if( g_BumpAll || GetMaterialShaderPropertyBool( matID, UTILMATLIB_NEEDS_BUMPED_LIGHTMAPS ) )
  194. {
  195. textureref[i].flags |= SURF_BUMPLIGHT;
  196. }
  197. if( GetMaterialShaderPropertyBool( matID, UTILMATLIB_NEEDS_LIGHTMAP ) )
  198. {
  199. textureref[i].flags &= ~SURF_NOLIGHT;
  200. }
  201. else if( !g_bLightIfMissing )
  202. {
  203. textureref[i].flags |= SURF_NOLIGHT;
  204. }
  205. // handle nodraw faces/brushes
  206. if ( ( propVal = GetMaterialVar( matID, "%compileNoDraw" ) ) && StringIsTrue( propVal ) )
  207. {
  208. // textureref[i].contents |= CONTENTS_DETAIL;
  209. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT;
  210. }
  211. // Just a combination of nodraw + pass bullets, makes things easier
  212. if ( ( propVal = GetMaterialVar( matID, "%compileInvisible" ) ) && StringIsTrue( propVal ) )
  213. {
  214. // change contents to grate, so bullets pass through
  215. // NOTE: This has effects on visibility too!
  216. textureref[i].contents &= ~CONTENTS_SOLID;
  217. textureref[i].contents |= CONTENTS_GRATE;
  218. textureref[i].flags |= SURF_NODRAW | SURF_NOLIGHT;
  219. }
  220. bool checkWindow = true;
  221. // handle non solid
  222. if ( ( propVal = GetMaterialVar( matID, "%compileNonsolid" ) ) && StringIsTrue( propVal ) )
  223. {
  224. textureref[i].contents = CONTENTS_OPAQUE;
  225. // Non-Solid can't be a window either!
  226. checkWindow = false;
  227. }
  228. // handle block LOS
  229. if ( ( propVal = GetMaterialVar( matID, "%compileBlockLOS" ) ) && StringIsTrue( propVal ) )
  230. {
  231. textureref[i].contents = CONTENTS_BLOCKLOS;
  232. // BlockLOS can't be a window either!
  233. checkWindow = false;
  234. }
  235. if ( ( propVal = GetMaterialVar( matID, "%compileDetail" ) ) &&
  236. StringIsTrue( propVal ) )
  237. {
  238. textureref[i].contents |= CONTENTS_DETAIL;
  239. }
  240. bool bKeepLighting = ( ( propVal = GetMaterialVar( matID, "%compileKeepLight" ) ) &&
  241. StringIsTrue( propVal ) );
  242. // handle materials that want to be treated as water.
  243. if ( ( propVal = GetMaterialVar( matID, "%compileWater" ) ) &&
  244. StringIsTrue( propVal ) )
  245. {
  246. textureref[i].contents &= ~(CONTENTS_SOLID|CONTENTS_DETAIL);
  247. textureref[i].contents |= CONTENTS_WATER;
  248. textureref[i].flags |= SURF_WARP | SURF_NOSHADOWS | SURF_NODECALS;
  249. if ( g_DisableWaterLighting && !bKeepLighting )
  250. {
  251. textureref[i].flags |= SURF_NOLIGHT;
  252. }
  253. // Set this so that we can check at the end of the process the presence of a a WaterLODControl entity.
  254. g_bHasWater = true;
  255. }
  256. // handle materials that want to be treated as water.
  257. if ( ( propVal = GetMaterialVar( matID, "%compileNoShadows" ) ) &&
  258. StringIsTrue( propVal ) )
  259. {
  260. textureref[i].flags |= SURF_NOSHADOWS;
  261. }
  262. const char *pShaderName = GetMaterialShaderName(matID);
  263. if ( !Q_strncasecmp( pShaderName, "UnlitGeneric", 12 ) )
  264. {
  265. //if ( !(textureref[i].flags & SURF_NOLIGHT) )
  266. // Warning("Forcing lit materal %s to nolight\n", name );
  267. textureref[i].flags |= SURF_NOLIGHT;
  268. }
  269. if ( ( propVal = GetMaterialVar( matID, "%compileSlime" ) ) &&
  270. StringIsTrue( propVal ) )
  271. {
  272. textureref[i].contents &= ~(CONTENTS_SOLID|CONTENTS_DETAIL);
  273. textureref[i].contents |= CONTENTS_SLIME;
  274. textureref[i].flags |= SURF_NODECALS;
  275. // Set this so that we can check at the end of the process the presence of a a WaterLODControl entity.
  276. g_bHasWater = true;
  277. }
  278. opacity = GetMaterialShaderPropertyInt( matID, UTILMATLIB_OPACITY );
  279. if ( checkWindow && opacity != UTILMATLIB_OPAQUE )
  280. {
  281. // transparent *and solid* brushes that aren't grates or water must be windows
  282. if ( !(textureref[i].contents & (CONTENTS_GRATE|CONTENTS_WATER)) )
  283. {
  284. textureref[i].contents |= CONTENTS_WINDOW;
  285. }
  286. textureref[i].contents &= ~CONTENTS_SOLID;
  287. // this affects engine primitive sorting, SURF_TRANS means sort as a translucent primitive
  288. if ( opacity == UTILMATLIB_TRANSLUCENT )
  289. {
  290. textureref[i].flags |= SURF_TRANS;
  291. }
  292. }
  293. if ( textureref[i].flags & SURF_NOLIGHT )
  294. {
  295. textureref[i].flags &= ~SURF_BUMPLIGHT;
  296. }
  297. }
  298. nummiptex++;
  299. return i;
  300. }
  301. /*
  302. ==================
  303. textureAxisFromPlane
  304. ==================
  305. */
  306. Vector baseaxis[18] =
  307. {
  308. Vector(0,0,1), Vector(1,0,0), Vector(0,-1,0), // floor
  309. Vector(0,0,-1), Vector(1,0,0), Vector(0,-1,0), // ceiling
  310. Vector(1,0,0), Vector(0,1,0), Vector(0,0,-1), // west wall
  311. Vector(-1,0,0), Vector(0,1,0), Vector(0,0,-1), // east wall
  312. Vector(0,1,0), Vector(1,0,0), Vector(0,0,-1), // south wall
  313. Vector(0,-1,0), Vector(1,0,0), Vector(0,0,-1) // north wall
  314. };
  315. void TextureAxisFromPlane(plane_t *pln, Vector& xv, Vector& yv)
  316. {
  317. int bestaxis;
  318. vec_t dot,best;
  319. int i;
  320. best = 0;
  321. bestaxis = 0;
  322. for (i=0 ; i<6 ; i++)
  323. {
  324. dot = DotProduct (pln->normal, baseaxis[i*3]);
  325. if (dot > best)
  326. {
  327. best = dot;
  328. bestaxis = i;
  329. }
  330. }
  331. VectorCopy (baseaxis[bestaxis*3+1], xv);
  332. VectorCopy (baseaxis[bestaxis*3+2], yv);
  333. }
  334. int g_SurfaceProperties[MAX_MAP_TEXDATA];
  335. int GetSurfaceProperties( MaterialSystemMaterial_t matID, const char *pMatName )
  336. {
  337. const char *pPropString = NULL;
  338. int surfaceIndex = -1;
  339. if ( physprops )
  340. {
  341. pPropString = GetMaterialVar( matID, "$surfaceprop" );
  342. if ( pPropString )
  343. {
  344. surfaceIndex = physprops->GetSurfaceIndex( pPropString );
  345. if ( surfaceIndex < 0 )
  346. {
  347. Msg("Can't find surfaceprop %s for material %s, using default\n", pPropString, pMatName );
  348. surfaceIndex = physprops->GetSurfaceIndex( pPropString );
  349. surfaceIndex = physprops->GetSurfaceIndex( "default" );
  350. }
  351. }
  352. }
  353. return surfaceIndex;
  354. }
  355. int GetSurfaceProperties2( MaterialSystemMaterial_t matID, const char *pMatName, const char *pVarName )
  356. {
  357. const char *pPropString = NULL;
  358. int surfaceIndex = -1;
  359. if ( physprops )
  360. {
  361. pPropString = GetMaterialVar( matID, pVarName );
  362. if ( pPropString )
  363. {
  364. surfaceIndex = physprops->GetSurfaceIndex( pPropString );
  365. if ( surfaceIndex < 0 )
  366. {
  367. Msg("Can't find %s %s for material %s, using default\n", pVarName, pPropString, pMatName );
  368. surfaceIndex = physprops->GetSurfaceIndex( "default" );
  369. }
  370. }
  371. else
  372. {
  373. // No surface property 2.
  374. return -1;
  375. }
  376. }
  377. return surfaceIndex;
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Purpose: Finds or adds a texdata for the specified name ( same as below except
  381. // instead of finding the named texture, copies the settings from the passed
  382. // in sourceTexture. )
  383. // Used for creation of one off .vmt files for water surface textures
  384. // Input : *pName - texture name
  385. // Output : int index into dtexdata array
  386. //-----------------------------------------------------------------------------
  387. int FindAliasedTexData( const char *pName_, dtexdata_t *sourceTexture )
  388. {
  389. char *pName = ( char * )_alloca( strlen( pName_ ) + 1 );
  390. strcpy( pName, pName_ );
  391. strlwr( pName );
  392. int i, output;
  393. bool found;
  394. dtexdata_t *pTexData;
  395. MaterialSystemMaterial_t matID;
  396. for ( i = 0; i < numtexdata; i++ )
  397. {
  398. if ( !strcmp( pName, TexDataStringTable_GetString( GetTexData( i )->nameStringTableID ) ) )
  399. return i;
  400. }
  401. output = numtexdata;
  402. if ( numtexdata >= MAX_MAP_TEXDATA )
  403. {
  404. Error( "Too many unique texture mappings, max = %d\n", MAX_MAP_TEXDATA );
  405. }
  406. pTexData = GetTexData( output );
  407. numtexdata++;
  408. // Save the name of the material.
  409. pTexData->nameStringTableID = TexDataStringTable_AddOrFindString( pName );
  410. // Get the width, height, view_width, view_height, and reflectivity from the material system.
  411. matID = FindOriginalMaterial( TexDataStringTable_GetString( sourceTexture->nameStringTableID ), &found, false );
  412. if( matID == MATERIAL_NOT_FOUND || (!found) )
  413. {
  414. qprintf( "WARNING: material not found: \"%s\"\n", pName );
  415. return -1;
  416. }
  417. GetMaterialDimensions( matID, &pTexData->width, &pTexData->height );
  418. pTexData->view_width = pTexData->width; // undone: what is this?
  419. pTexData->view_height = pTexData->height; // undone: what is this?
  420. GetMaterialReflectivity( matID, pTexData->reflectivity.Base() );
  421. g_SurfaceProperties[output] = GetSurfaceProperties( matID, pName );
  422. return output;
  423. }
  424. //-----------------------------------------------------------------------------
  425. // Finds a texdata for the specified name, returns -1 if not found
  426. //-----------------------------------------------------------------------------
  427. int FindTexData( const char *pName )
  428. {
  429. // Make sure the texdata doesn't already exist.
  430. for( int i = 0; i < numtexdata; i++ )
  431. {
  432. char const *pTexDataName = TexDataStringTable_GetString( GetTexData( i )->nameStringTableID );
  433. if ( !Q_stricmp( pTexDataName, pName ) )
  434. return i;
  435. }
  436. return -1;
  437. }
  438. //-----------------------------------------------------------------------------
  439. // Purpose: Finds or adds a texdata for the specified name
  440. // Input : *pName - texture name
  441. // Output : int index into dtexdata array
  442. //-----------------------------------------------------------------------------
  443. int FindOrCreateTexData( const char *pName_ )
  444. {
  445. char *pName = ( char * )_alloca( strlen( pName_ ) + 1 );
  446. strcpy( pName, pName_ );
  447. int nOutput = FindTexData( pName );
  448. if ( nOutput >= 0 )
  449. return nOutput;
  450. // Didn't find it, add a new one
  451. nOutput = numtexdata;
  452. if ( numtexdata >= MAX_MAP_TEXDATA )
  453. {
  454. Error( "Too many unique texture mappings, max = %d\n", MAX_MAP_TEXDATA );
  455. }
  456. dtexdata_t *pTexData = GetTexData( nOutput );
  457. numtexdata++;
  458. // Save the name of the material.
  459. pTexData->nameStringTableID = TexDataStringTable_AddOrFindString( pName );
  460. // Get the width, height, view_width, view_height, and reflectivity from the material system.
  461. bool bFound;
  462. MaterialSystemMaterial_t matID = FindOriginalMaterial( pName, &bFound );
  463. if ( matID == MATERIAL_NOT_FOUND || (!bFound) )
  464. {
  465. qprintf( "WARNING: material not found: \"%s\"\n", pName );
  466. return nOutput;
  467. }
  468. GetMaterialDimensions( matID, &pTexData->width, &pTexData->height );
  469. pTexData->view_width = pTexData->width; // undone: what is this?
  470. pTexData->view_height = pTexData->height; // undone: what is this?
  471. GetMaterialReflectivity( matID, pTexData->reflectivity.Base() );
  472. g_SurfaceProperties[nOutput] = GetSurfaceProperties( matID, pName );
  473. #if 0
  474. Msg( "reflectivity: %f %f %f\n",
  475. pTexData->reflectivity[0],
  476. pTexData->reflectivity[1],
  477. pTexData->reflectivity[2] );
  478. #endif
  479. return nOutput;
  480. }
  481. int AddCloneTexData( dtexdata_t *pExistingTexData, char const *cloneTexDataName )
  482. {
  483. int existingIndex = pExistingTexData - GetTexData( 0 );
  484. dtexdata_t *pNewTexData = GetTexData( numtexdata );
  485. int newIndex = numtexdata;
  486. numtexdata++;
  487. *pNewTexData = *pExistingTexData;
  488. pNewTexData->nameStringTableID = TexDataStringTable_AddOrFindString( cloneTexDataName );
  489. g_SurfaceProperties[newIndex] = g_SurfaceProperties[existingIndex];
  490. return newIndex;
  491. }
  492. //-----------------------------------------------------------------------------
  493. // Finds a texinfo that exactly matches the passed in texinfo
  494. //-----------------------------------------------------------------------------
  495. int FindTexInfo( const texinfo_t &searchTexInfo )
  496. {
  497. for( int i = 0; i < texinfo.Count(); i++ )
  498. {
  499. // Just an early-out for performance
  500. if ( texinfo[i].texdata != searchTexInfo.texdata )
  501. continue;
  502. if ( !memcmp( &texinfo[i], &searchTexInfo, sizeof( texinfo_t ) ) )
  503. return i;
  504. }
  505. return -1;
  506. }
  507. //-----------------------------------------------------------------------------
  508. // Finds or creates a texinfo that exactly matches the passed in texinfo
  509. //-----------------------------------------------------------------------------
  510. int FindOrCreateTexInfo( const texinfo_t &searchTexInfo )
  511. {
  512. int i = FindTexInfo( searchTexInfo );
  513. if ( i >= 0 )
  514. return i;
  515. i = texinfo.AddToTail( searchTexInfo );
  516. if ( onlyents )
  517. {
  518. Error( "FindOrCreateTexInfo: Tried to create new texinfo during -onlyents compile!\nMust compile without -onlyents" );
  519. }
  520. return i;
  521. }
  522. int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, const Vector& origin)
  523. {
  524. Vector vecs[2];
  525. int sv, tv;
  526. vec_t ang, sinv, cosv;
  527. vec_t ns, nt;
  528. texinfo_t tx;
  529. int i, j;
  530. if (!bt->name[0])
  531. return 0;
  532. memset (&tx, 0, sizeof(tx));
  533. // HLTOOLS - add support for texture vectors stored in the map file
  534. if (g_nMapFileVersion < 220)
  535. {
  536. TextureAxisFromPlane(plane, vecs[0], vecs[1]);
  537. }
  538. if (!bt->textureWorldUnitsPerTexel[0])
  539. bt->textureWorldUnitsPerTexel[0] = 1;
  540. if (!bt->textureWorldUnitsPerTexel[1])
  541. bt->textureWorldUnitsPerTexel[1] = 1;
  542. float shiftScaleU = 1.0f / 16.0f;
  543. float shiftScaleV = 1.0f / 16.0f;
  544. if (g_nMapFileVersion < 220)
  545. {
  546. // rotate axis
  547. if (bt->rotate == 0)
  548. { sinv = 0 ; cosv = 1; }
  549. else if (bt->rotate == 90)
  550. { sinv = 1 ; cosv = 0; }
  551. else if (bt->rotate == 180)
  552. { sinv = 0 ; cosv = -1; }
  553. else if (bt->rotate == 270)
  554. { sinv = -1 ; cosv = 0; }
  555. else
  556. {
  557. ang = bt->rotate / 180 * M_PI;
  558. sinv = sin(ang);
  559. cosv = cos(ang);
  560. }
  561. if (vecs[0][0])
  562. sv = 0;
  563. else if (vecs[0][1])
  564. sv = 1;
  565. else
  566. sv = 2;
  567. if (vecs[1][0])
  568. tv = 0;
  569. else if (vecs[1][1])
  570. tv = 1;
  571. else
  572. tv = 2;
  573. for (i=0 ; i<2 ; i++)
  574. {
  575. ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
  576. nt = sinv * vecs[i][sv] + cosv * vecs[i][tv];
  577. vecs[i][sv] = ns;
  578. vecs[i][tv] = nt;
  579. }
  580. for (i=0 ; i<2 ; i++)
  581. {
  582. for (j=0 ; j<3 ; j++)
  583. {
  584. tx.textureVecsTexelsPerWorldUnits[i][j] = vecs[i][j] / bt->textureWorldUnitsPerTexel[i];
  585. tx.lightmapVecsLuxelsPerWorldUnits[i][j] = tx.textureVecsTexelsPerWorldUnits[i][j] / 16.0f;
  586. }
  587. }
  588. }
  589. else
  590. {
  591. tx.textureVecsTexelsPerWorldUnits[0][0] = bt->UAxis[0] / bt->textureWorldUnitsPerTexel[0];
  592. tx.textureVecsTexelsPerWorldUnits[0][1] = bt->UAxis[1] / bt->textureWorldUnitsPerTexel[0];
  593. tx.textureVecsTexelsPerWorldUnits[0][2] = bt->UAxis[2] / bt->textureWorldUnitsPerTexel[0];
  594. tx.textureVecsTexelsPerWorldUnits[1][0] = bt->VAxis[0] / bt->textureWorldUnitsPerTexel[1];
  595. tx.textureVecsTexelsPerWorldUnits[1][1] = bt->VAxis[1] / bt->textureWorldUnitsPerTexel[1];
  596. tx.textureVecsTexelsPerWorldUnits[1][2] = bt->VAxis[2] / bt->textureWorldUnitsPerTexel[1];
  597. tx.lightmapVecsLuxelsPerWorldUnits[0][0] = bt->UAxis[0] / bt->lightmapWorldUnitsPerLuxel;
  598. tx.lightmapVecsLuxelsPerWorldUnits[0][1] = bt->UAxis[1] / bt->lightmapWorldUnitsPerLuxel;
  599. tx.lightmapVecsLuxelsPerWorldUnits[0][2] = bt->UAxis[2] / bt->lightmapWorldUnitsPerLuxel;
  600. tx.lightmapVecsLuxelsPerWorldUnits[1][0] = bt->VAxis[0] / bt->lightmapWorldUnitsPerLuxel;
  601. tx.lightmapVecsLuxelsPerWorldUnits[1][1] = bt->VAxis[1] / bt->lightmapWorldUnitsPerLuxel;
  602. tx.lightmapVecsLuxelsPerWorldUnits[1][2] = bt->VAxis[2] / bt->lightmapWorldUnitsPerLuxel;
  603. shiftScaleU = bt->textureWorldUnitsPerTexel[0] / bt->lightmapWorldUnitsPerLuxel;
  604. shiftScaleV = bt->textureWorldUnitsPerTexel[1] / bt->lightmapWorldUnitsPerLuxel;
  605. }
  606. tx.textureVecsTexelsPerWorldUnits[0][3] = bt->shift[0] +
  607. DOT_PRODUCT( origin, tx.textureVecsTexelsPerWorldUnits[0] );
  608. tx.textureVecsTexelsPerWorldUnits[1][3] = bt->shift[1] +
  609. DOT_PRODUCT( origin, tx.textureVecsTexelsPerWorldUnits[1] );
  610. tx.lightmapVecsLuxelsPerWorldUnits[0][3] = shiftScaleU * bt->shift[0] +
  611. DOT_PRODUCT( origin, tx.lightmapVecsLuxelsPerWorldUnits[0] );
  612. tx.lightmapVecsLuxelsPerWorldUnits[1][3] = shiftScaleV * bt->shift[1] +
  613. DOT_PRODUCT( origin, tx.lightmapVecsLuxelsPerWorldUnits[1] );
  614. tx.flags = bt->flags;
  615. tx.texdata = FindOrCreateTexData( bt->name );
  616. // find the texinfo
  617. return FindOrCreateTexInfo( tx );
  618. }
  619. void LoadSurfacePropFile( const char *pMaterialFilename )
  620. {
  621. FileHandle_t fp = g_pFileSystem->Open( pMaterialFilename, "rb" );
  622. if ( fp == FILESYSTEM_INVALID_HANDLE )
  623. {
  624. return;
  625. }
  626. int len = g_pFileSystem->Size( fp );
  627. char *pText = new char[len];
  628. g_pFileSystem->Read( pText, len, fp );
  629. g_pFileSystem->Close( fp );
  630. physprops->ParseSurfaceData( pMaterialFilename, pText );
  631. delete[] pText;
  632. }
  633. //-----------------------------------------------------------------------------
  634. // Purpose: Loads the surface properties database into the physics DLL
  635. //-----------------------------------------------------------------------------
  636. void LoadSurfaceProperties( void )
  637. {
  638. CreateInterfaceFn physicsFactory = GetPhysicsFactory();
  639. if ( !physicsFactory )
  640. return;
  641. physprops = (IPhysicsSurfaceProps *)physicsFactory( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION, NULL );
  642. const char *SURFACEPROP_MANIFEST_FILE = "scripts/surfaceproperties_manifest.txt";
  643. KeyValues *manifest = new KeyValues( SURFACEPROP_MANIFEST_FILE );
  644. if ( manifest->LoadFromFile( g_pFileSystem, SURFACEPROP_MANIFEST_FILE, "GAME" ) )
  645. {
  646. for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() )
  647. {
  648. if ( !Q_stricmp( sub->GetName(), "file" ) )
  649. {
  650. // Add
  651. LoadSurfacePropFile( sub->GetString() );
  652. continue;
  653. }
  654. }
  655. }
  656. manifest->deleteThis();
  657. }