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.

487 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "vbsp.h"
  8. #include "disp_vbsp.h"
  9. #include "builddisp.h"
  10. #include "mathlib/vmatrix.h"
  11. void Overlay_BuildBasisOrigin( doverlay_t *pOverlay );
  12. // Overlay list.
  13. CUtlVector<mapoverlay_t> g_aMapOverlays;
  14. CUtlVector<mapoverlay_t> g_aMapWaterOverlays;
  15. //-----------------------------------------------------------------------------
  16. //-----------------------------------------------------------------------------
  17. int Overlay_GetFromEntity( entity_t *pMapEnt )
  18. {
  19. int iAccessorID = -1;
  20. // Allocate the new overlay.
  21. int iOverlay = g_aMapOverlays.AddToTail();
  22. mapoverlay_t *pMapOverlay = &g_aMapOverlays[iOverlay];
  23. // Get the overlay data.
  24. pMapOverlay->nId = g_aMapOverlays.Count() - 1;
  25. if ( ValueForKey( pMapEnt, "targetname" )[ 0 ] != '\0' )
  26. {
  27. // Overlay has a name, remember it's ID for accessing
  28. iAccessorID = pMapOverlay->nId;
  29. }
  30. pMapOverlay->flU[0] = FloatForKey( pMapEnt, "StartU" );
  31. pMapOverlay->flU[1] = FloatForKey( pMapEnt, "EndU" );
  32. pMapOverlay->flV[0] = FloatForKey( pMapEnt, "StartV" );
  33. pMapOverlay->flV[1] = FloatForKey( pMapEnt, "EndV" );
  34. pMapOverlay->flFadeDistMinSq = FloatForKey( pMapEnt, "fademindist" );
  35. if ( pMapOverlay->flFadeDistMinSq > 0 )
  36. {
  37. pMapOverlay->flFadeDistMinSq *= pMapOverlay->flFadeDistMinSq;
  38. }
  39. pMapOverlay->flFadeDistMaxSq = FloatForKey( pMapEnt, "fademaxdist" );
  40. if ( pMapOverlay->flFadeDistMaxSq > 0 )
  41. {
  42. pMapOverlay->flFadeDistMaxSq *= pMapOverlay->flFadeDistMaxSq;
  43. }
  44. GetVectorForKey( pMapEnt, "BasisOrigin", pMapOverlay->vecOrigin );
  45. pMapOverlay->m_nRenderOrder = IntForKey( pMapEnt, "RenderOrder" );
  46. if ( pMapOverlay->m_nRenderOrder < 0 || pMapOverlay->m_nRenderOrder >= OVERLAY_NUM_RENDER_ORDERS )
  47. Error( "Overlay (%s) at %f %f %f has invalid render order (%d).\n", ValueForKey( pMapEnt, "material" ),
  48. pMapOverlay->vecOrigin.x, pMapOverlay->vecOrigin.y, pMapOverlay->vecOrigin.z,
  49. pMapOverlay->m_nRenderOrder );
  50. GetVectorForKey( pMapEnt, "uv0", pMapOverlay->vecUVPoints[0] );
  51. GetVectorForKey( pMapEnt, "uv1", pMapOverlay->vecUVPoints[1] );
  52. GetVectorForKey( pMapEnt, "uv2", pMapOverlay->vecUVPoints[2] );
  53. GetVectorForKey( pMapEnt, "uv3", pMapOverlay->vecUVPoints[3] );
  54. GetVectorForKey( pMapEnt, "BasisU", pMapOverlay->vecBasis[0] );
  55. GetVectorForKey( pMapEnt, "BasisV", pMapOverlay->vecBasis[1] );
  56. GetVectorForKey( pMapEnt, "BasisNormal", pMapOverlay->vecBasis[2] );
  57. const char *pMaterialName = ValueForKey( pMapEnt, "material" );
  58. Assert( strlen( pMaterialName ) < OVERLAY_MAP_STRLEN );
  59. if ( strlen( pMaterialName ) >= OVERLAY_MAP_STRLEN )
  60. {
  61. Error( "Overlay Material Name (%s) too long! > OVERLAY_MAP_STRLEN (%d)", pMaterialName, OVERLAY_MAP_STRLEN );
  62. return -1;
  63. }
  64. strcpy( pMapOverlay->szMaterialName, pMaterialName );
  65. // Convert the sidelist to side id(s).
  66. const char *pSideList = ValueForKey( pMapEnt, "sides" );
  67. char *pTmpList = ( char* )_alloca( strlen( pSideList ) + 1 );
  68. strcpy( pTmpList, pSideList );
  69. const char *pScan = strtok( pTmpList, " " );
  70. if ( !pScan )
  71. return iAccessorID;
  72. pMapOverlay->aSideList.Purge();
  73. pMapOverlay->aFaceList.Purge();
  74. do
  75. {
  76. int nSideId;
  77. if ( sscanf( pScan, "%d", &nSideId ) == 1 )
  78. {
  79. pMapOverlay->aSideList.AddToTail( nSideId );
  80. }
  81. } while ( ( pScan = strtok( NULL, " " ) ) );
  82. return iAccessorID;
  83. }
  84. //-----------------------------------------------------------------------------
  85. //-----------------------------------------------------------------------------
  86. side_t *GetSide( int nSideId )
  87. {
  88. for( int iSide = 0; iSide < g_LoadingMap->nummapbrushsides; ++iSide )
  89. {
  90. if ( g_LoadingMap->brushsides[iSide].id == nSideId )
  91. return &g_LoadingMap->brushsides[iSide];
  92. }
  93. return NULL;
  94. }
  95. //-----------------------------------------------------------------------------
  96. //-----------------------------------------------------------------------------
  97. void Overlay_UpdateSideLists( int StartIndex )
  98. {
  99. int nMapOverlayCount = g_aMapOverlays.Count();
  100. for( int iMapOverlay = StartIndex; iMapOverlay < nMapOverlayCount; ++iMapOverlay )
  101. {
  102. mapoverlay_t *pMapOverlay = &g_aMapOverlays.Element( iMapOverlay );
  103. if ( pMapOverlay )
  104. {
  105. int nSideCount = pMapOverlay->aSideList.Count();
  106. for( int iSide = 0; iSide < nSideCount; ++iSide )
  107. {
  108. side_t *pSide = GetSide( pMapOverlay->aSideList[iSide] );
  109. if ( pSide )
  110. {
  111. if ( pSide->aOverlayIds.Find( pMapOverlay->nId ) == -1 )
  112. {
  113. pSide->aOverlayIds.AddToTail( pMapOverlay->nId );
  114. }
  115. }
  116. }
  117. }
  118. }
  119. }
  120. //-----------------------------------------------------------------------------
  121. //-----------------------------------------------------------------------------
  122. void OverlayTransition_UpdateSideLists( int StartIndex )
  123. {
  124. int nOverlayCount = g_aMapWaterOverlays.Count();
  125. for( int iOverlay = StartIndex; iOverlay < nOverlayCount; ++iOverlay )
  126. {
  127. mapoverlay_t *pOverlay = &g_aMapWaterOverlays.Element( iOverlay );
  128. if ( pOverlay )
  129. {
  130. int nSideCount = pOverlay->aSideList.Count();
  131. for( int iSide = 0; iSide < nSideCount; ++iSide )
  132. {
  133. side_t *pSide = GetSide( pOverlay->aSideList[iSide] );
  134. if ( pSide )
  135. {
  136. if ( pSide->aWaterOverlayIds.Find( pOverlay->nId ) == -1 )
  137. {
  138. pSide->aWaterOverlayIds.AddToTail( pOverlay->nId );
  139. }
  140. }
  141. }
  142. }
  143. }
  144. }
  145. //-----------------------------------------------------------------------------
  146. //-----------------------------------------------------------------------------
  147. void Overlay_AddFaceToLists( int iFace, side_t *pSide )
  148. {
  149. int nOverlayIdCount = pSide->aOverlayIds.Count();
  150. for( int iOverlayId = 0; iOverlayId < nOverlayIdCount; ++iOverlayId )
  151. {
  152. mapoverlay_t *pMapOverlay = &g_aMapOverlays.Element( pSide->aOverlayIds[iOverlayId] );
  153. if ( pMapOverlay )
  154. {
  155. if( pMapOverlay->aFaceList.Find( iFace ) == -1 )
  156. {
  157. pMapOverlay->aFaceList.AddToTail( iFace );
  158. }
  159. }
  160. }
  161. }
  162. //-----------------------------------------------------------------------------
  163. //-----------------------------------------------------------------------------
  164. void OverlayTransition_AddFaceToLists( int iFace, side_t *pSide )
  165. {
  166. int nOverlayIdCount = pSide->aWaterOverlayIds.Count();
  167. for( int iOverlayId = 0; iOverlayId < nOverlayIdCount; ++iOverlayId )
  168. {
  169. mapoverlay_t *pMapOverlay = &g_aMapWaterOverlays.Element( pSide->aWaterOverlayIds[iOverlayId] - ( MAX_MAP_OVERLAYS + 1 ) );
  170. if ( pMapOverlay )
  171. {
  172. if( pMapOverlay->aFaceList.Find( iFace ) == -1 )
  173. {
  174. pMapOverlay->aFaceList.AddToTail( iFace );
  175. }
  176. }
  177. }
  178. }
  179. //-----------------------------------------------------------------------------
  180. //-----------------------------------------------------------------------------
  181. void Overlay_EmitOverlayFace( mapoverlay_t *pMapOverlay )
  182. {
  183. Assert( g_nOverlayCount < MAX_MAP_OVERLAYS );
  184. if ( g_nOverlayCount >= MAX_MAP_OVERLAYS )
  185. {
  186. Error ( "Too Many Overlays!\nMAX_MAP_OVERLAYS = %d", MAX_MAP_OVERLAYS );
  187. return;
  188. }
  189. doverlay_t *pOverlay = &g_Overlays[g_nOverlayCount];
  190. doverlayfade_t *pOverlayFade = &g_OverlayFades[g_nOverlayCount];
  191. g_nOverlayCount++;
  192. // Conver the map overlay into a .bsp overlay (doverlay_t).
  193. if ( pOverlay )
  194. {
  195. pOverlay->nId = pMapOverlay->nId;
  196. pOverlay->flU[0] = pMapOverlay->flU[0];
  197. pOverlay->flU[1] = pMapOverlay->flU[1];
  198. pOverlay->flV[0] = pMapOverlay->flV[0];
  199. pOverlay->flV[1] = pMapOverlay->flV[1];
  200. VectorCopy( pMapOverlay->vecUVPoints[0], pOverlay->vecUVPoints[0] );
  201. VectorCopy( pMapOverlay->vecUVPoints[1], pOverlay->vecUVPoints[1] );
  202. VectorCopy( pMapOverlay->vecUVPoints[2], pOverlay->vecUVPoints[2] );
  203. VectorCopy( pMapOverlay->vecUVPoints[3], pOverlay->vecUVPoints[3] );
  204. VectorCopy( pMapOverlay->vecOrigin, pOverlay->vecOrigin );
  205. VectorCopy( pMapOverlay->vecBasis[2], pOverlay->vecBasisNormal );
  206. pOverlay->SetRenderOrder( pMapOverlay->m_nRenderOrder );
  207. // Encode the BasisU into the unused z component of the vecUVPoints 0, 1, 2
  208. pOverlay->vecUVPoints[0].z = pMapOverlay->vecBasis[0].x;
  209. pOverlay->vecUVPoints[1].z = pMapOverlay->vecBasis[0].y;
  210. pOverlay->vecUVPoints[2].z = pMapOverlay->vecBasis[0].z;
  211. // Encode whether or not the v axis should be flipped.
  212. Vector vecCross = pMapOverlay->vecBasis[2].Cross( pMapOverlay->vecBasis[0] );
  213. if ( vecCross.Dot( pMapOverlay->vecBasis[1] ) < 0.0f )
  214. {
  215. pOverlay->vecUVPoints[3].z = 1.0f;
  216. }
  217. // Texinfo.
  218. texinfo_t texInfo;
  219. texInfo.flags = 0;
  220. texInfo.texdata = FindOrCreateTexData( pMapOverlay->szMaterialName );
  221. for( int iVec = 0; iVec < 2; ++iVec )
  222. {
  223. for( int iAxis = 0; iAxis < 3; ++iAxis )
  224. {
  225. texInfo.lightmapVecsLuxelsPerWorldUnits[iVec][iAxis] = 0.0f;
  226. texInfo.textureVecsTexelsPerWorldUnits[iVec][iAxis] = 0.0f;
  227. }
  228. texInfo.lightmapVecsLuxelsPerWorldUnits[iVec][3] = -99999.0f;
  229. texInfo.textureVecsTexelsPerWorldUnits[iVec][3] = -99999.0f;
  230. }
  231. pOverlay->nTexInfo = FindOrCreateTexInfo( texInfo );
  232. // Face List
  233. int nFaceCount = pMapOverlay->aFaceList.Count();
  234. Assert( nFaceCount < OVERLAY_BSP_FACE_COUNT );
  235. if ( nFaceCount >= OVERLAY_BSP_FACE_COUNT )
  236. {
  237. Error( "Overlay touching too many faces (touching %d, max %d)\nOverlay %s at %.1f %.1f %.1f", nFaceCount, OVERLAY_BSP_FACE_COUNT, pMapOverlay->szMaterialName, pMapOverlay->vecOrigin.x, pMapOverlay->vecOrigin.y, pMapOverlay->vecOrigin.z );
  238. return;
  239. }
  240. pOverlay->SetFaceCount( nFaceCount );
  241. for( int iFace = 0; iFace < nFaceCount; ++iFace )
  242. {
  243. pOverlay->aFaces[iFace] = pMapOverlay->aFaceList.Element( iFace );
  244. }
  245. }
  246. // Convert the map overlay fade data into a .bsp overlay fade (doverlayfade_t).
  247. if ( pOverlayFade )
  248. {
  249. pOverlayFade->flFadeDistMinSq = pMapOverlay->flFadeDistMinSq;
  250. pOverlayFade->flFadeDistMaxSq = pMapOverlay->flFadeDistMaxSq;
  251. }
  252. }
  253. //-----------------------------------------------------------------------------
  254. //-----------------------------------------------------------------------------
  255. void OverlayTransition_EmitOverlayFace( mapoverlay_t *pMapOverlay )
  256. {
  257. Assert( g_nWaterOverlayCount < MAX_MAP_WATEROVERLAYS );
  258. if ( g_nWaterOverlayCount >= MAX_MAP_WATEROVERLAYS )
  259. {
  260. Error ( "Too many water overlays!\nMAX_MAP_WATEROVERLAYS = %d", MAX_MAP_WATEROVERLAYS );
  261. return;
  262. }
  263. dwateroverlay_t *pOverlay = &g_WaterOverlays[g_nWaterOverlayCount];
  264. g_nWaterOverlayCount++;
  265. // Conver the map overlay into a .bsp overlay (doverlay_t).
  266. if ( pOverlay )
  267. {
  268. pOverlay->nId = pMapOverlay->nId;
  269. pOverlay->flU[0] = pMapOverlay->flU[0];
  270. pOverlay->flU[1] = pMapOverlay->flU[1];
  271. pOverlay->flV[0] = pMapOverlay->flV[0];
  272. pOverlay->flV[1] = pMapOverlay->flV[1];
  273. VectorCopy( pMapOverlay->vecUVPoints[0], pOverlay->vecUVPoints[0] );
  274. VectorCopy( pMapOverlay->vecUVPoints[1], pOverlay->vecUVPoints[1] );
  275. VectorCopy( pMapOverlay->vecUVPoints[2], pOverlay->vecUVPoints[2] );
  276. VectorCopy( pMapOverlay->vecUVPoints[3], pOverlay->vecUVPoints[3] );
  277. VectorCopy( pMapOverlay->vecOrigin, pOverlay->vecOrigin );
  278. VectorCopy( pMapOverlay->vecBasis[2], pOverlay->vecBasisNormal );
  279. pOverlay->SetRenderOrder( pMapOverlay->m_nRenderOrder );
  280. // Encode the BasisU into the unused z component of the vecUVPoints 0, 1, 2
  281. pOverlay->vecUVPoints[0].z = pMapOverlay->vecBasis[0].x;
  282. pOverlay->vecUVPoints[1].z = pMapOverlay->vecBasis[0].y;
  283. pOverlay->vecUVPoints[2].z = pMapOverlay->vecBasis[0].z;
  284. // Encode whether or not the v axis should be flipped.
  285. Vector vecCross = pMapOverlay->vecBasis[2].Cross( pMapOverlay->vecBasis[0] );
  286. if ( vecCross.Dot( pMapOverlay->vecBasis[1] ) < 0.0f )
  287. {
  288. pOverlay->vecUVPoints[3].z = 1.0f;
  289. }
  290. // Texinfo.
  291. texinfo_t texInfo;
  292. texInfo.flags = 0;
  293. texInfo.texdata = FindOrCreateTexData( pMapOverlay->szMaterialName );
  294. for( int iVec = 0; iVec < 2; ++iVec )
  295. {
  296. for( int iAxis = 0; iAxis < 3; ++iAxis )
  297. {
  298. texInfo.lightmapVecsLuxelsPerWorldUnits[iVec][iAxis] = 0.0f;
  299. texInfo.textureVecsTexelsPerWorldUnits[iVec][iAxis] = 0.0f;
  300. }
  301. texInfo.lightmapVecsLuxelsPerWorldUnits[iVec][3] = -99999.0f;
  302. texInfo.textureVecsTexelsPerWorldUnits[iVec][3] = -99999.0f;
  303. }
  304. pOverlay->nTexInfo = FindOrCreateTexInfo( texInfo );
  305. // Face List
  306. int nFaceCount = pMapOverlay->aFaceList.Count();
  307. Assert( nFaceCount < WATEROVERLAY_BSP_FACE_COUNT );
  308. if ( nFaceCount >= WATEROVERLAY_BSP_FACE_COUNT )
  309. {
  310. Error( "Water Overlay touching too many faces (touching %d, max %d)\nOverlay %s at %.1f %.1f %.1f", nFaceCount, OVERLAY_BSP_FACE_COUNT, pMapOverlay->szMaterialName, pMapOverlay->vecOrigin.x, pMapOverlay->vecOrigin.y, pMapOverlay->vecOrigin.z );
  311. return;
  312. }
  313. pOverlay->SetFaceCount( nFaceCount );
  314. for( int iFace = 0; iFace < nFaceCount; ++iFace )
  315. {
  316. pOverlay->aFaces[iFace] = pMapOverlay->aFaceList.Element( iFace );
  317. }
  318. }
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose:
  322. //-----------------------------------------------------------------------------
  323. void Overlay_EmitOverlayFaces( void )
  324. {
  325. int nMapOverlayCount = g_aMapOverlays.Count();
  326. for( int iMapOverlay = 0; iMapOverlay < nMapOverlayCount; ++iMapOverlay )
  327. {
  328. Overlay_EmitOverlayFace( &g_aMapOverlays.Element( iMapOverlay ) );
  329. }
  330. }
  331. //-----------------------------------------------------------------------------
  332. // Purpose:
  333. //-----------------------------------------------------------------------------
  334. void OverlayTransition_EmitOverlayFaces( void )
  335. {
  336. int nMapOverlayCount = g_aMapWaterOverlays.Count();
  337. for( int iMapOverlay = 0; iMapOverlay < nMapOverlayCount; ++iMapOverlay )
  338. {
  339. OverlayTransition_EmitOverlayFace( &g_aMapWaterOverlays.Element( iMapOverlay ) );
  340. }
  341. }
  342. //-----------------------------------------------------------------------------
  343. // These routines were mostly stolen from MapOverlay.cpp in Hammer
  344. //-----------------------------------------------------------------------------
  345. #define OVERLAY_BASIS_U 0
  346. #define OVERLAY_BASIS_V 1
  347. #define OVERLAY_BASIS_NORMAL 2
  348. #define OVERLAY_HANDLES_COUNT 4
  349. inline void TransformPoint( const VMatrix& matrix, Vector &point )
  350. {
  351. Vector orgVector = point;
  352. matrix.V3Mul( orgVector, point );
  353. }
  354. inline bool fequal( float value, float target, float delta) { return ( (value<(target+delta))&&(value>(target-delta)) ); }
  355. //-----------------------------------------------------------------------------
  356. // Purpose: this function translate / rotate an overlay.
  357. // Input : pOverlay - the overlay to be translated
  358. // OriginOffset - the translation
  359. // AngleOffset - the rotation
  360. // Matrix - the translation / rotation matrix
  361. // Output : none
  362. //-----------------------------------------------------------------------------
  363. void Overlay_Translate( mapoverlay_t *pOverlay, Vector &OriginOffset, QAngle &AngleOffset, matrix3x4_t &Matrix )
  364. {
  365. VMatrix tmpMatrix( Matrix );
  366. Vector temp = pOverlay->vecOrigin;
  367. VectorTransform( temp, Matrix, pOverlay->vecOrigin );
  368. // erase move component
  369. tmpMatrix.SetTranslation( vec3_origin );
  370. // check if matrix would still change something
  371. if ( !tmpMatrix.IsIdentity() )
  372. {
  373. // make sure axes are normalized (they should be anyways)
  374. pOverlay->vecBasis[OVERLAY_BASIS_U].NormalizeInPlace();
  375. pOverlay->vecBasis[OVERLAY_BASIS_V].NormalizeInPlace();
  376. Vector vecU = pOverlay->vecBasis[OVERLAY_BASIS_U];
  377. Vector vecV = pOverlay->vecBasis[OVERLAY_BASIS_V];
  378. Vector vecNormal = pOverlay->vecBasis[OVERLAY_BASIS_NORMAL];
  379. TransformPoint( tmpMatrix, vecU );
  380. TransformPoint( tmpMatrix, vecV );
  381. TransformPoint( tmpMatrix, vecNormal );
  382. float fScaleU = vecU.Length();
  383. float fScaleV = vecV.Length();
  384. float flScaleNormal = vecNormal.Length();
  385. bool bIsUnit = ( fequal( fScaleU, 1.0f, 0.0001 ) && fequal( fScaleV, 1.0f, 0.0001 ) && fequal( flScaleNormal, 1.0f, 0.0001 ) );
  386. bool bIsPerp = ( fequal( DotProduct( vecU, vecV ), 0.0f, 0.0025 ) && fequal( DotProduct( vecU, vecNormal ), 0.0f, 0.0025 ) && fequal( DotProduct( vecV, vecNormal ), 0.0f, 0.0025 ) );
  387. // if ( fequal(fScaleU,1,0.0001) && fequal(fScaleV,1,0.0001) && fequal(DotProduct( vecU, vecV ),0,0.0025) )
  388. if ( bIsUnit && bIsPerp )
  389. {
  390. // transformation doesnt scale or shear anything, so just update base axes
  391. pOverlay->vecBasis[OVERLAY_BASIS_U] = vecU;
  392. pOverlay->vecBasis[OVERLAY_BASIS_V] = vecV;
  393. pOverlay->vecBasis[OVERLAY_BASIS_NORMAL] = vecNormal;
  394. }
  395. else
  396. {
  397. // more complex transformation, move UV coordinates, but leave base axes
  398. for ( int iHandle=0; iHandle<OVERLAY_HANDLES_COUNT;iHandle++)
  399. {
  400. Vector vecUV = pOverlay->vecUVPoints[iHandle];
  401. Vector vecPos = ( vecUV.x * pOverlay->vecBasis[OVERLAY_BASIS_U] + vecUV.y * pOverlay->vecBasis[OVERLAY_BASIS_V] );
  402. // to transform in world space
  403. TransformPoint( tmpMatrix, vecPos );
  404. vecUV.x = pOverlay->vecBasis[OVERLAY_BASIS_U].Dot( vecPos );
  405. vecUV.y = pOverlay->vecBasis[OVERLAY_BASIS_V].Dot( vecPos );
  406. pOverlay->vecUVPoints[iHandle] = vecUV;
  407. }
  408. }
  409. }
  410. }