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.

2358 lines
78 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Model loading / unloading interface
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "render_pch.h"
  8. #include "Overlay.h"
  9. #include "bspfile.h"
  10. #include "modelloader.h"
  11. #include "materialsystem/imesh.h"
  12. #include "disp.h"
  13. #include "collisionutils.h"
  14. #include "tier0/vprof.h"
  15. #include "render.h"
  16. #include "r_decal.h"
  17. #include "fmtstr.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. //-----------------------------------------------------------------------------
  21. // Externs
  22. //-----------------------------------------------------------------------------
  23. int g_OverlayRenderFrameID;
  24. //-----------------------------------------------------------------------------
  25. // Convars
  26. //-----------------------------------------------------------------------------
  27. static ConVar r_renderoverlayfragment("r_renderoverlayfragment", "1");
  28. static ConVar r_overlaywireframe( "r_overlaywireframe", "0" );
  29. static ConVar r_overlayfadeenable( "r_overlayfadeenable", "0" );
  30. static ConVar r_overlayfademin( "r_overlayfademin", "1750.0f" );
  31. static ConVar r_overlayfademax( "r_overlayfademax", "2000.0f" );
  32. //-----------------------------------------------------------------------------
  33. // Structures used to represent the overlay
  34. //-----------------------------------------------------------------------------
  35. typedef unsigned short OverlayFragmentList_t;
  36. enum
  37. {
  38. OVERLAY_FRAGMENT_LIST_INVALID = (OverlayFragmentList_t)~0,
  39. };
  40. enum
  41. {
  42. NUM_OVERLAY_TEXCOORDS = 2,
  43. };
  44. struct overlayvert_t
  45. {
  46. Vector pos;
  47. Vector normal;
  48. Vector2D texCoord[NUM_OVERLAY_TEXCOORDS]; // texcoord 0 = the mapped tex coord from worldcraft
  49. // texcoord 1 is used for alpha and maps the whole texture into the whole overlay
  50. float lightCoord[2];
  51. float flAlpha;
  52. overlayvert_t()
  53. {
  54. pos.Init();
  55. normal.Init();
  56. texCoord[0].Init();
  57. texCoord[1].Init();
  58. lightCoord[0] = lightCoord[1] = 0.0f;
  59. flAlpha = 1.0f;
  60. }
  61. };
  62. struct moverlayfragment_t
  63. {
  64. int m_nRenderFrameID; // So we only render a fragment once a frame!
  65. SurfaceHandle_t m_SurfId; // Surface Id
  66. int m_iOverlay; // Overlay Id
  67. OverlayFragmentHandle_t m_hNextRender;
  68. unsigned short m_nMaterialSortID;
  69. CUtlVector<overlayvert_t> m_aPrimVerts;
  70. };
  71. struct moverlay_t
  72. {
  73. int m_nId;
  74. short m_nTexInfo;
  75. short m_nRenderOrder; // 0 - MAX_OVERLAY_RENDER_ORDERS
  76. OverlayFragmentList_t m_hFirstFragment;
  77. CUtlVector<SurfaceHandle_t> m_aFaces;
  78. float m_flU[2];
  79. float m_flV[2];
  80. Vector m_vecUVPoints[4];
  81. Vector m_vecOrigin;
  82. Vector m_vecBasis[3]; // 0 = u, 1 = v, 2 = normal
  83. void *m_pBindProxy; // client renderable for an overlay's material proxy to bind to
  84. float m_flFadeDistMinSq; // Distance from the overlay's origin at which we start fading (-1 = use max dist)
  85. float m_flFadeDistMaxSq; // Distance from the overlay's origin at which we fade out completely
  86. float m_flInvFadeRangeSq; // Precomputed 1.0f / ( m_flFadeDistMaxSq - m_flFadeDistMinSq )
  87. };
  88. // Going away!
  89. void Overlay_BuildBasisOrigin( Vector &vecBasisOrigin, SurfaceHandle_t surfID );
  90. void Overlay_BuildBasis( const Vector &vecBasisNormal, Vector &vecBasisU, Vector &vecBasisV, bool bFlip );
  91. void Overlay_OverlayUVToOverlayPlane( const Vector &vecBasisOrigin, const Vector &vecBasisU,
  92. const Vector &vecBasisV, const Vector &vecUVPoint,
  93. Vector &vecPlanePoint );
  94. void Overlay_WorldToOverlayPlane( const Vector &vecBasisOrigin, const Vector &vecBasisNormal,
  95. const Vector &vecWorldPoint, Vector &vecPlanePoint );
  96. void Overlay_OverlayPlaneToWorld( const Vector &vecBasisNormal, SurfaceHandle_t surfID,
  97. const Vector &vecPlanePoint, Vector &vecWorldPoint );
  98. void Overlay_DispUVToWorld( CDispInfo *pDisp, CMeshReader *pReader, const Vector2D &vecUV, Vector &vecWorld, moverlayfragment_t &surfaceFrag );
  99. void Overlay_TriTLToBR( CDispInfo *pDisp, Vector &vecWorld, float flU, float flV,
  100. int nSnapU, int nSnapV, int nWidth, int nHeight );
  101. void Overlay_TriBLToTR( CDispInfo *pDisp, Vector &vecWorld, float flU, float flV,
  102. int nSnapU, int nSnapV, int nWidth, int nHeight );
  103. //-----------------------------------------------------------------------------
  104. // Overlay manager class
  105. //-----------------------------------------------------------------------------
  106. class COverlayMgr : public IOverlayMgr
  107. {
  108. public:
  109. typedef CUtlVector<moverlayfragment_t*> OverlayFragmentVector_t;
  110. public:
  111. COverlayMgr();
  112. ~COverlayMgr();
  113. // Implementation of IOverlayMgr interface
  114. virtual bool LoadOverlays( );
  115. virtual void UnloadOverlays( );
  116. virtual void CreateFragments( void );
  117. virtual void ReSortMaterials( void );
  118. virtual void ClearRenderLists();
  119. virtual void ClearRenderLists( int nSortGroup );
  120. virtual void AddFragmentListToRenderList( int nSortGroup, OverlayFragmentHandle_t iFragment, bool bDisp );
  121. virtual void RenderOverlays( int nSortGroup );
  122. virtual void SetOverlayBindProxy( int iOverlayID, void *pBindProxy );
  123. private:
  124. // Create, destroy material sort order ids...
  125. int GetMaterialSortID( IMaterial* pMaterial, int nLightmapPage );
  126. void CleanupMaterial( unsigned short nSortOrder );
  127. moverlay_t *GetOverlay( int iOverlay );
  128. moverlayfragment_t *GetOverlayFragment( OverlayFragmentHandle_t iFragment );
  129. // Surfaces
  130. void Surf_CreateFragments( moverlay_t *pOverlay, SurfaceHandle_t surfID );
  131. bool Surf_PreClipFragment( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag, SurfaceHandle_t surfID, moverlayfragment_t &surfaceFrag );
  132. void Surf_PostClipFragment( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag, SurfaceHandle_t surfID );
  133. void Surf_ClipFragment( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag, SurfaceHandle_t surfID, moverlayfragment_t &surfaceFrag );
  134. // Displacements
  135. void Disp_CreateFragments( moverlay_t *pOverlay, SurfaceHandle_t surfID );
  136. bool Disp_PreClipFragment( moverlay_t *pOverlay, OverlayFragmentVector_t &aDispFragments, SurfaceHandle_t surfID );
  137. void Disp_PostClipFragment( CDispInfo *pDisp, CMeshReader *pReader, moverlay_t *pOverlay, OverlayFragmentVector_t &aDispFragments, SurfaceHandle_t surfID );
  138. void Disp_ClipFragment( CDispInfo *pDisp, OverlayFragmentVector_t &aDispFragments );
  139. void Disp_DoClip( CDispInfo *pDisp, OverlayFragmentVector_t &aCurrentFragments, cplane_t &clipPlane,
  140. float clipDistStart, int nInterval, int nLoopStart, int nLoopEnd, int nLoopInc );
  141. // Utility
  142. OverlayFragmentHandle_t AddFragmentToFragmentList( int nSize );
  143. OverlayFragmentHandle_t AddFragmentToFragmentList( moverlayfragment_t *pSrc );
  144. bool FadeOverlayFragmentGlobal( moverlayfragment_t *pFragment );
  145. bool FadeOverlayFragment( moverlay_t *pOverlay, moverlayfragment_t *pFragment );
  146. moverlayfragment_t *CreateTempFragment( int nSize );
  147. moverlayfragment_t *CopyTempFragment( moverlayfragment_t *pSrc );
  148. void DestroyTempFragment( moverlayfragment_t *pFragment );
  149. void BuildClipPlanes( SurfaceHandle_t surfID, moverlayfragment_t &surfaceFrag, const Vector &vecBasisNormal, CUtlVector<cplane_t> &m_ClipPlanes );
  150. void DoClipFragment( moverlayfragment_t *pFragment, cplane_t *pClipPlane, moverlayfragment_t **ppFront, moverlayfragment_t **ppBack );
  151. void InitTexCoords( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag );
  152. private:
  153. enum
  154. {
  155. RENDER_QUEUE_INVALID = 0xFFFF
  156. };
  157. // Structures used to assign sort order handles
  158. struct RenderQueueInfo_t
  159. {
  160. OverlayFragmentHandle_t m_hFirstFragment;
  161. unsigned short m_nNextRenderQueue; // Index of next queue that has stuff to render
  162. unsigned short m_nVertexCount;
  163. unsigned short m_nIndexCount;
  164. };
  165. struct RenderQueueHead_t
  166. {
  167. IMaterial *m_pMaterial;
  168. int m_nLightmapPage;
  169. RenderQueueInfo_t m_Queue[MAX_MAT_SORT_GROUPS];
  170. unsigned short m_nRefCount;
  171. };
  172. // First render queue to render
  173. unsigned short m_nFirstRenderQueue[MAX_MAT_SORT_GROUPS];
  174. // Used to assign sort order handles
  175. CUtlLinkedList<RenderQueueHead_t, unsigned short> m_RenderQueue;
  176. // All overlays
  177. CUtlVector<moverlay_t> m_aOverlays;
  178. // List of all overlay fragments. prev/next links point to the next fragment on a *surface*
  179. CUtlLinkedList< moverlayfragment_t, unsigned short, true > m_aFragments;
  180. // Used to find all fragments associated with a particular overlay
  181. CUtlLinkedList< OverlayFragmentHandle_t, unsigned short, true > m_OverlayFragments;
  182. // Fade parameters.
  183. float m_flFadeMin2;
  184. float m_flFadeMax2;
  185. float m_flFadeDelta2;
  186. };
  187. //-----------------------------------------------------------------------------
  188. // Singleton accessor
  189. //-----------------------------------------------------------------------------
  190. static COverlayMgr g_OverlayMgr;
  191. IOverlayMgr *OverlayMgr( void )
  192. {
  193. return &g_OverlayMgr;
  194. }
  195. //-----------------------------------------------------------------------------
  196. // Constructor
  197. //-----------------------------------------------------------------------------
  198. COverlayMgr::COverlayMgr()
  199. {
  200. for ( int i = 0; i < MAX_MAT_SORT_GROUPS; ++i )
  201. {
  202. m_nFirstRenderQueue[i] = RENDER_QUEUE_INVALID;
  203. }
  204. m_flFadeMin2 = 0.0f;
  205. m_flFadeMax2 = 0.0f;
  206. m_flFadeDelta2 = 0.0f;
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Destructor
  210. //-----------------------------------------------------------------------------
  211. COverlayMgr::~COverlayMgr()
  212. {
  213. UnloadOverlays();
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Returns a particular overlay
  217. //-----------------------------------------------------------------------------
  218. inline moverlay_t *COverlayMgr::GetOverlay( int iOverlay )
  219. {
  220. return &m_aOverlays[iOverlay];
  221. }
  222. //-----------------------------------------------------------------------------
  223. // Returns a particular overlay fragment
  224. //-----------------------------------------------------------------------------
  225. inline moverlayfragment_t *COverlayMgr::GetOverlayFragment( OverlayFragmentHandle_t iFragment )
  226. {
  227. return &m_aFragments[iFragment];
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Cleanup overlays
  231. //-----------------------------------------------------------------------------
  232. void COverlayMgr::UnloadOverlays( )
  233. {
  234. FOR_EACH_LL( m_RenderQueue, i )
  235. {
  236. m_RenderQueue[i].m_pMaterial->DecrementReferenceCount();
  237. }
  238. int nOverlayCount = m_aOverlays.Count();
  239. for ( int iOverlay = 0; iOverlay < nOverlayCount; ++iOverlay )
  240. {
  241. moverlay_t *pOverlay = &m_aOverlays.Element( iOverlay );
  242. int hFrag = pOverlay->m_hFirstFragment;
  243. while ( hFrag != OVERLAY_FRAGMENT_INVALID )
  244. {
  245. int iFrag = m_OverlayFragments[hFrag];
  246. m_aFragments.Free( iFrag );
  247. hFrag = m_OverlayFragments.Next( hFrag );
  248. }
  249. }
  250. m_aOverlays.Purge();
  251. m_aFragments.Purge();
  252. m_OverlayFragments.Purge();
  253. m_RenderQueue.Purge();
  254. for ( int i = 0; i < MAX_MAT_SORT_GROUPS; ++i )
  255. {
  256. m_nFirstRenderQueue[i] = RENDER_QUEUE_INVALID;
  257. }
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Create, destroy material sort order ids...
  261. //-----------------------------------------------------------------------------
  262. int COverlayMgr::GetMaterialSortID( IMaterial* pMaterial, int nLightmapPage )
  263. {
  264. // Search the sort order handles for an enumeration id match (means materials + lightmaps match)
  265. unsigned short i;
  266. for ( i = m_RenderQueue.Head(); i != m_RenderQueue.InvalidIndex();
  267. i = m_RenderQueue.Next(i) )
  268. {
  269. // Found a match, lets increment the refcount of this sort order id
  270. if ((m_RenderQueue[i].m_pMaterial == pMaterial) && (m_RenderQueue[i].m_nLightmapPage == nLightmapPage))
  271. {
  272. ++m_RenderQueue[i].m_nRefCount;
  273. return i;
  274. }
  275. }
  276. // Didn't find it, lets assign a new sort order ID, with a refcount of 1
  277. i = m_RenderQueue.AddToTail();
  278. RenderQueueHead_t &renderQueue = m_RenderQueue[i];
  279. renderQueue.m_pMaterial = pMaterial;
  280. renderQueue.m_nLightmapPage = nLightmapPage;
  281. renderQueue.m_nRefCount = 1;
  282. for ( int j = 0; j < MAX_MAT_SORT_GROUPS; ++j )
  283. {
  284. RenderQueueInfo_t &info = renderQueue.m_Queue[j];
  285. info.m_hFirstFragment = OVERLAY_FRAGMENT_INVALID;
  286. info.m_nNextRenderQueue = RENDER_QUEUE_INVALID;
  287. info.m_nVertexCount = 0;
  288. info.m_nIndexCount = 0;
  289. }
  290. pMaterial->IncrementReferenceCount();
  291. return i;
  292. }
  293. void COverlayMgr::CleanupMaterial( unsigned short nSortOrder )
  294. {
  295. RenderQueueHead_t &renderQueue = m_RenderQueue[nSortOrder];
  296. #ifdef _DEBUG
  297. for ( int i = 0; i < MAX_MAT_SORT_GROUPS; ++i )
  298. {
  299. // Shouldn't be cleaning up while we've got a render list
  300. Assert( renderQueue.m_Queue[i].m_nVertexCount == 0 );
  301. }
  302. #endif
  303. // Decrease the sort order reference count
  304. if (--renderQueue.m_nRefCount <= 0)
  305. {
  306. renderQueue.m_pMaterial->DecrementReferenceCount();
  307. // No one referencing the sort order number?
  308. // Then lets clean up the sort order id
  309. m_RenderQueue.Remove(nSortOrder);
  310. }
  311. }
  312. //-----------------------------------------------------------------------------
  313. // Clears the render lists
  314. //-----------------------------------------------------------------------------
  315. void COverlayMgr::ClearRenderLists()
  316. {
  317. for ( int i = 0; i < MAX_MAT_SORT_GROUPS; ++i )
  318. {
  319. ClearRenderLists( i );
  320. }
  321. if ( r_overlayfadeenable.GetBool() )
  322. {
  323. float flFadeMin = r_overlayfademin.GetFloat();
  324. float flFadeMax = r_overlayfademax.GetFloat();
  325. m_flFadeMin2 = flFadeMin * flFadeMin;
  326. m_flFadeMax2 = flFadeMax * flFadeMax;
  327. m_flFadeDelta2 = 1.0f / ( m_flFadeMax2 - m_flFadeMin2 );
  328. }
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Calculate the fade using the global convars.
  332. //-----------------------------------------------------------------------------
  333. bool COverlayMgr::FadeOverlayFragmentGlobal( moverlayfragment_t *pFragment )
  334. {
  335. // Test the overlay distance and set alpha values.
  336. int iVert;
  337. bool bInRange = false;
  338. int nVertexCount = pFragment->m_aPrimVerts.Count();
  339. for ( iVert = 0; iVert < nVertexCount; ++iVert )
  340. {
  341. Vector vecSegment;
  342. VectorSubtract( MainViewOrigin(), pFragment->m_aPrimVerts.Element( iVert ).pos, vecSegment );
  343. float flLength2 = vecSegment.LengthSqr();
  344. // min dist of -1 means use max dist for fading
  345. if ( flLength2 < m_flFadeMin2 )
  346. {
  347. pFragment->m_aPrimVerts.Element( iVert ).flAlpha = 1.0f;
  348. bInRange = true;
  349. }
  350. else if ( flLength2 > m_flFadeMax2 )
  351. {
  352. // Set vertex alpha to off.
  353. pFragment->m_aPrimVerts.Element( iVert ).flAlpha = 0.0f;
  354. }
  355. else
  356. {
  357. // Set the alpha based on distance inside of fadeMin and fadeMax
  358. float flAlpha = flLength2 - m_flFadeMin2;
  359. flAlpha *= m_flFadeDelta2;
  360. pFragment->m_aPrimVerts.Element( iVert ).flAlpha = ( 1.0f - flAlpha );
  361. bInRange = true;
  362. }
  363. }
  364. return bInRange;
  365. }
  366. //-----------------------------------------------------------------------------
  367. // Calculate the fade using per-overlay fade distances.
  368. //-----------------------------------------------------------------------------
  369. bool COverlayMgr::FadeOverlayFragment( moverlay_t *pOverlay, moverlayfragment_t *pFragment )
  370. {
  371. // min dist of -1 means use max dist for fading
  372. float flFadeDistMinSq = pOverlay->m_flFadeDistMinSq;
  373. float flFadeDistMaxSq = pOverlay->m_flFadeDistMaxSq;
  374. Vector vecSegment;
  375. VectorSubtract( MainViewOrigin(), pOverlay->m_vecOrigin, vecSegment );
  376. float flLength2 = vecSegment.LengthSqr();
  377. float flAlpha = 0.0f;
  378. bool bInRange = false;
  379. if ( flLength2 < flFadeDistMaxSq )
  380. {
  381. if ( ( flFadeDistMinSq >= 0 ) && ( flLength2 > flFadeDistMinSq ) )
  382. {
  383. flAlpha = pOverlay->m_flInvFadeRangeSq * ( flFadeDistMaxSq - flLength2 );
  384. flAlpha = clamp( flAlpha, 0.0f, 1.0f );
  385. bInRange = true;
  386. }
  387. else
  388. {
  389. flAlpha = 1.0f;
  390. bInRange = true;
  391. }
  392. }
  393. int nVertexCount = pFragment->m_aPrimVerts.Count();
  394. for ( int iVert = 0; iVert < nVertexCount; ++iVert )
  395. {
  396. pFragment->m_aPrimVerts.Element( iVert ).flAlpha = flAlpha;
  397. }
  398. return bInRange;
  399. }
  400. //-----------------------------------------------------------------------------
  401. // Adds the fragment list to the list of fragments to render when RenderOverlays is called
  402. //-----------------------------------------------------------------------------
  403. void COverlayMgr::AddFragmentListToRenderList( int nSortGroup, OverlayFragmentHandle_t iFragment, bool bDisp )
  404. {
  405. OverlayFragmentHandle_t i;
  406. for ( i = iFragment; i != OVERLAY_FRAGMENT_INVALID; i = m_aFragments.Next(i) )
  407. {
  408. // Make sure we don't add the fragment twice...
  409. // FIXME: I currently have no way of ensuring a fragment doesn't end up in 2 sort groups
  410. // which would cause all manner of nastiness.
  411. moverlayfragment_t *pFragment = GetOverlayFragment(i);
  412. if ( !bDisp && pFragment->m_nRenderFrameID == g_OverlayRenderFrameID )
  413. continue;
  414. // Triangle count too low? Skip it...
  415. int nVertexCount = pFragment->m_aPrimVerts.Count();
  416. if ( nVertexCount < 3 )
  417. continue;
  418. moverlay_t *pOverlay = &m_aOverlays[ pFragment->m_iOverlay ];
  419. // See if we should fade the overlay.
  420. if ( r_overlayfadeenable.GetBool() )
  421. {
  422. // Fade using the convars that control distance.
  423. if ( !FadeOverlayFragmentGlobal( pFragment ) )
  424. continue;
  425. }
  426. else if ( pOverlay->m_flFadeDistMaxSq > 0 )
  427. {
  428. // Fade using per-overlay fade distances, configured by the level designer.
  429. if ( !FadeOverlayFragment( pOverlay, pFragment ) )
  430. continue;
  431. }
  432. // Update the frame count.
  433. pFragment->m_nRenderFrameID = g_OverlayRenderFrameID;
  434. // Determine the material associated with the fragment...
  435. int nMaterialSortID = pFragment->m_nMaterialSortID;
  436. // Insert the render queue into the list of render queues to render
  437. RenderQueueHead_t &renderQueue = m_RenderQueue[nMaterialSortID];
  438. RenderQueueInfo_t &info = renderQueue.m_Queue[nSortGroup];
  439. if ( info.m_hFirstFragment == OVERLAY_FRAGMENT_INVALID )
  440. {
  441. info.m_nNextRenderQueue = m_nFirstRenderQueue[nSortGroup];
  442. m_nFirstRenderQueue[nSortGroup] = nMaterialSortID;
  443. }
  444. // Add to list of fragments for this surface
  445. // NOTE: Render them in *reverse* order in which they appeared in the list
  446. // because they are stored in the list in *reverse* order in which they should be rendered.
  447. // Add the fragment to the bucket of fragments to render...
  448. pFragment->m_hNextRender = info.m_hFirstFragment;
  449. info.m_hFirstFragment = i;
  450. Assert( info.m_nVertexCount + nVertexCount < 65535 );
  451. info.m_nVertexCount += nVertexCount;
  452. info.m_nIndexCount += 3 * (nVertexCount - 2);
  453. }
  454. }
  455. //-----------------------------------------------------------------------------
  456. // Renders all queued up overlays
  457. //-----------------------------------------------------------------------------
  458. void COverlayMgr::ClearRenderLists( int nSortGroup )
  459. {
  460. g_OverlayRenderFrameID++;
  461. int nNextRenderQueue;
  462. for( int i = m_nFirstRenderQueue[nSortGroup]; i != RENDER_QUEUE_INVALID; i = nNextRenderQueue )
  463. {
  464. RenderQueueInfo_t &renderQueue = m_RenderQueue[i].m_Queue[nSortGroup];
  465. nNextRenderQueue = renderQueue.m_nNextRenderQueue;
  466. // Clean up the render queue for next time...
  467. renderQueue.m_nVertexCount = 0;
  468. renderQueue.m_nIndexCount = 0;
  469. renderQueue.m_hFirstFragment = OVERLAY_FRAGMENT_INVALID;
  470. renderQueue.m_nNextRenderQueue = RENDER_QUEUE_INVALID;
  471. }
  472. m_nFirstRenderQueue[nSortGroup] = RENDER_QUEUE_INVALID;
  473. }
  474. //-----------------------------------------------------------------------------
  475. // Renders all queued up overlays
  476. //-----------------------------------------------------------------------------
  477. void COverlayMgr::RenderOverlays( int nSortGroup )
  478. {
  479. #ifndef SWDS
  480. VPROF_BUDGET( "COverlayMgr::RenderOverlays", VPROF_BUDGETGROUP_OVERLAYS );
  481. if (r_renderoverlayfragment.GetInt() == 0)
  482. {
  483. ClearRenderLists( nSortGroup );
  484. return;
  485. }
  486. CMatRenderContextPtr pRenderContext( materials );
  487. bool bWireframeFragments = ( r_overlaywireframe.GetInt() != 0 );
  488. if ( bWireframeFragments )
  489. {
  490. pRenderContext->Bind( g_materialWorldWireframe );
  491. }
  492. // Render sorted by material + lightmap...
  493. // Render them in order of their m_nRenderOrder parameter (set in the entity).
  494. int iCurrentRenderOrder = 0;
  495. int iHighestRenderOrder = 0;
  496. bool bLightmappedMaterial = false;
  497. int nMaxIndices = pRenderContext->GetMaxIndicesToRender();
  498. while ( iCurrentRenderOrder <= iHighestRenderOrder )
  499. {
  500. int nNextRenderQueue;
  501. for( int i = m_nFirstRenderQueue[nSortGroup]; i != RENDER_QUEUE_INVALID; i = nNextRenderQueue )
  502. {
  503. RenderQueueHead_t &renderQueueHead = m_RenderQueue[i];
  504. RenderQueueInfo_t &renderQueue = renderQueueHead.m_Queue[nSortGroup];
  505. nNextRenderQueue = renderQueue.m_nNextRenderQueue;
  506. Assert( renderQueue.m_nVertexCount > 0 );
  507. int nMaxVertices = pRenderContext->GetMaxVerticesToRender( !bWireframeFragments ? renderQueueHead.m_pMaterial : g_materialWorldWireframe );
  508. if ( nMaxVertices == 0 )
  509. continue;
  510. // Run this list for each bind proxy
  511. OverlayFragmentHandle_t hStartFragment = renderQueue.m_hFirstFragment;
  512. while ( hStartFragment != OVERLAY_FRAGMENT_INVALID )
  513. {
  514. void *pCurrentBindProxy = m_aOverlays[ m_aFragments[ hStartFragment ].m_iOverlay ].m_pBindProxy;
  515. IMesh* pMesh = 0; // only init when we actually have something
  516. CMeshBuilder meshBuilder;
  517. CUtlVectorFixedGrowable<int,256> polyList;
  518. int nCurrVertexCount = 0;
  519. int nCurrIndexCount = 0;
  520. bool bBoundMaterial = false;
  521. // We just need to make sure there's a unique sort ID for that. Then we bind once per queue
  522. OverlayFragmentHandle_t hFragment = hStartFragment;
  523. hStartFragment = OVERLAY_FRAGMENT_INVALID;
  524. for ( ; hFragment != OVERLAY_FRAGMENT_INVALID; hFragment = m_aFragments[hFragment].m_hNextRender )
  525. {
  526. moverlayfragment_t *pFragment = &m_aFragments[hFragment];
  527. moverlay_t *pOverlay = &m_aOverlays[pFragment->m_iOverlay];
  528. if ( pOverlay->m_pBindProxy != pCurrentBindProxy )
  529. {
  530. // This is from a different bind proxy
  531. if ( hStartFragment == OVERLAY_FRAGMENT_INVALID )
  532. {
  533. // Start at the first different bind proxy when we rerun the fragment list
  534. hStartFragment = hFragment;
  535. }
  536. continue;
  537. }
  538. // Only render the current render order.
  539. int iThisOverlayRenderOrder = pOverlay->m_nRenderOrder;
  540. iHighestRenderOrder = max( iThisOverlayRenderOrder, iHighestRenderOrder );
  541. if ( iThisOverlayRenderOrder != iCurrentRenderOrder )
  542. continue;
  543. int nVertCount = pFragment->m_aPrimVerts.Count();
  544. int nIndexCount = 3 * ( nVertCount - 2 );
  545. if ( pMesh )
  546. {
  547. // Would this cause an overflow? Flush!
  548. if ( ( ( nCurrVertexCount + nVertCount ) > nMaxVertices ) ||
  549. ( ( nCurrIndexCount + nIndexCount ) > nMaxIndices ) )
  550. {
  551. CIndexBuilder &indexBuilder = meshBuilder;
  552. indexBuilder.FastPolygonList( 0, polyList.Base(), polyList.Count() );
  553. meshBuilder.End();
  554. pMesh->Draw();
  555. pMesh = NULL;
  556. polyList.RemoveAll();
  557. nCurrIndexCount = nCurrVertexCount = 0;
  558. }
  559. }
  560. nCurrVertexCount += nVertCount;
  561. nCurrIndexCount += nIndexCount;
  562. const overlayvert_t *pVert = &(pFragment->m_aPrimVerts[0]);
  563. int iVert;
  564. if ( !pMesh ) // have we output any vertices yet? if first verts, init material and meshbuilder
  565. {
  566. if ( !bWireframeFragments && !bBoundMaterial )
  567. {
  568. pRenderContext->Bind( renderQueueHead.m_pMaterial, pOverlay->m_pBindProxy /*proxy*/ );
  569. pRenderContext->BindLightmapPage( renderQueueHead.m_nLightmapPage );
  570. bLightmappedMaterial = renderQueueHead.m_pMaterial->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_LIGHTMAP ) ||
  571. renderQueueHead.m_pMaterial->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS );
  572. bBoundMaterial = true;
  573. }
  574. // Create the mesh/mesh builder.
  575. pMesh = pRenderContext->GetDynamicMesh();
  576. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, MIN( renderQueue.m_nVertexCount, nMaxVertices ),
  577. MIN( renderQueue.m_nIndexCount, nMaxIndices ) );
  578. }
  579. if ( bLightmappedMaterial )
  580. {
  581. float flOffset = ComputeDecalLightmapOffset( pFragment->m_SurfId );
  582. for ( iVert = 0; iVert < nVertCount; ++iVert, ++pVert )
  583. {
  584. unsigned char nAlpha = FastFToC( pVert->flAlpha );
  585. meshBuilder.Position3fv( pVert->pos.Base() );
  586. meshBuilder.Normal3fv( pVert->normal.Base() );
  587. meshBuilder.Color4ub( 255, 255, 255, nAlpha );
  588. meshBuilder.TexCoord2fv( 0, pVert->texCoord[0].Base() );
  589. meshBuilder.TexCoord2fv( 1, pVert->lightCoord );
  590. meshBuilder.TexCoord1f( 2, flOffset );
  591. meshBuilder.AdvanceVertex();
  592. }
  593. }
  594. else
  595. {
  596. for ( iVert = 0; iVert < nVertCount; ++iVert, ++pVert )
  597. {
  598. unsigned char nAlpha = FastFToC( pVert->flAlpha );
  599. meshBuilder.Position3fv( pVert->pos.Base() );
  600. meshBuilder.Normal3fv( pVert->normal.Base() );
  601. meshBuilder.Color4ub( 255, 255, 255, nAlpha );
  602. meshBuilder.TexCoord2fv( 0, pVert->texCoord[0].Base() );
  603. meshBuilder.TexCoord2fv( 1, pVert->lightCoord );
  604. meshBuilder.TexCoord2fv( 2, pVert->texCoord[1].Base() );
  605. meshBuilder.AdvanceVertex();
  606. }
  607. }
  608. polyList.AddToTail( nVertCount );
  609. }
  610. if (pMesh)
  611. {
  612. CIndexBuilder &indexBuilder = meshBuilder;
  613. indexBuilder.FastPolygonList( 0, polyList.Base(), polyList.Count() );
  614. meshBuilder.End();
  615. pMesh->Draw();
  616. }
  617. }
  618. }
  619. ++iCurrentRenderOrder;
  620. }
  621. #endif
  622. }
  623. void COverlayMgr::SetOverlayBindProxy( int iOverlayID, void *pBindProxy )
  624. {
  625. moverlay_t *pOverlay = GetOverlay( iOverlayID );
  626. if ( pOverlay )
  627. pOverlay->m_pBindProxy = pBindProxy;
  628. }
  629. //-----------------------------------------------------------------------------
  630. //-----------------------------------------------------------------------------
  631. bool COverlayMgr::Surf_PreClipFragment( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag,
  632. SurfaceHandle_t surfID, moverlayfragment_t &surfaceFrag )
  633. {
  634. MEM_ALLOC_CREDIT();
  635. // Convert the overlay uv points to overlay plane points.
  636. overlayFrag.m_aPrimVerts.SetCount( 4 );
  637. for( int iVert = 0; iVert < 4; ++iVert )
  638. {
  639. Overlay_OverlayUVToOverlayPlane( pOverlay->m_vecOrigin, pOverlay->m_vecBasis[0],
  640. pOverlay->m_vecBasis[1], pOverlay->m_vecUVPoints[iVert],
  641. overlayFrag.m_aPrimVerts[iVert].pos );
  642. }
  643. // Overlay texture coordinates.
  644. InitTexCoords( pOverlay, overlayFrag );
  645. // Surface
  646. int nVertCount = surfaceFrag.m_aPrimVerts.Count();
  647. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  648. {
  649. // Position.
  650. Overlay_WorldToOverlayPlane( pOverlay->m_vecOrigin, pOverlay->m_vecBasis[2],
  651. surfaceFrag.m_aPrimVerts[iVert].pos, surfaceFrag.m_aPrimVerts[iVert].pos );
  652. }
  653. return true;
  654. }
  655. //-----------------------------------------------------------------------------
  656. //-----------------------------------------------------------------------------
  657. void COverlayMgr::Surf_PostClipFragment( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag,
  658. SurfaceHandle_t surfID )
  659. {
  660. #ifndef SWDS
  661. // Get fragment vertex count.
  662. int nVertCount = overlayFrag.m_aPrimVerts.Count();
  663. if ( nVertCount == 0 )
  664. return;
  665. // Create fragment.
  666. OverlayFragmentHandle_t hFragment = AddFragmentToFragmentList( nVertCount );
  667. moverlayfragment_t *pFragment = GetOverlayFragment( hFragment );
  668. // Get surface context.
  669. SurfaceCtx_t ctx;
  670. SurfSetupSurfaceContext( ctx, surfID );
  671. pFragment->m_iOverlay = pOverlay->m_nId;
  672. pFragment->m_SurfId = surfID;
  673. const Vector &vNormal = MSurf_Plane( surfID ).normal;
  674. moverlayfragment_t origOverlay;
  675. origOverlay.m_aPrimVerts.SetSize( 4 );
  676. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  677. {
  678. Overlay_OverlayUVToOverlayPlane( pOverlay->m_vecOrigin, pOverlay->m_vecBasis[0],
  679. pOverlay->m_vecBasis[1], pOverlay->m_vecUVPoints[iPoint],
  680. origOverlay.m_aPrimVerts[iPoint].pos );
  681. }
  682. InitTexCoords( pOverlay, origOverlay );
  683. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  684. {
  685. Vector2D vecUV;
  686. PointInQuadToBarycentric( origOverlay.m_aPrimVerts[0].pos,
  687. origOverlay.m_aPrimVerts[3].pos,
  688. origOverlay.m_aPrimVerts[2].pos,
  689. origOverlay.m_aPrimVerts[1].pos,
  690. overlayFrag.m_aPrimVerts[iVert].pos, vecUV );
  691. Overlay_OverlayPlaneToWorld( pOverlay->m_vecBasis[2], surfID,
  692. overlayFrag.m_aPrimVerts[iVert].pos,
  693. pFragment->m_aPrimVerts[iVert].pos );
  694. // Texture coordinates.
  695. Vector2D vecTexCoord;
  696. for ( int iTexCoord=0; iTexCoord < NUM_OVERLAY_TEXCOORDS; iTexCoord++ )
  697. {
  698. TexCoordInQuadFromBarycentric( origOverlay.m_aPrimVerts[0].texCoord[iTexCoord], origOverlay.m_aPrimVerts[3].texCoord[iTexCoord],
  699. origOverlay.m_aPrimVerts[2].texCoord[iTexCoord], origOverlay.m_aPrimVerts[1].texCoord[iTexCoord],
  700. vecUV, vecTexCoord );
  701. pFragment->m_aPrimVerts[iVert].texCoord[iTexCoord][0] = vecTexCoord.x;
  702. pFragment->m_aPrimVerts[iVert].texCoord[iTexCoord][1] = vecTexCoord.y;
  703. }
  704. // Normals : FIXME this isn't an interpolated normal.
  705. pFragment->m_aPrimVerts[iVert].normal = vNormal;
  706. // Lightmap coordinates.
  707. Vector2D uv;
  708. SurfComputeLightmapCoordinate( ctx, surfID, pFragment->m_aPrimVerts[iVert].pos, uv );
  709. pFragment->m_aPrimVerts[iVert].lightCoord[0] = uv.x;
  710. pFragment->m_aPrimVerts[iVert].lightCoord[1] = uv.y;
  711. // Push -just- off the surface to avoid z-clipping errors.
  712. pFragment->m_aPrimVerts[iVert].pos += vNormal * OVERLAY_AVOID_FLICKER_NORMAL_OFFSET;
  713. }
  714. // Create the sort ID for this fragment
  715. const MaterialSystem_SortInfo_t &sortInfo = materialSortInfoArray[MSurf_MaterialSortID( surfID )];
  716. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[pOverlay->m_nTexInfo];
  717. pFragment->m_nMaterialSortID = GetMaterialSortID( pTexInfo->material, sortInfo.lightmapPageID );
  718. // Add to list of fragments for this overlay
  719. MEM_ALLOC_CREDIT();
  720. OverlayFragmentList_t i = m_OverlayFragments.Alloc( true );
  721. m_OverlayFragments[i] = hFragment;
  722. m_OverlayFragments.LinkBefore( pOverlay->m_hFirstFragment, i );
  723. pOverlay->m_hFirstFragment = i;
  724. // Add to list of fragments for this surface
  725. // NOTE: Store them in *reverse* order so that when we pull them off for
  726. // rendering, we can do *that* in reverse order too? Reduces the amount of iteration necessary
  727. // Therefore, we need to add to the head of the list
  728. m_aFragments.LinkBefore( MSurf_OverlayFragmentList( surfID ), hFragment );
  729. MSurf_OverlayFragmentList( surfID ) = hFragment;
  730. #endif // !SWDS
  731. }
  732. //-----------------------------------------------------------------------------
  733. // Clips an overlay to a surface
  734. //-----------------------------------------------------------------------------
  735. void COverlayMgr::Surf_ClipFragment( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag,
  736. SurfaceHandle_t surfID, moverlayfragment_t &surfaceFrag )
  737. {
  738. MEM_ALLOC_CREDIT();
  739. // Create the clip planes.
  740. CUtlVector<cplane_t> m_ClipPlanes;
  741. BuildClipPlanes( surfID, surfaceFrag, pOverlay->m_vecBasis[2], m_ClipPlanes );
  742. // Copy the overlay fragment (initial clipped fragment).
  743. moverlayfragment_t *pClippedFrag = CopyTempFragment( &overlayFrag );
  744. for( int iPlane = 0; iPlane < m_ClipPlanes.Count(); ++iPlane )
  745. {
  746. moverlayfragment_t *pFront = NULL, *pBack = NULL;
  747. DoClipFragment( pClippedFrag, &m_ClipPlanes[iPlane], &pFront, &pBack );
  748. DestroyTempFragment( pClippedFrag );
  749. pClippedFrag = NULL;
  750. // Keep the backside and continue clipping.
  751. if ( pBack )
  752. {
  753. pClippedFrag = pBack;
  754. }
  755. if ( pFront )
  756. {
  757. DestroyTempFragment( pFront );
  758. }
  759. }
  760. m_ClipPlanes.Purge();
  761. // Copy the clipped polygon back to the overlay frag.
  762. overlayFrag.m_aPrimVerts.RemoveAll();
  763. if ( pClippedFrag )
  764. {
  765. overlayFrag.m_aPrimVerts.SetCount( pClippedFrag->m_aPrimVerts.Count() );
  766. for ( int iVert = 0; iVert < pClippedFrag->m_aPrimVerts.Count(); ++iVert )
  767. {
  768. overlayFrag.m_aPrimVerts[iVert].pos = pClippedFrag->m_aPrimVerts[iVert].pos;
  769. memcpy( overlayFrag.m_aPrimVerts[iVert].texCoord, pClippedFrag->m_aPrimVerts[iVert].texCoord, sizeof( overlayFrag.m_aPrimVerts[iVert].texCoord ) );
  770. }
  771. }
  772. DestroyTempFragment( pClippedFrag );
  773. }
  774. inline float TriangleArea( const Vector &v0, const Vector &v1, const Vector &v2 )
  775. {
  776. Vector vecEdge0, vecEdge1, vecCross;
  777. VectorSubtract( v1, v0, vecEdge0 );
  778. VectorSubtract( v2, v0, vecEdge1 );
  779. CrossProduct( vecEdge0, vecEdge1, vecCross );
  780. return ( VectorLength( vecCross ) * 0.5f );
  781. }
  782. //-----------------------------------------------------------------------------
  783. // Creates overlay fragments for a particular surface
  784. //-----------------------------------------------------------------------------
  785. void COverlayMgr::Surf_CreateFragments( moverlay_t *pOverlay, SurfaceHandle_t surfID )
  786. {
  787. moverlayfragment_t overlayFrag, surfaceFrag;
  788. // The faces get fan tesselated into triangles when rendered - do the same to
  789. // create the fragments!
  790. int iFirstVert = MSurf_FirstVertIndex( surfID );
  791. int nSurfTriangleCount = MSurf_VertCount( surfID ) - 2;
  792. for( int iTri = 0; iTri < nSurfTriangleCount; ++iTri )
  793. {
  794. // 3 Points in a triangle.
  795. surfaceFrag.m_aPrimVerts.SetCount( 3 );
  796. int iVert = host_state.worldbrush->vertindices[(iFirstVert)];
  797. mvertex_t *pVert = &host_state.worldbrush->vertexes[iVert];
  798. surfaceFrag.m_aPrimVerts[0].pos = pVert->position;
  799. iVert = host_state.worldbrush->vertindices[(iFirstVert+iTri+1)];
  800. pVert = &host_state.worldbrush->vertexes[iVert];
  801. surfaceFrag.m_aPrimVerts[1].pos = pVert->position;
  802. iVert = host_state.worldbrush->vertindices[(iFirstVert+iTri+2)];
  803. pVert = &host_state.worldbrush->vertexes[iVert];
  804. surfaceFrag.m_aPrimVerts[2].pos = pVert->position;
  805. if ( TriangleArea( surfaceFrag.m_aPrimVerts[0].pos, surfaceFrag.m_aPrimVerts[1].pos, surfaceFrag.m_aPrimVerts[2].pos ) > 1.0f )
  806. {
  807. if ( Surf_PreClipFragment( pOverlay, overlayFrag, surfID, surfaceFrag ) )
  808. {
  809. Surf_ClipFragment( pOverlay, overlayFrag, surfID, surfaceFrag );
  810. Surf_PostClipFragment( pOverlay, overlayFrag, surfID );
  811. }
  812. }
  813. // Clean up!
  814. surfaceFrag.m_aPrimVerts.RemoveAll();
  815. overlayFrag.m_aPrimVerts.RemoveAll();
  816. }
  817. }
  818. //-----------------------------------------------------------------------------
  819. // Creates fragments from the overlays loaded in from file
  820. //-----------------------------------------------------------------------------
  821. void COverlayMgr::CreateFragments( void )
  822. {
  823. int nOverlayCount = m_aOverlays.Count();
  824. for ( int iOverlay = 0; iOverlay < nOverlayCount; ++iOverlay )
  825. {
  826. moverlay_t *pOverlay = &m_aOverlays.Element( iOverlay );
  827. int nFaceCount = pOverlay->m_aFaces.Count();
  828. if ( nFaceCount == 0 )
  829. continue;
  830. // Build the overlay basis.
  831. bool bFlip = ( pOverlay->m_vecUVPoints[3].z == 1.0f );
  832. pOverlay->m_vecUVPoints[3].z = 0.0f;
  833. Overlay_BuildBasis( pOverlay->m_vecBasis[2], pOverlay->m_vecBasis[0], pOverlay->m_vecBasis[1], bFlip );
  834. // Clip against each face in the face list.
  835. for( int iFace = 0; iFace < nFaceCount; ++iFace )
  836. {
  837. SurfaceHandle_t surfID = pOverlay->m_aFaces[iFace];
  838. if ( SurfaceHasDispInfo( surfID ) )
  839. {
  840. Disp_CreateFragments( pOverlay, surfID );
  841. }
  842. else
  843. {
  844. Surf_CreateFragments( pOverlay, surfID );
  845. }
  846. }
  847. }
  848. // Overlay checking!
  849. for ( int iOverlay = 0; iOverlay < nOverlayCount; ++iOverlay )
  850. {
  851. moverlay_t *pOverlay = &m_aOverlays.Element( iOverlay );
  852. int hFrag = pOverlay->m_hFirstFragment;
  853. while ( hFrag != OVERLAY_FRAGMENT_INVALID )
  854. {
  855. int iFrag = m_OverlayFragments[hFrag];
  856. moverlayfragment_t *pFrag = &m_aFragments[iFrag];
  857. int nVertCount = pFrag->m_aPrimVerts.Count();
  858. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  859. {
  860. overlayvert_t *pVert = &pFrag->m_aPrimVerts[iVert];
  861. if ( !pVert->pos.IsValid() )
  862. {
  863. Assert( 0 );
  864. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[pOverlay->m_nTexInfo];
  865. DevMsg( 1, "Bad overlay vert - %d at (%f, %f, %f) with material '%s'\n", iOverlay,
  866. pOverlay->m_vecOrigin.x, pOverlay->m_vecOrigin.y, pOverlay->m_vecOrigin.z,
  867. ( pTexInfo && pTexInfo->material ) ? pTexInfo->material->GetName() : "" );
  868. }
  869. if ( !pVert->normal.IsValid() )
  870. {
  871. Assert( 0 );
  872. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[pOverlay->m_nTexInfo];
  873. DevMsg( 1, "Bad overlay normal - %d at (%f, %f, %f) with material '%s'\n", iOverlay,
  874. pOverlay->m_vecOrigin.x, pOverlay->m_vecOrigin.y, pOverlay->m_vecOrigin.z,
  875. ( pTexInfo && pTexInfo->material ) ? pTexInfo->material->GetName() : "" );
  876. }
  877. if ( !pVert->texCoord[0].IsValid() || !pVert->texCoord[1].IsValid() )
  878. {
  879. Assert( 0 );
  880. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[pOverlay->m_nTexInfo];
  881. DevMsg( 1, "Bad overlay texture coords - %d at (%f, %f, %f) with material '%s'\n", iOverlay,
  882. pOverlay->m_vecOrigin.x, pOverlay->m_vecOrigin.y, pOverlay->m_vecOrigin.z,
  883. ( pTexInfo && pTexInfo->material ) ? pTexInfo->material->GetName() : "" );
  884. }
  885. }
  886. hFrag = m_OverlayFragments.Next( hFrag );
  887. }
  888. }
  889. }
  890. //-----------------------------------------------------------------------------
  891. // Purpose:
  892. //-----------------------------------------------------------------------------
  893. void COverlayMgr::ReSortMaterials( void )
  894. {
  895. #ifndef SWDS
  896. // Clear the old render queue.
  897. m_RenderQueue.Purge();
  898. for ( int iSort = 0; iSort < MAX_MAT_SORT_GROUPS; ++iSort )
  899. {
  900. m_nFirstRenderQueue[iSort] = RENDER_QUEUE_INVALID;
  901. }
  902. // Update all fragments.
  903. int nOverlayCount = m_aOverlays.Count();
  904. for ( int iOverlay = 0; iOverlay < nOverlayCount; ++iOverlay )
  905. {
  906. moverlay_t *pOverlay = &m_aOverlays.Element( iOverlay );
  907. if ( !pOverlay )
  908. continue;
  909. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[pOverlay->m_nTexInfo];
  910. if ( !pTexInfo )
  911. continue;
  912. int hFrag = pOverlay->m_hFirstFragment;
  913. while ( hFrag != OVERLAY_FRAGMENT_INVALID )
  914. {
  915. int iFrag = m_OverlayFragments[hFrag];
  916. moverlayfragment_t *pFrag = &m_aFragments[iFrag];
  917. if ( pFrag )
  918. {
  919. const MaterialSystem_SortInfo_t &sortInfo = materialSortInfoArray[MSurf_MaterialSortID( pFrag->m_SurfId )];
  920. pFrag->m_nMaterialSortID = GetMaterialSortID( pTexInfo->material, sortInfo.lightmapPageID );
  921. // Get surface context.
  922. SurfaceCtx_t ctx;
  923. SurfSetupSurfaceContext( ctx, pFrag->m_SurfId );
  924. int nVertCount = pFrag->m_aPrimVerts.Count();
  925. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  926. {
  927. // Lightmap coordinates.
  928. Vector2D uv;
  929. SurfComputeLightmapCoordinate( ctx, pFrag->m_SurfId, pFrag->m_aPrimVerts[iVert].pos, uv );
  930. pFrag->m_aPrimVerts[iVert].lightCoord[0] = uv.x;
  931. pFrag->m_aPrimVerts[iVert].lightCoord[1] = uv.y;
  932. }
  933. }
  934. hFrag = m_OverlayFragments.Next( hFrag );
  935. }
  936. }
  937. #endif // !SWDS
  938. }
  939. //-----------------------------------------------------------------------------
  940. // Loads overlays from the lump
  941. //-----------------------------------------------------------------------------
  942. bool COverlayMgr::LoadOverlays( )
  943. {
  944. CMapLoadHelper lh( LUMP_OVERLAYS );
  945. CMapLoadHelper lh2( LUMP_WATEROVERLAYS );
  946. CMapLoadHelper lhOverlayFades( LUMP_OVERLAY_FADES );
  947. doverlay_t *pOverlayIn;
  948. dwateroverlay_t *pWaterOverlayIn;
  949. pOverlayIn = ( doverlay_t* )lh.LumpBase();
  950. if ( lh.LumpSize() % sizeof( doverlay_t ) )
  951. return false;
  952. pWaterOverlayIn = ( dwateroverlay_t* )lh2.LumpBase();
  953. if ( lh2.LumpSize() % sizeof( dwateroverlay_t ) )
  954. return false;
  955. // Fade distances are in a parallel lump
  956. doverlayfade_t *pOverlayFadesIn = (doverlayfade_t *)lhOverlayFades.LumpBase();
  957. if ( lhOverlayFades.LumpSize() % sizeof( doverlayfade_t ) )
  958. return false;
  959. int nOverlayCount = lh.LumpSize() / sizeof( doverlay_t );
  960. int nWaterOverlayCount = lh2.LumpSize() / sizeof( dwateroverlay_t );
  961. // Memory allocation!
  962. m_aOverlays.SetSize( nOverlayCount + nWaterOverlayCount );
  963. for( int iOverlay = 0; iOverlay < nOverlayCount; ++iOverlay, ++pOverlayIn )
  964. {
  965. moverlay_t *pOverlayOut = &m_aOverlays.Element( iOverlay );
  966. pOverlayOut->m_nId = iOverlay;
  967. pOverlayOut->m_nTexInfo = pOverlayIn->nTexInfo;
  968. pOverlayOut->m_nRenderOrder = pOverlayIn->GetRenderOrder();
  969. if ( pOverlayOut->m_nRenderOrder >= OVERLAY_NUM_RENDER_ORDERS )
  970. Error( "COverlayMgr::LoadOverlays: invalid render order (%d) for an overlay.", pOverlayOut->m_nRenderOrder );
  971. pOverlayOut->m_flU[0] = pOverlayIn->flU[0];
  972. pOverlayOut->m_flU[1] = pOverlayIn->flU[1];
  973. pOverlayOut->m_flV[0] = pOverlayIn->flV[0];
  974. pOverlayOut->m_flV[1] = pOverlayIn->flV[1];
  975. if ( pOverlayFadesIn )
  976. {
  977. pOverlayOut->m_flFadeDistMinSq = pOverlayFadesIn->flFadeDistMinSq;
  978. pOverlayOut->m_flFadeDistMaxSq = pOverlayFadesIn->flFadeDistMaxSq;
  979. pOverlayOut->m_flInvFadeRangeSq = 1.0f / ( pOverlayFadesIn->flFadeDistMaxSq - pOverlayFadesIn->flFadeDistMinSq );
  980. pOverlayFadesIn++;
  981. }
  982. else
  983. {
  984. pOverlayOut->m_flFadeDistMinSq = -1.0f;
  985. pOverlayOut->m_flFadeDistMaxSq = 0;
  986. pOverlayOut->m_flInvFadeRangeSq = 1.0f;
  987. }
  988. VectorCopy( pOverlayIn->vecOrigin, pOverlayOut->m_vecOrigin );
  989. VectorCopy( pOverlayIn->vecUVPoints[0], pOverlayOut->m_vecUVPoints[0] );
  990. VectorCopy( pOverlayIn->vecUVPoints[1], pOverlayOut->m_vecUVPoints[1] );
  991. VectorCopy( pOverlayIn->vecUVPoints[2], pOverlayOut->m_vecUVPoints[2] );
  992. VectorCopy( pOverlayIn->vecUVPoints[3], pOverlayOut->m_vecUVPoints[3] );
  993. VectorCopy( pOverlayIn->vecBasisNormal, pOverlayOut->m_vecBasis[2] );
  994. // Basis U is encoded in the z components of the UVPoints 0, 1, 2
  995. pOverlayOut->m_vecBasis[0].x = pOverlayOut->m_vecUVPoints[0].z;
  996. pOverlayOut->m_vecBasis[0].y = pOverlayOut->m_vecUVPoints[1].z;
  997. pOverlayOut->m_vecBasis[0].z = pOverlayOut->m_vecUVPoints[2].z;
  998. if ( pOverlayOut->m_vecBasis[0].x == 0.0f && pOverlayOut->m_vecBasis[0].y == 0.0f && pOverlayOut->m_vecBasis[0].z == 0.0f )
  999. {
  1000. Warning( "Bad overlay basis at (%f %f %f)!\n", pOverlayOut->m_vecOrigin.x, pOverlayOut->m_vecOrigin.y, pOverlayOut->m_vecOrigin.z );
  1001. }
  1002. CrossProduct( pOverlayOut->m_vecBasis[2], pOverlayOut->m_vecBasis[0], pOverlayOut->m_vecBasis[1] );
  1003. VectorNormalize( pOverlayOut->m_vecBasis[1] );
  1004. pOverlayOut->m_vecUVPoints[0].z = 0.0f;
  1005. pOverlayOut->m_vecUVPoints[1].z = 0.0f;
  1006. pOverlayOut->m_vecUVPoints[2].z = 0.0f;
  1007. pOverlayOut->m_aFaces.SetSize( pOverlayIn->GetFaceCount() );
  1008. for( int iFace = 0; iFace < pOverlayIn->GetFaceCount(); ++iFace )
  1009. {
  1010. pOverlayOut->m_aFaces[iFace] = SurfaceHandleFromIndex( pOverlayIn->aFaces[iFace], lh.GetMap() );
  1011. }
  1012. pOverlayOut->m_hFirstFragment = OVERLAY_FRAGMENT_LIST_INVALID;
  1013. pOverlayOut->m_pBindProxy = NULL;
  1014. }
  1015. for( int iWaterOverlay = 0; iWaterOverlay < nWaterOverlayCount; ++iWaterOverlay, ++pWaterOverlayIn )
  1016. {
  1017. moverlay_t *pOverlayOut = &m_aOverlays.Element( nOverlayCount + iWaterOverlay );
  1018. pOverlayOut->m_nId = nOverlayCount + iWaterOverlay;
  1019. pOverlayOut->m_nTexInfo = pWaterOverlayIn->nTexInfo;
  1020. pOverlayOut->m_nRenderOrder = pWaterOverlayIn->GetRenderOrder();
  1021. if ( pOverlayOut->m_nRenderOrder >= OVERLAY_NUM_RENDER_ORDERS )
  1022. Error( "COverlayMgr::LoadOverlays: invalid render order (%d) for an overlay.", pOverlayOut->m_nRenderOrder );
  1023. pOverlayOut->m_flU[0] = pWaterOverlayIn->flU[0];
  1024. pOverlayOut->m_flU[1] = pWaterOverlayIn->flU[1];
  1025. pOverlayOut->m_flV[0] = pWaterOverlayIn->flV[0];
  1026. pOverlayOut->m_flV[1] = pWaterOverlayIn->flV[1];
  1027. VectorCopy( pWaterOverlayIn->vecOrigin, pOverlayOut->m_vecOrigin );
  1028. VectorCopy( pWaterOverlayIn->vecUVPoints[0], pOverlayOut->m_vecUVPoints[0] );
  1029. VectorCopy( pWaterOverlayIn->vecUVPoints[1], pOverlayOut->m_vecUVPoints[1] );
  1030. VectorCopy( pWaterOverlayIn->vecUVPoints[2], pOverlayOut->m_vecUVPoints[2] );
  1031. VectorCopy( pWaterOverlayIn->vecUVPoints[3], pOverlayOut->m_vecUVPoints[3] );
  1032. VectorCopy( pWaterOverlayIn->vecBasisNormal, pOverlayOut->m_vecBasis[2] );
  1033. // Basis U is encoded in the z components of the UVPoints 0, 1, 2
  1034. pOverlayOut->m_vecBasis[0].x = pOverlayOut->m_vecUVPoints[0].z;
  1035. pOverlayOut->m_vecBasis[0].y = pOverlayOut->m_vecUVPoints[1].z;
  1036. pOverlayOut->m_vecBasis[0].z = pOverlayOut->m_vecUVPoints[2].z;
  1037. if ( pOverlayOut->m_vecBasis[0].x == 0.0f && pOverlayOut->m_vecBasis[0].y == 0.0f && pOverlayOut->m_vecBasis[0].z == 0.0f )
  1038. {
  1039. Warning( "Bad overlay basis at (%f %f %f)!\n", pOverlayOut->m_vecOrigin.x, pOverlayOut->m_vecOrigin.y, pOverlayOut->m_vecOrigin.z );
  1040. }
  1041. CrossProduct( pOverlayOut->m_vecBasis[2], pOverlayOut->m_vecBasis[0], pOverlayOut->m_vecBasis[1] );
  1042. VectorNormalize( pOverlayOut->m_vecBasis[1] );
  1043. pOverlayOut->m_vecUVPoints[0].z = 0.0f;
  1044. pOverlayOut->m_vecUVPoints[1].z = 0.0f;
  1045. pOverlayOut->m_vecUVPoints[2].z = 0.0f;
  1046. pOverlayOut->m_aFaces.SetSize( pWaterOverlayIn->GetFaceCount() );
  1047. for( int iFace = 0; iFace < pWaterOverlayIn->GetFaceCount(); ++iFace )
  1048. {
  1049. pOverlayOut->m_aFaces[iFace] = SurfaceHandleFromIndex( pWaterOverlayIn->aFaces[iFace], lh2.GetMap() );
  1050. }
  1051. pOverlayOut->m_hFirstFragment = OVERLAY_FRAGMENT_LIST_INVALID;
  1052. pOverlayOut->m_pBindProxy = NULL;
  1053. }
  1054. return true;
  1055. }
  1056. //-----------------------------------------------------------------------------
  1057. // Purpose:
  1058. //-----------------------------------------------------------------------------
  1059. void COverlayMgr::Disp_CreateFragments( moverlay_t *pOverlay, SurfaceHandle_t surfID )
  1060. {
  1061. OverlayFragmentVector_t aDispFragments;
  1062. if ( Disp_PreClipFragment( pOverlay, aDispFragments, surfID ) )
  1063. {
  1064. IDispInfo *pIDisp = MSurf_DispInfo( surfID );
  1065. CDispInfo *pDisp = static_cast<CDispInfo*>( pIDisp );
  1066. if ( pDisp )
  1067. {
  1068. Disp_ClipFragment( pDisp, aDispFragments );
  1069. Disp_PostClipFragment( pDisp, &pDisp->m_MeshReader, pOverlay, aDispFragments, surfID );
  1070. }
  1071. }
  1072. for ( int i = aDispFragments.Count(); --i >= 0; )
  1073. {
  1074. DestroyTempFragment( aDispFragments[i] );
  1075. }
  1076. }
  1077. //-----------------------------------------------------------------------------
  1078. // Purpose:
  1079. //-----------------------------------------------------------------------------
  1080. bool COverlayMgr::Disp_PreClipFragment( moverlay_t *pOverlay, OverlayFragmentVector_t &aDispFragments,
  1081. SurfaceHandle_t surfID )
  1082. {
  1083. MEM_ALLOC_CREDIT();
  1084. // The faces are not tesselated when they are displaced faces.
  1085. int iFirstVert = MSurf_FirstVertIndex( surfID );
  1086. // Displaced faces are quads.
  1087. moverlayfragment_t surfaceFrag;
  1088. surfaceFrag.m_aPrimVerts.SetCount( 4 );
  1089. for( int iVert = 0; iVert < 4; ++iVert )
  1090. {
  1091. int iVertex = host_state.worldbrush->vertindices[(iFirstVert+iVert)];
  1092. mvertex_t *pVert = &host_state.worldbrush->vertexes[iVertex];
  1093. surfaceFrag.m_aPrimVerts[iVert].pos = pVert->position;
  1094. }
  1095. // Setup the base fragment to be clipped by the base surface previous to the
  1096. // displaced surface.
  1097. moverlayfragment_t overlayFrag;
  1098. if ( !Surf_PreClipFragment( pOverlay, overlayFrag, surfID, surfaceFrag ) )
  1099. return false;
  1100. Surf_ClipFragment( pOverlay, overlayFrag, surfID, surfaceFrag );
  1101. // Get fragment vertex count.
  1102. int nVertCount = overlayFrag.m_aPrimVerts.Count();
  1103. if ( nVertCount == 0 )
  1104. return false;
  1105. // Setup
  1106. moverlayfragment_t *pFragment = CopyTempFragment( &overlayFrag );
  1107. aDispFragments.AddToTail( pFragment );
  1108. IDispInfo *pIDispInfo = MSurf_DispInfo( surfID );
  1109. CDispInfo *pDispInfo = static_cast<CDispInfo*>( pIDispInfo );
  1110. int iPointStart = pDispInfo->m_iPointStart;
  1111. Vector2D vecTmpUV;
  1112. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  1113. {
  1114. PointInQuadToBarycentric( surfaceFrag.m_aPrimVerts[iPointStart].pos,
  1115. surfaceFrag.m_aPrimVerts[(iPointStart+3)%4].pos,
  1116. surfaceFrag.m_aPrimVerts[(iPointStart+2)%4].pos,
  1117. surfaceFrag.m_aPrimVerts[(iPointStart+1)%4].pos,
  1118. overlayFrag.m_aPrimVerts[iVert].pos,
  1119. vecTmpUV );
  1120. if ( !vecTmpUV.IsValid() )
  1121. {
  1122. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[pOverlay->m_nTexInfo];
  1123. DevWarning( 1, "Bad overlay geometry at %s with material '%s'\n", VecToString(pOverlay->m_vecOrigin),
  1124. ( pTexInfo && pTexInfo->material ) ? pTexInfo->material->GetName() : "" );
  1125. return false;
  1126. }
  1127. pFragment->m_aPrimVerts[iVert].pos.x = vecTmpUV.x;
  1128. pFragment->m_aPrimVerts[iVert].pos.y = vecTmpUV.y;
  1129. pFragment->m_aPrimVerts[iVert].pos.z = 0.0f;
  1130. }
  1131. return true;
  1132. }
  1133. //-----------------------------------------------------------------------------
  1134. // Purpose:
  1135. //-----------------------------------------------------------------------------
  1136. void COverlayMgr::Disp_PostClipFragment( CDispInfo *pDisp, CMeshReader *pReader, moverlay_t *pOverlay,
  1137. OverlayFragmentVector_t &aDispFragments, SurfaceHandle_t surfID )
  1138. {
  1139. #ifndef SWDS
  1140. if ( aDispFragments.Count() == 0 )
  1141. return;
  1142. // Get surface context.
  1143. SurfaceCtx_t ctx;
  1144. SurfSetupSurfaceContext( ctx, surfID );
  1145. // The faces are not tesselated when they are displaced faces.
  1146. int iFirstVert = MSurf_FirstVertIndex( surfID );
  1147. // Displaced faces are quads.
  1148. moverlayfragment_t surfaceFrag;
  1149. surfaceFrag.m_aPrimVerts.SetCount( 4 );
  1150. for( int iVert = 0; iVert < 4; ++iVert )
  1151. {
  1152. int iVertex = host_state.worldbrush->vertindices[(iFirstVert+iVert)];
  1153. mvertex_t *pVert = &host_state.worldbrush->vertexes[iVertex];
  1154. surfaceFrag.m_aPrimVerts[iVert].pos = pVert->position;
  1155. }
  1156. Vector2D lightCoords[4];
  1157. int nInterval = pDisp->GetSideLength();
  1158. pReader->TexCoord2f( 0, DISP_LMCOORDS_STAGE, lightCoords[0].x, lightCoords[0].y );
  1159. pReader->TexCoord2f( nInterval - 1, DISP_LMCOORDS_STAGE, lightCoords[1].x, lightCoords[1].y );
  1160. pReader->TexCoord2f( ( nInterval * nInterval ) - 1, DISP_LMCOORDS_STAGE, lightCoords[2].x, lightCoords[2].y );
  1161. pReader->TexCoord2f( nInterval * ( nInterval - 1 ), DISP_LMCOORDS_STAGE, lightCoords[3].x, lightCoords[3].y );
  1162. // Get the number of displacement fragments.
  1163. int nFragCount = aDispFragments.Count();
  1164. for ( int iFrag = 0; iFrag < nFragCount; ++iFrag )
  1165. {
  1166. moverlayfragment_t *pDispFragment = aDispFragments[iFrag];
  1167. if ( !pDispFragment )
  1168. continue;
  1169. int nVertCount = pDispFragment->m_aPrimVerts.Count();
  1170. if ( nVertCount < 3 )
  1171. continue;
  1172. // Create fragment.
  1173. OverlayFragmentHandle_t hFragment = AddFragmentToFragmentList( nVertCount );
  1174. moverlayfragment_t *pFragment = GetOverlayFragment( hFragment );
  1175. pFragment->m_iOverlay = pOverlay->m_nId;
  1176. pFragment->m_SurfId = surfID;
  1177. Vector2D vecTmpUV;
  1178. Vector vecTmp;
  1179. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  1180. {
  1181. vecTmpUV.x = pDispFragment->m_aPrimVerts[iVert].pos.x;
  1182. vecTmpUV.y = pDispFragment->m_aPrimVerts[iVert].pos.y;
  1183. vecTmpUV.x = clamp( vecTmpUV.x, 0.0f, 1.0f );
  1184. vecTmpUV.y = clamp( vecTmpUV.y, 0.0f, 1.0f );
  1185. Overlay_DispUVToWorld( pDisp, pReader, vecTmpUV, pFragment->m_aPrimVerts[iVert].pos, surfaceFrag );
  1186. // Texture coordinates.
  1187. pFragment->m_aPrimVerts[iVert].texCoord[0] = pDispFragment->m_aPrimVerts[iVert].texCoord[0];
  1188. pFragment->m_aPrimVerts[iVert].texCoord[1] = pDispFragment->m_aPrimVerts[iVert].texCoord[1];
  1189. // Lightmap coordinates.
  1190. Vector2D uv;
  1191. TexCoordInQuadFromBarycentric( lightCoords[0], lightCoords[1], lightCoords[2], lightCoords[3], vecTmpUV, uv );
  1192. pFragment->m_aPrimVerts[iVert].lightCoord[0] = uv.x;
  1193. pFragment->m_aPrimVerts[iVert].lightCoord[1] = uv.y;
  1194. }
  1195. // Calculate the normal for this fragment.
  1196. Vector vecFragmentNormal;
  1197. Vector vecEdges[2];
  1198. VectorSubtract( pFragment->m_aPrimVerts[1].pos, pFragment->m_aPrimVerts[0].pos, vecEdges[0] );
  1199. VectorSubtract( pFragment->m_aPrimVerts[2].pos, pFragment->m_aPrimVerts[0].pos, vecEdges[1] );
  1200. vecFragmentNormal = CrossProduct( vecEdges[1], vecEdges[0] );
  1201. if ( VectorNormalize( vecFragmentNormal ) < 1e-3 )
  1202. {
  1203. vecFragmentNormal.Init( -vecEdges[1].y, vecEdges[1].x, 0.0f );
  1204. if ( VectorNormalize( vecFragmentNormal ) < 1e-3 )
  1205. {
  1206. vecFragmentNormal.Init( 0.0f, 0.0f, 1.0f );
  1207. }
  1208. }
  1209. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  1210. {
  1211. pFragment->m_aPrimVerts[iVert].normal = vecFragmentNormal;
  1212. }
  1213. // Create the sort ID for this fragment
  1214. const MaterialSystem_SortInfo_t &sortInfo = materialSortInfoArray[MSurf_MaterialSortID( surfID )];
  1215. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[pOverlay->m_nTexInfo];
  1216. pFragment->m_nMaterialSortID = GetMaterialSortID( pTexInfo->material, sortInfo.lightmapPageID );
  1217. // Add to list of fragments for this overlay
  1218. MEM_ALLOC_CREDIT();
  1219. OverlayFragmentList_t i = m_OverlayFragments.Alloc( true );
  1220. m_OverlayFragments[i] = hFragment;
  1221. m_OverlayFragments.LinkBefore( pOverlay->m_hFirstFragment, i );
  1222. pOverlay->m_hFirstFragment = i;
  1223. // Add to list of fragments for this surface
  1224. // NOTE: Store them in *reverse* order so that when we pull them off for
  1225. // rendering, we can do *that* in reverse order too? Reduces the amount of iteration necessary
  1226. // Therefore, we need to add to the head of the list
  1227. m_aFragments.LinkBefore( MSurf_OverlayFragmentList( surfID ), hFragment );
  1228. MSurf_OverlayFragmentList( surfID ) = hFragment;
  1229. }
  1230. #endif // !SWDS
  1231. }
  1232. //-----------------------------------------------------------------------------
  1233. // Purpose:
  1234. //-----------------------------------------------------------------------------
  1235. void COverlayMgr::Disp_ClipFragment( CDispInfo *pDisp, OverlayFragmentVector_t &aDispFragments )
  1236. {
  1237. cplane_t clipPlane;
  1238. // Cache the displacement interval.
  1239. const CPowerInfo *pPowerInfo = pDisp->GetPowerInfo();
  1240. int nInterval = ( 1 << pPowerInfo->GetPower() );
  1241. // Displacement-space clipping in V.
  1242. clipPlane.normal.Init( 1.0f, 0.0f, 0.0f );
  1243. Disp_DoClip( pDisp, aDispFragments, clipPlane, 1.0f, nInterval, 1, nInterval, 1 );
  1244. // Displacement-space clipping in U.
  1245. clipPlane.normal.Init( 0.0f, 1.0f, 0.0f );
  1246. Disp_DoClip( pDisp, aDispFragments, clipPlane, 1.0f, nInterval, 1, nInterval, 1 );
  1247. // Displacement-space clipping UV from top-left to bottom-right.
  1248. clipPlane.normal.Init( 0.707f, 0.707f, 0.0f ); // 45 degrees
  1249. Disp_DoClip( pDisp, aDispFragments, clipPlane, 0.707f, nInterval, 2, ( nInterval * 2 - 1 ), 2 );
  1250. // Displacement-space clipping UV from bottom-left to top-right.
  1251. clipPlane.normal.Init( -0.707f, 0.707f, 0.0f ); // 135 degrees
  1252. Disp_DoClip( pDisp, aDispFragments, clipPlane, 0.707f, nInterval, -( nInterval - 2 ), ( nInterval - 1 ), 2 );
  1253. }
  1254. //-----------------------------------------------------------------------------
  1255. //-----------------------------------------------------------------------------
  1256. void COverlayMgr::Disp_DoClip( CDispInfo *pDisp, OverlayFragmentVector_t &aDispFragments, cplane_t &clipPlane,
  1257. float clipDistStart, int nInterval,
  1258. int nLoopStart, int nLoopEnd, int nLoopInc )
  1259. {
  1260. // Setup interval information.
  1261. float flInterval = static_cast<float>( nInterval );
  1262. float flOOInterval = 1.0f / flInterval;
  1263. // Holds the current set of clipped faces.
  1264. OverlayFragmentVector_t aClippedFragments;
  1265. for ( int iInterval = nLoopStart; iInterval < nLoopEnd; iInterval += nLoopInc )
  1266. {
  1267. // Copy the current list to clipped face list.
  1268. aClippedFragments.CopyArray( aDispFragments.Base(), aDispFragments.Count() );
  1269. aDispFragments.Purge();
  1270. // Clip in V.
  1271. int nFragCount = aClippedFragments.Count();
  1272. for ( int iFrag = 0; iFrag < nFragCount; iFrag++ )
  1273. {
  1274. moverlayfragment_t *pClipFrag = aClippedFragments[iFrag];
  1275. if ( pClipFrag )
  1276. {
  1277. moverlayfragment_t *pFront = NULL, *pBack = NULL;
  1278. clipPlane.dist = clipDistStart * ( ( float )iInterval * flOOInterval );
  1279. DoClipFragment( pClipFrag, &clipPlane, &pFront, &pBack );
  1280. DestroyTempFragment( pClipFrag );
  1281. pClipFrag = NULL;
  1282. if ( pFront )
  1283. {
  1284. aDispFragments.AddToTail( pFront );
  1285. }
  1286. if ( pBack )
  1287. {
  1288. aDispFragments.AddToTail( pBack );
  1289. }
  1290. }
  1291. }
  1292. }
  1293. }
  1294. //-----------------------------------------------------------------------------
  1295. // Purpose:
  1296. //-----------------------------------------------------------------------------
  1297. void COverlayMgr::InitTexCoords( moverlay_t *pOverlay, moverlayfragment_t &overlayFrag )
  1298. {
  1299. // Overlay texture coordinates.
  1300. overlayFrag.m_aPrimVerts[0].texCoord[0].Init( pOverlay->m_flU[0], pOverlay->m_flV[0] );
  1301. overlayFrag.m_aPrimVerts[1].texCoord[0].Init( pOverlay->m_flU[0], pOverlay->m_flV[1] );
  1302. overlayFrag.m_aPrimVerts[2].texCoord[0].Init( pOverlay->m_flU[1], pOverlay->m_flV[1] );
  1303. overlayFrag.m_aPrimVerts[3].texCoord[0].Init( pOverlay->m_flU[1], pOverlay->m_flV[0] );
  1304. overlayFrag.m_aPrimVerts[0].texCoord[1].Init( 0, 0 );
  1305. overlayFrag.m_aPrimVerts[1].texCoord[1].Init( 0, 1 );
  1306. overlayFrag.m_aPrimVerts[2].texCoord[1].Init( 1, 1 );
  1307. overlayFrag.m_aPrimVerts[3].texCoord[1].Init( 1, 0 );
  1308. }
  1309. //-----------------------------------------------------------------------------
  1310. //-----------------------------------------------------------------------------
  1311. void COverlayMgr::DoClipFragment( moverlayfragment_t *pFragment, cplane_t *pClipPlane,
  1312. moverlayfragment_t **ppFront, moverlayfragment_t **ppBack )
  1313. {
  1314. const float OVERLAY_EPSILON = 0.0001f;
  1315. // Verify.
  1316. if ( !pFragment )
  1317. return;
  1318. float flDists[128] = {};
  1319. int nSides[128] = {};
  1320. int nSideCounts[3] = {};
  1321. //
  1322. // Determine "sidedness" of all the polygon points.
  1323. //
  1324. nSideCounts[0] = nSideCounts[1] = nSideCounts[2] = 0;
  1325. int iVert = 0;
  1326. for ( ; iVert < pFragment->m_aPrimVerts.Count(); ++iVert )
  1327. {
  1328. flDists[iVert] = pClipPlane->normal.Dot( pFragment->m_aPrimVerts[iVert].pos ) - pClipPlane->dist;
  1329. if ( flDists[iVert] > OVERLAY_EPSILON )
  1330. {
  1331. nSides[iVert] = SIDE_FRONT;
  1332. }
  1333. else if ( flDists[iVert] < -OVERLAY_EPSILON )
  1334. {
  1335. nSides[iVert] = SIDE_BACK;
  1336. }
  1337. else
  1338. {
  1339. nSides[iVert] = SIDE_ON;
  1340. }
  1341. nSideCounts[nSides[iVert]]++;
  1342. }
  1343. // Wrap around (close the polygon).
  1344. nSides[iVert] = nSides[0];
  1345. flDists[iVert] = flDists[0];
  1346. // All points in back - no split (copy face to back).
  1347. if( !nSideCounts[SIDE_FRONT] )
  1348. {
  1349. *ppBack = CopyTempFragment( pFragment );
  1350. return;
  1351. }
  1352. // All points in front - no split (copy face to front).
  1353. if( !nSideCounts[SIDE_BACK] )
  1354. {
  1355. *ppFront = CopyTempFragment( pFragment );
  1356. return;
  1357. }
  1358. // Build new front and back faces.
  1359. // NOTE: Gotta create them first
  1360. moverlayfragment_t *pFront = CreateTempFragment( 0 );
  1361. moverlayfragment_t *pBack = CreateTempFragment( 0 );
  1362. if ( !pFront || !pBack )
  1363. {
  1364. DestroyTempFragment( pFront );
  1365. DestroyTempFragment( pBack );
  1366. return;
  1367. }
  1368. MEM_ALLOC_CREDIT();
  1369. int nVertCount = pFragment->m_aPrimVerts.Count();
  1370. for ( iVert = 0; iVert < nVertCount; ++iVert )
  1371. {
  1372. // "On" clip plane.
  1373. if ( nSides[iVert] == SIDE_ON )
  1374. {
  1375. pFront->m_aPrimVerts.AddToTail( pFragment->m_aPrimVerts[iVert] );
  1376. pBack->m_aPrimVerts.AddToTail( pFragment->m_aPrimVerts[iVert] );
  1377. continue;
  1378. }
  1379. // "In back" of clip plane.
  1380. if ( nSides[iVert] == SIDE_BACK )
  1381. {
  1382. pBack->m_aPrimVerts.AddToTail( pFragment->m_aPrimVerts[iVert] );
  1383. }
  1384. // "In front" of clip plane.
  1385. if ( nSides[iVert] == SIDE_FRONT )
  1386. {
  1387. pFront->m_aPrimVerts.AddToTail( pFragment->m_aPrimVerts[iVert] );
  1388. }
  1389. if ( nSides[iVert+1] == SIDE_ON || nSides[iVert+1] == nSides[iVert] )
  1390. continue;
  1391. // Split!
  1392. float fraction = flDists[iVert] / ( flDists[iVert] - flDists[iVert+1] );
  1393. overlayvert_t vert;
  1394. vert.pos = pFragment->m_aPrimVerts[iVert].pos + fraction * ( pFragment->m_aPrimVerts[(iVert+1)%nVertCount].pos -
  1395. pFragment->m_aPrimVerts[iVert].pos );
  1396. for ( int iTexCoord=0; iTexCoord < NUM_OVERLAY_TEXCOORDS; iTexCoord++ )
  1397. {
  1398. vert.texCoord[iTexCoord][0] = pFragment->m_aPrimVerts[iVert].texCoord[iTexCoord][0] + fraction * ( pFragment->m_aPrimVerts[(iVert+1)%nVertCount].texCoord[iTexCoord][0] -
  1399. pFragment->m_aPrimVerts[iVert].texCoord[iTexCoord][0] );
  1400. vert.texCoord[iTexCoord][1] = pFragment->m_aPrimVerts[iVert].texCoord[iTexCoord][1] + fraction * ( pFragment->m_aPrimVerts[(iVert+1)%nVertCount].texCoord[iTexCoord][1] -
  1401. pFragment->m_aPrimVerts[iVert].texCoord[iTexCoord][1] );
  1402. }
  1403. pFront->m_aPrimVerts.AddToTail( vert );
  1404. pBack->m_aPrimVerts.AddToTail( vert );
  1405. }
  1406. *ppFront = pFront;
  1407. *ppBack = pBack;
  1408. }
  1409. //-----------------------------------------------------------------------------
  1410. // Copies a fragment into the main fragment list
  1411. //-----------------------------------------------------------------------------
  1412. OverlayFragmentHandle_t COverlayMgr::AddFragmentToFragmentList( int nSize )
  1413. {
  1414. MEM_ALLOC_CREDIT();
  1415. // Add to list of fragments.
  1416. int iFragment = m_aFragments.Alloc( true );
  1417. moverlayfragment_t &frag = m_aFragments[iFragment];
  1418. frag.m_SurfId = SURFACE_HANDLE_INVALID;
  1419. frag.m_iOverlay = -1;
  1420. frag.m_nRenderFrameID = -1;
  1421. frag.m_nMaterialSortID = 0xFFFF;
  1422. frag.m_hNextRender = OVERLAY_FRAGMENT_INVALID;
  1423. if ( nSize > 0 )
  1424. {
  1425. frag.m_aPrimVerts.SetSize( nSize );
  1426. }
  1427. return iFragment;
  1428. }
  1429. //-----------------------------------------------------------------------------
  1430. // Copies a fragment into the main fragment list
  1431. //-----------------------------------------------------------------------------
  1432. OverlayFragmentHandle_t COverlayMgr::AddFragmentToFragmentList( moverlayfragment_t *pSrc )
  1433. {
  1434. MEM_ALLOC_CREDIT();
  1435. // Add to list of fragments.
  1436. int iFragment = m_aFragments.Alloc( true );
  1437. moverlayfragment_t &frag = m_aFragments[iFragment];
  1438. frag.m_SurfId = pSrc->m_SurfId;
  1439. frag.m_iOverlay = pSrc->m_iOverlay;
  1440. frag.m_aPrimVerts.CopyArray( pSrc->m_aPrimVerts.Base(), pSrc->m_aPrimVerts.Count() );
  1441. return iFragment;
  1442. }
  1443. //-----------------------------------------------------------------------------
  1444. // Temp fragments for clipping algorithms
  1445. //-----------------------------------------------------------------------------
  1446. moverlayfragment_t *COverlayMgr::CreateTempFragment( int nSize )
  1447. {
  1448. MEM_ALLOC_CREDIT();
  1449. moverlayfragment_t *pDst = new moverlayfragment_t;
  1450. if ( pDst )
  1451. {
  1452. pDst->m_SurfId = SURFACE_HANDLE_INVALID;
  1453. pDst->m_iOverlay = -1;
  1454. if ( nSize > 0 )
  1455. {
  1456. pDst->m_aPrimVerts.SetSize( nSize );
  1457. }
  1458. }
  1459. return pDst;
  1460. }
  1461. //-----------------------------------------------------------------------------
  1462. // Temp fragments for clipping algorithms
  1463. //-----------------------------------------------------------------------------
  1464. moverlayfragment_t *COverlayMgr::CopyTempFragment( moverlayfragment_t *pSrc )
  1465. {
  1466. MEM_ALLOC_CREDIT();
  1467. moverlayfragment_t *pDst = new moverlayfragment_t;
  1468. if ( pDst )
  1469. {
  1470. pDst->m_SurfId = pSrc->m_SurfId;
  1471. pDst->m_iOverlay = pSrc->m_iOverlay;
  1472. pDst->m_aPrimVerts.CopyArray( pSrc->m_aPrimVerts.Base(), pSrc->m_aPrimVerts.Count() );
  1473. }
  1474. return pDst;
  1475. }
  1476. //-----------------------------------------------------------------------------
  1477. // Temp fragments for clipping algorithms
  1478. //-----------------------------------------------------------------------------
  1479. void COverlayMgr::DestroyTempFragment( moverlayfragment_t *pFragment )
  1480. {
  1481. if ( pFragment )
  1482. {
  1483. delete pFragment;
  1484. }
  1485. }
  1486. //-----------------------------------------------------------------------------
  1487. //-----------------------------------------------------------------------------
  1488. void COverlayMgr::BuildClipPlanes( SurfaceHandle_t surfID, moverlayfragment_t &surfaceFrag,
  1489. const Vector &vecBasisNormal,
  1490. CUtlVector<cplane_t> &m_ClipPlanes )
  1491. {
  1492. int nVertCount = surfaceFrag.m_aPrimVerts.Count();
  1493. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  1494. {
  1495. Vector vecEdge;
  1496. vecEdge = surfaceFrag.m_aPrimVerts[(iVert+1)%nVertCount].pos - surfaceFrag.m_aPrimVerts[iVert].pos;
  1497. VectorNormalize( vecEdge );
  1498. int iPlane = m_ClipPlanes.AddToTail();
  1499. cplane_t *pPlane = &m_ClipPlanes[iPlane];
  1500. pPlane->normal = vecBasisNormal.Cross( vecEdge );
  1501. pPlane->dist = pPlane->normal.Dot( surfaceFrag.m_aPrimVerts[iVert].pos );
  1502. pPlane->type = 3;
  1503. // Check normal facing.
  1504. float flDistance = pPlane->normal.Dot( surfaceFrag.m_aPrimVerts[(iVert+2)%nVertCount].pos ) - pPlane->dist;
  1505. if ( flDistance > 0.0 )
  1506. {
  1507. // Flip
  1508. pPlane->normal.Negate();
  1509. pPlane->dist = -pPlane->dist;
  1510. }
  1511. }
  1512. }
  1513. //=============================================================================
  1514. //
  1515. // Code below this line will get moved out into common code!!!!!!!!!!!!!
  1516. //
  1517. //-----------------------------------------------------------------------------
  1518. // Purpose:
  1519. //-----------------------------------------------------------------------------
  1520. void Overlay_BuildBasisOrigin( Vector &vecBasisOrigin, SurfaceHandle_t surfID )
  1521. {
  1522. cplane_t surfacePlane = MSurf_Plane( surfID );
  1523. VectorNormalize( surfacePlane.normal );
  1524. // Get the distance from entity origin to face plane.
  1525. float flDist = surfacePlane.normal.Dot( vecBasisOrigin ) - surfacePlane.dist;
  1526. // Move the basis origin to the position of the entity projected into the face plane.
  1527. vecBasisOrigin = vecBasisOrigin - ( flDist * surfacePlane.normal );
  1528. }
  1529. //-----------------------------------------------------------------------------
  1530. //-----------------------------------------------------------------------------
  1531. bool Overlay_IsBasisFlipped( int *pFlip, int iAxis, int iComponent )
  1532. {
  1533. if ( iAxis < 0 || iAxis > 2 || iComponent < 0 || iComponent > 2 )
  1534. return false;
  1535. int nValue = ( 1 << iComponent );
  1536. return ( ( pFlip[iAxis] & nValue ) != 0 );
  1537. }
  1538. //-----------------------------------------------------------------------------
  1539. // Purpose:
  1540. //-----------------------------------------------------------------------------
  1541. void Overlay_BuildBasis( const Vector &vecBasisNormal, Vector &vecBasisU, Vector &vecBasisV, bool bFlip )
  1542. {
  1543. // Verify incoming data.
  1544. Assert( vecBasisNormal.IsValid() );
  1545. if ( !vecBasisNormal.IsValid() )
  1546. return;
  1547. vecBasisV = vecBasisNormal.Cross( vecBasisU );
  1548. if ( bFlip )
  1549. {
  1550. vecBasisV.Negate();
  1551. }
  1552. }
  1553. //-----------------------------------------------------------------------------
  1554. // Purpose:
  1555. //-----------------------------------------------------------------------------
  1556. void Overlay_TriTLToBR(
  1557. CDispInfo *pDisp,
  1558. CMeshReader *pReader,
  1559. Vector &vecWorld,
  1560. float flU,
  1561. float flV,
  1562. int nWidth,
  1563. const Vector &vecIntersectPoint )
  1564. {
  1565. const float TRIEDGE_EPSILON = 0.000001f;
  1566. int nHeight = nWidth;
  1567. int nSnapU = static_cast<int>( flU );
  1568. int nSnapV = static_cast<int>( flV );
  1569. int nNextU = nSnapU + 1;
  1570. int nNextV = nSnapV + 1;
  1571. if ( nNextU == nWidth) { --nNextU; }
  1572. if ( nNextV == nHeight ) { --nNextV; }
  1573. float flFracU = flU - static_cast<float>( nSnapU );
  1574. float flFracV = flV - static_cast<float>( nSnapV );
  1575. Vector vecVerts[3], vecFlatVerts[3];
  1576. if( ( flFracU + flFracV ) >= ( 1.0f + TRIEDGE_EPSILON ) )
  1577. {
  1578. int nIndices[3];
  1579. nIndices[0] = nNextV * nWidth + nSnapU;
  1580. nIndices[1] = nNextV * nWidth + nNextU;
  1581. nIndices[2] = nSnapV * nWidth + nNextU;
  1582. for( int iVert = 0; iVert < 3; ++iVert )
  1583. {
  1584. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1585. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1586. }
  1587. if ( nSnapU == nNextU )
  1588. {
  1589. if ( nSnapV == nNextV )
  1590. {
  1591. vecWorld = vecVerts[0];
  1592. }
  1593. else
  1594. {
  1595. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1596. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1597. }
  1598. }
  1599. else if ( nSnapV == nNextV )
  1600. {
  1601. if ( nSnapU == nNextU )
  1602. {
  1603. vecWorld = vecVerts[0];
  1604. }
  1605. else
  1606. {
  1607. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1608. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1609. }
  1610. }
  1611. else
  1612. {
  1613. float flCfs[3];
  1614. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  1615. {
  1616. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1617. }
  1618. else
  1619. {
  1620. nIndices[0] = nSnapV * nWidth + nSnapU;
  1621. nIndices[1] = nNextV * nWidth + nSnapU;
  1622. nIndices[2] = nSnapV * nWidth + nNextU;
  1623. for( int iVert = 0; iVert < 3; ++iVert )
  1624. {
  1625. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1626. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1627. }
  1628. if ( nSnapU == nNextU )
  1629. {
  1630. if ( nSnapV == nNextV )
  1631. {
  1632. vecWorld = vecVerts[0];
  1633. }
  1634. else
  1635. {
  1636. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length();
  1637. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) );
  1638. }
  1639. }
  1640. else if ( nSnapV == nNextV )
  1641. {
  1642. if ( nSnapU == nNextU )
  1643. {
  1644. vecWorld = vecVerts[0];
  1645. }
  1646. else
  1647. {
  1648. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1649. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1650. }
  1651. }
  1652. else
  1653. {
  1654. CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] );
  1655. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1656. }
  1657. }
  1658. }
  1659. }
  1660. else
  1661. {
  1662. int nIndices[3];
  1663. nIndices[0] = nSnapV * nWidth + nSnapU;
  1664. nIndices[1] = nNextV * nWidth + nSnapU;
  1665. nIndices[2] = nSnapV * nWidth + nNextU;
  1666. for( int iVert = 0; iVert < 3; ++iVert )
  1667. {
  1668. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1669. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1670. }
  1671. if ( nSnapU == nNextU )
  1672. {
  1673. if ( nSnapV == nNextV )
  1674. {
  1675. vecWorld = vecVerts[0];
  1676. }
  1677. else
  1678. {
  1679. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length();
  1680. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) );
  1681. }
  1682. }
  1683. else if ( nSnapV == nNextV )
  1684. {
  1685. if ( nSnapU == nNextU )
  1686. {
  1687. vecWorld = vecVerts[0];
  1688. }
  1689. else
  1690. {
  1691. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1692. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1693. }
  1694. }
  1695. else
  1696. {
  1697. float flCfs[3];
  1698. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  1699. {
  1700. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1701. }
  1702. else
  1703. {
  1704. nIndices[0] = nNextV * nWidth + nSnapU;
  1705. nIndices[1] = nNextV * nWidth + nNextU;
  1706. nIndices[2] = nSnapV * nWidth + nNextU;
  1707. for( int iVert = 0; iVert < 3; ++iVert )
  1708. {
  1709. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1710. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1711. }
  1712. if ( nSnapU == nNextU )
  1713. {
  1714. if ( nSnapV == nNextV )
  1715. {
  1716. vecWorld = vecVerts[0];
  1717. }
  1718. else
  1719. {
  1720. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1721. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1722. }
  1723. }
  1724. else if ( nSnapV == nNextV )
  1725. {
  1726. if ( nSnapU == nNextU )
  1727. {
  1728. vecWorld = vecVerts[0];
  1729. }
  1730. else
  1731. {
  1732. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1733. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1734. }
  1735. }
  1736. else
  1737. {
  1738. CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] );
  1739. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1740. }
  1741. }
  1742. }
  1743. }
  1744. }
  1745. //-----------------------------------------------------------------------------
  1746. // Purpose:
  1747. //-----------------------------------------------------------------------------
  1748. void Overlay_TriBLToTR(
  1749. CDispInfo *pDisp,
  1750. CMeshReader *pReader,
  1751. Vector &vecWorld,
  1752. float flU,
  1753. float flV,
  1754. int nWidth,
  1755. const Vector &vecIntersectPoint )
  1756. {
  1757. int nHeight = nWidth;
  1758. int nSnapU = static_cast<int>( flU );
  1759. int nSnapV = static_cast<int>( flV );
  1760. int nNextU = nSnapU + 1;
  1761. int nNextV = nSnapV + 1;
  1762. if ( nNextU == nWidth) { --nNextU; }
  1763. if ( nNextV == nHeight ) { --nNextV; }
  1764. float flFracU = flU - static_cast<float>( nSnapU );
  1765. float flFracV = flV - static_cast<float>( nSnapV );
  1766. // The fractions are not correct all the time - but they are a good first guess!
  1767. Vector vecVerts[3], vecFlatVerts[3];
  1768. if( flFracU < flFracV )
  1769. {
  1770. int nIndices[3];
  1771. nIndices[0] = nSnapV * nWidth + nSnapU;
  1772. nIndices[1] = nNextV * nWidth + nSnapU;
  1773. nIndices[2] = nNextV * nWidth + nNextU;
  1774. for( int iVert = 0; iVert < 3; ++iVert )
  1775. {
  1776. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1777. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1778. }
  1779. if ( nSnapU == nNextU )
  1780. {
  1781. if ( nSnapV == nNextV )
  1782. {
  1783. vecWorld = vecVerts[0];
  1784. }
  1785. else
  1786. {
  1787. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1788. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1789. }
  1790. }
  1791. else if ( nSnapV == nNextV )
  1792. {
  1793. if ( nSnapU == nNextU )
  1794. {
  1795. vecWorld = vecVerts[0];
  1796. }
  1797. else
  1798. {
  1799. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1800. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1801. }
  1802. }
  1803. else
  1804. {
  1805. float flCfs[3];
  1806. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  1807. {
  1808. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1809. }
  1810. else
  1811. {
  1812. nIndices[0] = nSnapV * nWidth + nSnapU;
  1813. nIndices[1] = nNextV * nWidth + nNextU;
  1814. nIndices[2] = nSnapV * nWidth + nNextU;
  1815. for( int iVert = 0; iVert < 3; ++iVert )
  1816. {
  1817. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1818. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1819. }
  1820. if ( nSnapU == nNextU )
  1821. {
  1822. if ( nSnapV == nNextV )
  1823. {
  1824. vecWorld = vecVerts[0];
  1825. }
  1826. else
  1827. {
  1828. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length();
  1829. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) );
  1830. }
  1831. }
  1832. else if ( nSnapV == nNextV )
  1833. {
  1834. if ( nSnapU == nNextU )
  1835. {
  1836. vecWorld = vecVerts[0];
  1837. }
  1838. else
  1839. {
  1840. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1841. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1842. }
  1843. }
  1844. else
  1845. {
  1846. CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] );
  1847. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1848. }
  1849. }
  1850. }
  1851. }
  1852. else
  1853. {
  1854. int nIndices[3];
  1855. nIndices[0] = nSnapV * nWidth + nSnapU;
  1856. nIndices[1] = nNextV * nWidth + nNextU;
  1857. nIndices[2] = nSnapV * nWidth + nNextU;
  1858. for( int iVert = 0; iVert < 3; ++iVert )
  1859. {
  1860. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1861. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1862. }
  1863. if ( nSnapU == nNextU )
  1864. {
  1865. if ( nSnapV == nNextV )
  1866. {
  1867. vecWorld = vecVerts[0];
  1868. }
  1869. else
  1870. {
  1871. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length();
  1872. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) );
  1873. }
  1874. }
  1875. else if ( nSnapV == nNextV )
  1876. {
  1877. if ( nSnapU == nNextU )
  1878. {
  1879. vecWorld = vecVerts[0];
  1880. }
  1881. else
  1882. {
  1883. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1884. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1885. }
  1886. }
  1887. else
  1888. {
  1889. float flCfs[3];
  1890. if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) )
  1891. {
  1892. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1893. }
  1894. else
  1895. {
  1896. nIndices[0] = nSnapV * nWidth + nSnapU;
  1897. nIndices[1] = nNextV * nWidth + nSnapU;
  1898. nIndices[2] = nNextV * nWidth + nNextU;
  1899. for( int iVert = 0; iVert < 3; ++iVert )
  1900. {
  1901. vecVerts[iVert] = GetOverlayPos( pReader, nIndices[iVert] );
  1902. vecFlatVerts[iVert] = pDisp->GetFlatVert( nIndices[iVert] );
  1903. }
  1904. if ( nSnapU == nNextU )
  1905. {
  1906. if ( nSnapV == nNextV )
  1907. {
  1908. vecWorld = vecVerts[0];
  1909. }
  1910. else
  1911. {
  1912. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1913. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1914. }
  1915. }
  1916. else if ( nSnapV == nNextV )
  1917. {
  1918. if ( nSnapU == nNextU )
  1919. {
  1920. vecWorld = vecVerts[0];
  1921. }
  1922. else
  1923. {
  1924. float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length();
  1925. vecWorld = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) );
  1926. }
  1927. }
  1928. else
  1929. {
  1930. CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] );
  1931. vecWorld = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] );
  1932. }
  1933. }
  1934. }
  1935. }
  1936. }
  1937. //-----------------------------------------------------------------------------
  1938. // Purpose:
  1939. //-----------------------------------------------------------------------------
  1940. void Overlay_DispUVToWorld( CDispInfo *pDisp, CMeshReader *pReader, const Vector2D &vecUV, Vector &vecWorld, moverlayfragment_t &surfaceFrag )
  1941. {
  1942. // Get the displacement power.
  1943. const CPowerInfo *pPowerInfo = pDisp->GetPowerInfo();
  1944. int nWidth = ( ( 1 << pPowerInfo->GetPower() ) + 1 );
  1945. int nHeight = nWidth;
  1946. Vector vecIntersectPoint;
  1947. PointInQuadFromBarycentric( surfaceFrag.m_aPrimVerts[(0+pDisp->m_iPointStart)%4].pos,
  1948. surfaceFrag.m_aPrimVerts[(3+pDisp->m_iPointStart)%4].pos,
  1949. surfaceFrag.m_aPrimVerts[(2+pDisp->m_iPointStart)%4].pos,
  1950. surfaceFrag.m_aPrimVerts[(1+pDisp->m_iPointStart)%4].pos,
  1951. vecUV, vecIntersectPoint );
  1952. // Scale the U, V coordinates to the displacement grid size.
  1953. float flU = vecUV.x * static_cast<float>( nWidth - 1.000001f );
  1954. float flV = vecUV.y * static_cast<float>( nHeight - 1.000001f );
  1955. // Find the base U, V.
  1956. int nSnapU = static_cast<int>( flU );
  1957. int nSnapV = static_cast<int>( flV );
  1958. // Use this to get the triangle orientation.
  1959. bool bOdd = ( ( ( nSnapV * nWidth ) + nSnapU ) % 2 == 1 );
  1960. // Top Left to Bottom Right
  1961. if( bOdd )
  1962. {
  1963. Overlay_TriTLToBR( pDisp, pReader, vecWorld, flU, flV, nWidth, vecIntersectPoint );
  1964. }
  1965. // Bottom Left to Top Right
  1966. else
  1967. {
  1968. Overlay_TriBLToTR( pDisp, pReader, vecWorld, flU, flV, nWidth, vecIntersectPoint );
  1969. }
  1970. }
  1971. //-----------------------------------------------------------------------------
  1972. //-----------------------------------------------------------------------------
  1973. void Overlay_OverlayUVToOverlayPlane( const Vector &vecBasisOrigin, const Vector &vecBasisU,
  1974. const Vector &vecBasisV, const Vector &vecUVPoint,
  1975. Vector &vecPlanePoint )
  1976. {
  1977. vecPlanePoint = ( vecUVPoint.x * vecBasisU ) + ( vecUVPoint.y * vecBasisV );
  1978. vecPlanePoint += vecBasisOrigin;
  1979. }
  1980. //-----------------------------------------------------------------------------
  1981. //-----------------------------------------------------------------------------
  1982. void Overlay_WorldToOverlayPlane( const Vector &vecBasisOrigin, const Vector &vecBasisNormal,
  1983. const Vector &vecWorldPoint, Vector &vecPlanePoint )
  1984. {
  1985. Vector vecDelta = vecWorldPoint - vecBasisOrigin;
  1986. float flDistance = vecBasisNormal.Dot( vecDelta );
  1987. vecPlanePoint = vecWorldPoint - ( flDistance * vecBasisNormal );
  1988. }
  1989. //-----------------------------------------------------------------------------
  1990. //-----------------------------------------------------------------------------
  1991. void Overlay_OverlayPlaneToWorld( const Vector &vecBasisNormal, SurfaceHandle_t surfID,
  1992. const Vector &vecPlanePoint, Vector &vecWorldPoint )
  1993. {
  1994. cplane_t surfacePlane = MSurf_Plane( surfID );
  1995. VectorNormalize( surfacePlane.normal );
  1996. float flDistanceToSurface = surfacePlane.normal.Dot( vecPlanePoint ) - surfacePlane.dist;
  1997. float flDenom = surfacePlane.normal.Dot( vecBasisNormal );
  1998. float flDistance;
  1999. if( flDenom != 0.0f )
  2000. {
  2001. flDistance = ( 1.0f / flDenom ) * flDistanceToSurface;
  2002. }
  2003. else
  2004. {
  2005. flDistance = flDistanceToSurface;
  2006. }
  2007. vecWorldPoint = vecPlanePoint - ( vecBasisNormal * flDistance );
  2008. }