Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

688 lines
20 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #include "disp_vbsp.h"
  10. #include "tier0/dbg.h"
  11. #include "vbsp.h"
  12. #include "mstristrip.h"
  13. #include "writebsp.h"
  14. #include "pacifier.h"
  15. #include "disp_ivp.h"
  16. #include "builddisp.h"
  17. #include "mathlib/vector.h"
  18. // map displacement info -- runs parallel to the dispinfos struct
  19. int nummapdispinfo = 0;
  20. CUtlBlockVector<mapdispinfo_t> mapdispinfo;
  21. CUtlVector<CCoreDispInfo*> g_CoreDispInfos;
  22. //-----------------------------------------------------------------------------
  23. // Computes the bounds for a disp info
  24. //-----------------------------------------------------------------------------
  25. void ComputeDispInfoBounds( int dispinfo, Vector& mins, Vector& maxs )
  26. {
  27. CDispBox box;
  28. // Get a CCoreDispInfo. All we need is the triangles and lightmap texture coordinates.
  29. mapdispinfo_t *pMapDisp = &mapdispinfo[dispinfo];
  30. CCoreDispInfo coreDispInfo;
  31. DispMapToCoreDispInfo( pMapDisp, &coreDispInfo, NULL, NULL );
  32. GetDispBox( &coreDispInfo, box );
  33. mins = box.m_Min;
  34. maxs = box.m_Max;
  35. }
  36. // Gets the barycentric coordinates of the position on the triangle where the lightmap
  37. // coordinates are equal to lmCoords. This always generates the coordinates but it
  38. // returns false if the point containing them does not lie inside the triangle.
  39. bool GetBarycentricCoordsFromLightmapCoords( Vector2D tri[3], Vector2D const &lmCoords, float bcCoords[3] )
  40. {
  41. GetBarycentricCoords2D( tri[0], tri[1], tri[2], lmCoords, bcCoords );
  42. return
  43. (bcCoords[0] >= 0.0f && bcCoords[0] <= 1.0f) &&
  44. (bcCoords[1] >= 0.0f && bcCoords[1] <= 1.0f) &&
  45. (bcCoords[2] >= 0.0f && bcCoords[2] <= 1.0f);
  46. }
  47. bool FindTriIndexMapByUV( CCoreDispInfo *pCoreDisp, Vector2D const &lmCoords,
  48. int &iTriangle, float flBarycentric[3] )
  49. {
  50. const CPowerInfo *pPowerInfo = GetPowerInfo( pCoreDisp->GetPower() );
  51. // Search all the triangles..
  52. int nTriCount= pCoreDisp->GetTriCount();
  53. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  54. {
  55. unsigned short iVerts[3];
  56. // pCoreDisp->GetTriIndices( iTri, iVerts[0], iVerts[1], iVerts[2] );
  57. CTriInfo *pTri = &pPowerInfo->m_pTriInfos[iTri];
  58. iVerts[0] = pTri->m_Indices[0];
  59. iVerts[1] = pTri->m_Indices[1];
  60. iVerts[2] = pTri->m_Indices[2];
  61. // Get this triangle's UVs.
  62. Vector2D vecUV[3];
  63. for ( int iCoord = 0; iCoord < 3; ++iCoord )
  64. {
  65. pCoreDisp->GetLuxelCoord( 0, iVerts[iCoord], vecUV[iCoord] );
  66. }
  67. // See if the passed-in UVs are in this triangle's UVs.
  68. if( GetBarycentricCoordsFromLightmapCoords( vecUV, lmCoords, flBarycentric ) )
  69. {
  70. iTriangle = iTri;
  71. return true;
  72. }
  73. }
  74. return false;
  75. }
  76. void CalculateLightmapSamplePositions( CCoreDispInfo *pCoreDispInfo, const dface_t *pFace, CUtlVector<unsigned char> &out )
  77. {
  78. int width = pFace->m_LightmapTextureSizeInLuxels[0] + 1;
  79. int height = pFace->m_LightmapTextureSizeInLuxels[1] + 1;
  80. // For each lightmap sample, find the triangle it sits in.
  81. Vector2D lmCoords;
  82. for( int y=0; y < height; y++ )
  83. {
  84. lmCoords.y = y + 0.5f;
  85. for( int x=0; x < width; x++ )
  86. {
  87. lmCoords.x = x + 0.5f;
  88. float flBarycentric[3];
  89. int iTri;
  90. if( FindTriIndexMapByUV( pCoreDispInfo, lmCoords, iTri, flBarycentric ) )
  91. {
  92. if( iTri < 255 )
  93. {
  94. out.AddToTail( iTri );
  95. }
  96. else
  97. {
  98. out.AddToTail( 255 );
  99. out.AddToTail( iTri - 255 );
  100. }
  101. out.AddToTail( (unsigned char)( flBarycentric[0] * 255.9f ) );
  102. out.AddToTail( (unsigned char)( flBarycentric[1] * 255.9f ) );
  103. out.AddToTail( (unsigned char)( flBarycentric[2] * 255.9f ) );
  104. }
  105. else
  106. {
  107. out.AddToTail( 0 );
  108. out.AddToTail( 0 );
  109. out.AddToTail( 0 );
  110. out.AddToTail( 0 );
  111. }
  112. }
  113. }
  114. }
  115. //-----------------------------------------------------------------------------
  116. //-----------------------------------------------------------------------------
  117. int GetDispInfoEntityNum( mapdispinfo_t *pDisp )
  118. {
  119. return pDisp->entitynum;
  120. }
  121. // Setup a CCoreDispInfo given a mapdispinfo_t.
  122. // If pFace is non-NULL, then lightmap texture coordinates will be generated.
  123. void DispMapToCoreDispInfo( mapdispinfo_t *pMapDisp, CCoreDispInfo *pCoreDispInfo, dface_t *pFace, int *pSwappedTexInfos )
  124. {
  125. winding_t *pWinding = pMapDisp->face.originalface->winding;
  126. Assert( pWinding->numpoints == 4 );
  127. //
  128. // set initial surface data
  129. //
  130. CCoreDispSurface *pSurf = pCoreDispInfo->GetSurface();
  131. texinfo_t *pTexInfo = &texinfo[ pMapDisp->face.texinfo ];
  132. Assert( pTexInfo != NULL );
  133. // init material contents
  134. pMapDisp->contents = pMapDisp->face.contents;
  135. if (!(pMapDisp->contents & (ALL_VISIBLE_CONTENTS | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) )
  136. {
  137. pMapDisp->contents |= CONTENTS_SOLID;
  138. }
  139. pSurf->SetContents( pMapDisp->contents );
  140. // Calculate the lightmap coordinates.
  141. Vector2D tCoords[4] = {Vector2D(0,0),Vector2D(0,1),Vector2D(1,0),Vector2D(1,1)};
  142. if( pFace )
  143. {
  144. Assert( pFace->numedges == 4 );
  145. Vector pt[4];
  146. for( int i=0; i < 4; i++ )
  147. pt[i] = pWinding->p[i];
  148. int zeroOffset[2] = {0,0};
  149. CalcTextureCoordsAtPoints(
  150. pTexInfo->textureVecsTexelsPerWorldUnits,
  151. zeroOffset,
  152. pt,
  153. 4,
  154. tCoords );
  155. }
  156. //
  157. // set face point data ...
  158. //
  159. pSurf->SetPointCount( 4 );
  160. for( int i = 0; i < 4; i++ )
  161. {
  162. // position
  163. pSurf->SetPoint( i, pWinding->p[i] );
  164. pSurf->SetTexCoord( i, tCoords[i] );
  165. }
  166. // reset surface given start info
  167. pSurf->SetPointStart( pMapDisp->startPosition );
  168. pSurf->FindSurfPointStartIndex();
  169. pSurf->AdjustSurfPointData();
  170. // Set the luxel coordinates on the base displacement surface.
  171. Vector vecTmp( pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][0],
  172. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][1],
  173. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][2] );
  174. int nLuxelsPerWorldUnit = static_cast<int>( 1.0f / VectorLength( vecTmp ) );
  175. Vector vecU( pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][0],
  176. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][1],
  177. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][2] );
  178. Vector vecV( pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][0],
  179. pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][1],
  180. pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][2] );
  181. bool bSwap = pSurf->CalcLuxelCoords( nLuxelsPerWorldUnit, false, vecU, vecV );
  182. // Set the face m_LightmapExtents
  183. if ( pFace )
  184. {
  185. pFace->m_LightmapTextureSizeInLuxels[0] = pSurf->GetLuxelU();
  186. pFace->m_LightmapTextureSizeInLuxels[1] = pSurf->GetLuxelV();
  187. if ( bSwap )
  188. {
  189. if ( pSwappedTexInfos[ pMapDisp->face.texinfo ] < 0 )
  190. {
  191. // Create a new texinfo to hold the swapped data.
  192. // We must do this because other surfaces may want the non-swapped data
  193. // This fixes a lighting bug in d2_prison_08 where many non-displacement surfaces
  194. // were pitch black, in addition to bugs in other maps I bet.
  195. // NOTE: Copy here because adding a texinfo could realloc.
  196. texinfo_t temp = *pTexInfo;
  197. memcpy( temp.lightmapVecsLuxelsPerWorldUnits[0], pTexInfo->lightmapVecsLuxelsPerWorldUnits[1], 4 * sizeof(float) );
  198. memcpy( temp.lightmapVecsLuxelsPerWorldUnits[1], pTexInfo->lightmapVecsLuxelsPerWorldUnits[0], 4 * sizeof(float) );
  199. temp.lightmapVecsLuxelsPerWorldUnits[1][0] *= -1.0f;
  200. temp.lightmapVecsLuxelsPerWorldUnits[1][1] *= -1.0f;
  201. temp.lightmapVecsLuxelsPerWorldUnits[1][2] *= -1.0f;
  202. temp.lightmapVecsLuxelsPerWorldUnits[1][3] *= -1.0f;
  203. pSwappedTexInfos[ pMapDisp->face.texinfo ] = texinfo.AddToTail( temp );
  204. }
  205. pMapDisp->face.texinfo = pSwappedTexInfos[ pMapDisp->face.texinfo ];
  206. }
  207. // NOTE: This is here to help future-proof code, since there are codepaths where
  208. // pTexInfo can be made invalid (texinfo.AddToTail above).
  209. pTexInfo = NULL;
  210. }
  211. // Setup the displacement vectors and offsets.
  212. int size = ( ( ( 1 << pMapDisp->power ) + 1 ) * ( ( 1 << pMapDisp->power ) + 1 ) );
  213. Vector vectorDisps[2048];
  214. float dispDists[2048];
  215. Assert( size < sizeof(vectorDisps)/sizeof(vectorDisps[0]) );
  216. for( int j = 0; j < size; j++ )
  217. {
  218. Vector v;
  219. float dist;
  220. VectorScale( pMapDisp->vectorDisps[j], pMapDisp->dispDists[j], v );
  221. VectorAdd( v, pMapDisp->vectorOffsets[j], v );
  222. dist = VectorLength( v );
  223. VectorNormalize( v );
  224. vectorDisps[j] = v;
  225. dispDists[j] = dist;
  226. }
  227. // Use CCoreDispInfo to setup the actual vertex positions.
  228. pCoreDispInfo->InitDispInfo( pMapDisp->power, pMapDisp->minTess, pMapDisp->smoothingAngle,
  229. pMapDisp->alphaValues, vectorDisps, dispDists, pMapDisp->flags, pMapDisp->m_vMultiBlends );
  230. pCoreDispInfo->Create();
  231. }
  232. //-----------------------------------------------------------------------------
  233. //-----------------------------------------------------------------------------
  234. void EmitInitialDispInfos( void )
  235. {
  236. int i;
  237. mapdispinfo_t *pMapDisp;
  238. ddispinfo_t *pDisp;
  239. Vector v;
  240. // Calculate the total number of verts.
  241. int nTotalVerts = 0;
  242. int nTotalTris = 0;
  243. int nTotalMultiBlend = 0;
  244. for ( i=0; i < nummapdispinfo; i++ )
  245. {
  246. nTotalVerts += NUM_DISP_POWER_VERTS( mapdispinfo[i].power );
  247. nTotalTris += NUM_DISP_POWER_TRIS( mapdispinfo[i].power );
  248. if ( ( mapdispinfo[ i ].flags & DISP_INFO_FLAG_HAS_MULTIBLEND ) != 0 )
  249. {
  250. nTotalMultiBlend += NUM_DISP_POWER_VERTS( mapdispinfo[i].power );
  251. }
  252. }
  253. // Clear the output arrays..
  254. g_dispinfo.Purge();
  255. g_dispinfo.SetSize( nummapdispinfo );
  256. g_DispVerts.SetSize( nTotalVerts );
  257. g_DispTris.SetSize( nTotalTris );
  258. g_DispMultiBlend.SetSize( nTotalMultiBlend );
  259. int iCurVert = 0;
  260. int iCurTri = 0;
  261. int iCurMultiBlend = 0;
  262. for( i = 0; i < nummapdispinfo; i++ )
  263. {
  264. pDisp = &g_dispinfo[i];
  265. pMapDisp = &mapdispinfo[i];
  266. CDispVert *pOutVerts = &g_DispVerts[iCurVert];
  267. CDispTri *pOutTris = &g_DispTris[iCurTri];
  268. // Setup the vert pointers.
  269. pDisp->m_iDispVertStart = iCurVert;
  270. pDisp->m_iDispTriStart = iCurTri;
  271. iCurVert += NUM_DISP_POWER_VERTS( pMapDisp->power );
  272. iCurTri += NUM_DISP_POWER_TRIS( pMapDisp->power );
  273. //
  274. // save power, minimum tesselation, and smoothing angle
  275. //
  276. pDisp->power = pMapDisp->power;
  277. // If the high bit is set - this is FLAGS!
  278. pDisp->minTess = pMapDisp->flags | DISP_INFO_FLAG_MAGIC;
  279. // pDisp->minTess = pMapDisp->minTess;
  280. pDisp->smoothingAngle = pMapDisp->smoothingAngle;
  281. pDisp->m_iMapFace = (unsigned short)-2;
  282. // get surface contents
  283. pDisp->contents = pMapDisp->face.contents;
  284. pDisp->startPosition = pMapDisp->startPosition;
  285. //
  286. // add up the vectorOffsets and displacements, save alphas (per vertex)
  287. //
  288. int size = ( ( ( 1 << pDisp->power ) + 1 ) * ( ( 1 << pDisp->power ) + 1 ) );
  289. for( int j = 0; j < size; j++ )
  290. {
  291. VectorScale( pMapDisp->vectorDisps[j], pMapDisp->dispDists[j], v );
  292. VectorAdd( v, pMapDisp->vectorOffsets[j], v );
  293. float dist = VectorLength( v );
  294. VectorNormalize( v );
  295. VectorCopy( v, pOutVerts[j].m_vVector );
  296. pOutVerts[j].m_flDist = dist;
  297. pOutVerts[j].m_flAlpha = pMapDisp->alphaValues[j];
  298. if ( ( pMapDisp->flags & DISP_INFO_FLAG_HAS_MULTIBLEND ) != 0 )
  299. {
  300. g_DispMultiBlend[ iCurMultiBlend ] = pMapDisp->m_vMultiBlends[ j ];
  301. iCurMultiBlend++;
  302. }
  303. }
  304. int nTriCount = ( (1 << (pDisp->power)) * (1 << (pDisp->power)) * 2 );
  305. for ( int iTri = 0; iTri< nTriCount; ++iTri )
  306. {
  307. pOutTris[iTri].m_uiTags = pMapDisp->triTags[iTri];
  308. }
  309. //===================================================================
  310. //===================================================================
  311. // save the index for face data reference
  312. pMapDisp->face.dispinfo = i;
  313. }
  314. }
  315. void ExportCoreDispNeighborData( const CCoreDispInfo *pIn, ddispinfo_t *pOut )
  316. {
  317. for ( int i=0; i < 4; i++ )
  318. {
  319. pOut->m_EdgeNeighbors[i] = *pIn->GetEdgeNeighbor( i );
  320. pOut->m_CornerNeighbors[i] = *pIn->GetCornerNeighbors( i );
  321. }
  322. }
  323. void ExportNeighborData( CCoreDispInfo **ppListBase, ddispinfo_t *pBSPDispInfos, int listSize )
  324. {
  325. FindNeighboringDispSurfs( ppListBase, listSize );
  326. // Export the neighbor data.
  327. for ( int i=0; i < nummapdispinfo; i++ )
  328. {
  329. ExportCoreDispNeighborData( g_CoreDispInfos[i], &pBSPDispInfos[i] );
  330. }
  331. }
  332. void ExportCoreDispAllowedVertList( const CCoreDispInfo *pIn, ddispinfo_t *pOut )
  333. {
  334. ErrorIfNot(
  335. pIn->GetAllowedVerts().GetNumDWords() == sizeof( pOut->m_AllowedVerts ) / 4,
  336. ("ExportCoreDispAllowedVertList: size mismatch")
  337. );
  338. for ( int i=0; i < pIn->GetAllowedVerts().GetNumDWords(); i++ )
  339. pOut->m_AllowedVerts[i] = pIn->GetAllowedVerts().GetDWord( i );
  340. }
  341. void ExportAllowedVertLists( CCoreDispInfo **ppListBase, ddispinfo_t *pBSPDispInfos, int listSize )
  342. {
  343. SetupAllowedVerts( ppListBase, listSize );
  344. for ( int i=0; i < listSize; i++ )
  345. {
  346. ExportCoreDispAllowedVertList( ppListBase[i], &pBSPDispInfos[i] );
  347. }
  348. }
  349. bool FindEnclosingTri(
  350. const Vector2D &vert,
  351. CUtlVector<Vector2D> &vertCoords,
  352. CUtlVector<unsigned short> &indices,
  353. int *pStartVert,
  354. float bcCoords[3] )
  355. {
  356. for ( int i=0; i < indices.Count(); i += 3 )
  357. {
  358. GetBarycentricCoords2D(
  359. vertCoords[indices[i+0]],
  360. vertCoords[indices[i+1]],
  361. vertCoords[indices[i+2]],
  362. vert,
  363. bcCoords );
  364. if ( bcCoords[0] >= 0 && bcCoords[0] <= 1 &&
  365. bcCoords[1] >= 0 && bcCoords[1] <= 1 &&
  366. bcCoords[2] >= 0 && bcCoords[2] <= 1 )
  367. {
  368. *pStartVert = i;
  369. return true;
  370. }
  371. }
  372. return false;
  373. }
  374. void SnapRemainingVertsToSurface( CCoreDispInfo *pCoreDisp, ddispinfo_t *pDispInfo )
  375. {
  376. // First, tesselate the displacement.
  377. CUtlVector<unsigned short> indices;
  378. CVBSPTesselateHelper helper;
  379. helper.m_pIndices = &indices;
  380. helper.m_pActiveVerts = pCoreDisp->GetAllowedVerts().Base();
  381. helper.m_pPowerInfo = pCoreDisp->GetPowerInfo();
  382. ::TesselateDisplacement( &helper );
  383. // Figure out which verts are actually referenced in the tesselation.
  384. CUtlVector<bool> vertsTouched;
  385. vertsTouched.SetSize( pCoreDisp->GetSize() );
  386. memset( vertsTouched.Base(), 0, sizeof( bool ) * vertsTouched.Count() );
  387. for ( int i=0; i < indices.Count(); i++ )
  388. vertsTouched[ indices[i] ] = true;
  389. // Generate 2D floating point coordinates for each vertex. We use these to generate
  390. // barycentric coordinates, and the scale doesn't matter.
  391. CUtlVector<Vector2D> vertCoords;
  392. vertCoords.SetSize( pCoreDisp->GetSize() );
  393. for ( int y=0; y < pCoreDisp->GetHeight(); y++ )
  394. {
  395. for ( int x=0; x < pCoreDisp->GetWidth(); x++ )
  396. vertCoords[y*pCoreDisp->GetWidth()+x].Init( x, y );
  397. }
  398. // Now, for each vert not touched, snap its position to the main surface.
  399. for ( int y=0; y < pCoreDisp->GetHeight(); y++ )
  400. {
  401. for ( int x=0; x < pCoreDisp->GetWidth(); x++ )
  402. {
  403. int index = y * pCoreDisp->GetWidth() + x;
  404. if ( !( vertsTouched[index] ) )
  405. {
  406. float bcCoords[3];
  407. int iStartVert = -1;
  408. if ( FindEnclosingTri( vertCoords[index], vertCoords, indices, &iStartVert, bcCoords ) )
  409. {
  410. const Vector &A = pCoreDisp->GetVert( indices[iStartVert+0] );
  411. const Vector &B = pCoreDisp->GetVert( indices[iStartVert+1] );
  412. const Vector &C = pCoreDisp->GetVert( indices[iStartVert+2] );
  413. Vector vNewPos = A*bcCoords[0] + B*bcCoords[1] + C*bcCoords[2];
  414. // This is kind of cheesy, but it gets the job done. Since the CDispVerts store the
  415. // verts relative to some other offset, we'll just offset their position instead
  416. // of setting it directly.
  417. Vector vOffset = vNewPos - pCoreDisp->GetVert( index );
  418. // Modify the mapfile vert.
  419. CDispVert *pVert = &g_DispVerts[pDispInfo->m_iDispVertStart + index];
  420. pVert->m_vVector = (pVert->m_vVector * pVert->m_flDist) + vOffset;
  421. pVert->m_flDist = 1;
  422. // Modify the CCoreDispInfo vert (although it probably won't be used later).
  423. pCoreDisp->SetVert( index, vNewPos );
  424. }
  425. else
  426. {
  427. // This shouldn't happen because it would mean that the triangulation that
  428. // disp_tesselation.h produced was missing a chunk of the space that the
  429. // displacement covers.
  430. // It also could indicate a floating-point epsilon error.. check to see if
  431. // FindEnclosingTri finds a triangle that -almost- encloses the vert.
  432. Assert( false );
  433. }
  434. }
  435. }
  436. }
  437. }
  438. void SnapRemainingVertsToSurface( CCoreDispInfo **ppListBase, ddispinfo_t *pBSPDispInfos, int listSize )
  439. {
  440. //g_pPad = ScratchPad3D_Create();
  441. for ( int i=0; i < listSize; i++ )
  442. {
  443. SnapRemainingVertsToSurface( ppListBase[i], &pBSPDispInfos[i] );
  444. }
  445. }
  446. void EmitDispLMAlphaAndNeighbors()
  447. {
  448. int i;
  449. Msg( "Finding displacement neighbors...\n" );
  450. // Build the CCoreDispInfos.
  451. CUtlVector<dface_t*> faces;
  452. // Create the core dispinfos and init them for use as CDispUtilsHelpers.
  453. for ( int iDisp = 0; iDisp < nummapdispinfo; ++iDisp )
  454. {
  455. CCoreDispInfo *pDisp = new CCoreDispInfo;
  456. if ( !pDisp )
  457. {
  458. g_CoreDispInfos.Purge();
  459. return;
  460. }
  461. int nIndex = g_CoreDispInfos.AddToTail();
  462. pDisp->SetListIndex( nIndex );
  463. g_CoreDispInfos[nIndex] = pDisp;
  464. }
  465. for ( i=0; i < nummapdispinfo; i++ )
  466. {
  467. g_CoreDispInfos[i]->SetDispUtilsHelperInfo( g_CoreDispInfos.Base(), nummapdispinfo );
  468. }
  469. faces.SetSize( nummapdispinfo );
  470. int nMemSize = texinfo.Count() * sizeof(int);
  471. int *pSwappedTexInfos = (int*)stackalloc( nMemSize );
  472. memset( pSwappedTexInfos, 0xFF, nMemSize );
  473. for( i = 0; i < numfaces; i++ )
  474. {
  475. dface_t *pFace = &dfaces[i];
  476. if( pFace->dispinfo == -1 )
  477. continue;
  478. mapdispinfo_t *pMapDisp = &mapdispinfo[pFace->dispinfo];
  479. // Set the displacement's face index.
  480. ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo];
  481. pDisp->m_iMapFace = i;
  482. // Get a CCoreDispInfo. All we need is the triangles and lightmap texture coordinates.
  483. CCoreDispInfo *pCoreDispInfo = g_CoreDispInfos[pFace->dispinfo];
  484. DispMapToCoreDispInfo( pMapDisp, pCoreDispInfo, pFace, pSwappedTexInfos );
  485. faces[pFace->dispinfo] = pFace;
  486. }
  487. stackfree( pSwappedTexInfos );
  488. // Generate and export neighbor data.
  489. ExportNeighborData( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo );
  490. // Generate and export the active vert lists.
  491. ExportAllowedVertLists( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo );
  492. // Now that we know which vertices are actually going to be around, snap the ones that won't
  493. // be around onto the slightly-reduced mesh. This is so the engine's ray test code and
  494. // overlay code works right.
  495. SnapRemainingVertsToSurface( g_CoreDispInfos.Base(), g_dispinfo.Base(), nummapdispinfo );
  496. Msg( "Finding lightmap sample positions...\n" );
  497. for ( i=0; i < nummapdispinfo; i++ )
  498. {
  499. dface_t *pFace = faces[i];
  500. ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo];
  501. CCoreDispInfo *pCoreDispInfo = g_CoreDispInfos[i];
  502. pDisp->m_iLightmapSamplePositionStart = g_DispLightmapSamplePositions.Count();
  503. CalculateLightmapSamplePositions( pCoreDispInfo, pFace, g_DispLightmapSamplePositions );
  504. }
  505. StartPacifier( "Displacement Alpha : ");
  506. // Build lightmap alphas.
  507. int dispCount = 0; // How many we've processed.
  508. for( i = 0; i < nummapdispinfo; i++ )
  509. {
  510. dface_t *pFace = faces[i];
  511. Assert( pFace->dispinfo == i );
  512. ddispinfo_t *pDisp = &g_dispinfo[pFace->dispinfo];
  513. // Allocate space for the alpha values.
  514. pDisp->m_iLightmapAlphaStart = 0; // not used anymore
  515. ++dispCount;
  516. }
  517. EndPacifier();
  518. }
  519. //-----------------------------------------------------------------------------
  520. //-----------------------------------------------------------------------------
  521. void DispGetFaceInfo( mapbrush_t *pBrush )
  522. {
  523. int i;
  524. side_t *pSide;
  525. // we don't support displacement on entities at the moment!!
  526. if( pBrush->entitynum != 0 )
  527. {
  528. char* pszEntityName = ValueForKey( &g_LoadingMap->entities[pBrush->entitynum], "classname" );
  529. Error( "Error: displacement found on a(n) %s entity - not supported (entity %d, brush %d)\n", pszEntityName, pBrush->entitynum, pBrush->brushnum );
  530. }
  531. for( i = 0; i < pBrush->numsides; i++ )
  532. {
  533. pSide = &pBrush->original_sides[i];
  534. if( pSide->pMapDisp )
  535. {
  536. // error checking!!
  537. if( pSide->winding->numpoints != 4 )
  538. Error( "Trying to create a non-quad displacement! (entity %d, brush %d)\n", pBrush->entitynum, pBrush->brushnum );
  539. pSide->pMapDisp->face.originalface = pSide;
  540. pSide->pMapDisp->face.texinfo = pSide->texinfo;
  541. pSide->pMapDisp->face.dispinfo = -1;
  542. pSide->pMapDisp->face.planenum = pSide->planenum;
  543. pSide->pMapDisp->face.numpoints = pSide->winding->numpoints;
  544. pSide->pMapDisp->face.w = CopyWinding( pSide->winding );
  545. pSide->pMapDisp->face.contents = pBrush->contents;
  546. pSide->pMapDisp->face.merged = FALSE;
  547. pSide->pMapDisp->face.split[0] = FALSE;
  548. pSide->pMapDisp->face.split[1] = FALSE;
  549. pSide->pMapDisp->entitynum = pBrush->entitynum;
  550. pSide->pMapDisp->brushSideID = pSide->id;
  551. }
  552. }
  553. }
  554. //-----------------------------------------------------------------------------
  555. //-----------------------------------------------------------------------------
  556. bool HasDispInfo( mapbrush_t *pBrush )
  557. {
  558. int i;
  559. side_t *pSide;
  560. for( i = 0; i < pBrush->numsides; i++ )
  561. {
  562. pSide = &pBrush->original_sides[i];
  563. if( pSide->pMapDisp )
  564. return true;
  565. }
  566. return false;
  567. }