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.

737 lines
21 KiB

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