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.

4365 lines
117 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdafx.h>
  8. #include "bitmap/tgaloader.h"
  9. #include "ChunkFile.h"
  10. #include "MapDefs.h"
  11. #include "MapDisp.h"
  12. #include "MapDoc.h"
  13. #include "MapFace.h"
  14. #include "MapSolid.h"
  15. #include "MapWorld.h"
  16. #include "MainFrm.h"
  17. #include "GlobalFunctions.h"
  18. #include "SaveInfo.h"
  19. #include "TextureSystem.h"
  20. #include "materialsystem/imesh.h"
  21. #include "Material.h"
  22. #include "CollisionUtils.h"
  23. #include "CModel.h"
  24. #include "History.h"
  25. #include "ToolDisplace.h"
  26. #include "ToolManager.h"
  27. #include "mathlib/mathlib.h"
  28. #include "dispshore.h"
  29. #include "Color.h"
  30. #include "render2d.h"
  31. #include "faceeditsheet.h"
  32. // memdbgon must be the last include file in a .cpp file!!!
  33. #include <tier0/memdbgon.h>
  34. #define OVERLAY_CHECK_BLOAT 16.0f
  35. bool CMapDisp::m_bSelectMask = false;
  36. bool CMapDisp::m_bGridMask = false;
  37. //-----------------------------------------------------------------------------
  38. // Purpose : CMapDisp constructor
  39. //-----------------------------------------------------------------------------
  40. CMapDisp::CMapDisp()
  41. {
  42. // clear neighbor data
  43. ResetNeighbors();
  44. //
  45. // initialize the hit indices
  46. //
  47. ResetTexelHitIndex();
  48. ResetDispMapHitIndex();
  49. m_bHasMappingAxes = false;
  50. VectorClear( m_MapAxes[0] );
  51. VectorClear( m_MapAxes[1] );
  52. m_Scale = 1.0f;
  53. m_bSubdiv = false;
  54. m_bReSubdiv = false;
  55. m_CoreDispInfo.InitDispInfo( 4, 0, 0, NULL, NULL, NULL );
  56. Paint_Init( DISPPAINT_CHANNEL_POSITION );
  57. m_CoreDispInfo.AllowedVerts_Clear();
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Purpose : CMapDisp deconstructor
  61. //-----------------------------------------------------------------------------
  62. CMapDisp::~CMapDisp()
  63. {
  64. m_aWalkableVerts.Purge();
  65. m_aWalkableIndices.Purge();
  66. m_aForcedWalkableIndices.Purge();
  67. m_aBuildableVerts.Purge();
  68. m_aBuildableIndices.Purge();
  69. m_aForcedBuildableIndices.Purge();
  70. m_aRemoveVerts.Purge();
  71. m_aRemoveIndices.Purge();
  72. }
  73. //-----------------------------------------------------------------------------
  74. //-----------------------------------------------------------------------------
  75. bool CMapDisp::InitDispSurfaceData( CMapFace *pFace, bool bGenerateStartPoint )
  76. {
  77. //
  78. // verify face is a "quad"
  79. //
  80. int pointCount = pFace->GetPointCount();
  81. if( pointCount != 4 )
  82. return false;
  83. // get the displacement surface
  84. CCoreDispSurface *pSurf = m_CoreDispInfo.GetSurface();
  85. //
  86. // set face point data - pos, normal, texture, etc....
  87. //
  88. Vector v3;
  89. Vector2D v2;
  90. pSurf->SetPointCount( 4 );
  91. for( int i = 0; i < 4; i++ )
  92. {
  93. // position
  94. pFace->GetPoint( v3, i );
  95. pSurf->SetPoint( i, v3 );
  96. // normal
  97. pFace->GetFaceNormal( v3 );
  98. pSurf->SetPointNormal( i, v3 );
  99. // texture coords
  100. pFace->GetTexCoord( v2, i );
  101. pSurf->SetTexCoord( i, v2 );
  102. }
  103. //
  104. // get displacement surface point start index
  105. //
  106. int pointStartIndex = pSurf->GetPointStartIndex();
  107. if( m_bHasMappingAxes && ( pointStartIndex == -1 ) )
  108. {
  109. pSurf->GeneratePointStartIndexFromMappingAxes( m_MapAxes[0], m_MapAxes[1] );
  110. }
  111. else
  112. {
  113. if( bGenerateStartPoint )
  114. {
  115. pSurf->GenerateSurfPointStartIndex();
  116. }
  117. else
  118. {
  119. pSurf->FindSurfPointStartIndex();
  120. }
  121. }
  122. pSurf->AdjustSurfPointData();
  123. // Luxel coords.
  124. int nLightmapScale = pFace->texture.nLightmapScale;
  125. pSurf->CalcLuxelCoords( nLightmapScale, false, pFace->texture.UAxis.AsVector3D(), pFace->texture.VAxis.AsVector3D() );
  126. // Set the lightmap coordinates.
  127. for ( int iLuxelCoord = 0; iLuxelCoord < 4; ++iLuxelCoord )
  128. {
  129. Vector2D vecCoord;
  130. pSurf->GetLuxelCoord( 0, iLuxelCoord, vecCoord );
  131. pFace->SetLightmapCoord( vecCoord, iLuxelCoord );
  132. }
  133. // reset the has mapping axes flag (surface has been created! - use new method now)
  134. m_bHasMappingAxes = false;
  135. // set the s and t texture mapping axes so that tangent spaces can be calculated
  136. pSurf->SetSAxis( pFace->texture.UAxis.AsVector3D() );
  137. pSurf->SetTAxis( pFace->texture.VAxis.AsVector3D() );
  138. // successful init
  139. return true;
  140. }
  141. //-----------------------------------------------------------------------------
  142. //-----------------------------------------------------------------------------
  143. void CMapDisp::ResetFieldData( void )
  144. {
  145. ResetFieldVectors();
  146. ResetFieldDistances();
  147. ResetSubdivPositions();
  148. ResetSubdivNormals();
  149. }
  150. //-----------------------------------------------------------------------------
  151. //-----------------------------------------------------------------------------
  152. void CMapDisp::InitData( int power )
  153. {
  154. // set surface "power" (defines size)
  155. SetPower( power );
  156. // clear vector field distances, subdiv positions and normals
  157. ResetFieldData();
  158. }
  159. //-----------------------------------------------------------------------------
  160. //-----------------------------------------------------------------------------
  161. bool CMapDisp::Create( void )
  162. {
  163. if ( m_CoreDispInfo.CreateWithoutLOD() )
  164. {
  165. PostCreate();
  166. return true;
  167. }
  168. return false;
  169. }
  170. //-----------------------------------------------------------------------------
  171. //-----------------------------------------------------------------------------
  172. void CMapDisp::PostCreate( void )
  173. {
  174. UpdateBoundingBox();
  175. UpdateNeighborDependencies( false );
  176. UpdateLightmapExtents();
  177. UpdateWalkable();
  178. UpdateBuildable();
  179. // Get the current face and create/update any detail objects
  180. CMapFace *pFace = static_cast<CMapFace*>( GetParent() );
  181. if ( pFace )
  182. DetailObjects::BuildAnyDetailObjects(pFace);
  183. }
  184. //-----------------------------------------------------------------------------
  185. //-----------------------------------------------------------------------------
  186. CMapDisp *CMapDisp::CopyFrom( CMapDisp *pMapDisp, bool bUpdateDependencies )
  187. {
  188. //
  189. // check for valid displacement to copy from
  190. //
  191. if( !pMapDisp )
  192. return NULL;
  193. //
  194. // copy the base surface data - positions, normals, texture coords, etc...
  195. //
  196. CCoreDispSurface *pFromSurf = pMapDisp->m_CoreDispInfo.GetSurface();
  197. CCoreDispSurface *pToSurf = m_CoreDispInfo.GetSurface();
  198. int pointCount = pFromSurf->GetPointCount();
  199. pToSurf->SetPointCount( pointCount );
  200. Vector2D v2;
  201. Vector v3;
  202. for( int i = 0; i < pointCount; i++ )
  203. {
  204. pFromSurf->GetPoint( i, v3 );
  205. pToSurf->SetPoint( i, v3 );
  206. pFromSurf->GetPointNormal( i, v3 );
  207. pToSurf->SetPointNormal( i, v3 );
  208. pFromSurf->GetTexCoord( i, v2 );
  209. pToSurf->SetTexCoord( i, v2 );
  210. pFromSurf->GetLuxelCoord( 0, i, v2 );
  211. pToSurf->SetLuxelCoord( 0, i, v2 );
  212. }
  213. pToSurf->SetFlags( pFromSurf->GetFlags() );
  214. pToSurf->SetContents( pFromSurf->GetContents() );
  215. pToSurf->SetPointStartIndex( pFromSurf->GetPointStartIndex() );
  216. //
  217. // copy displacement surface data
  218. //
  219. SetPower( pMapDisp->GetPower() );
  220. SetElevation( pMapDisp->GetElevation() );
  221. // save the scale -- don't want to rescale!!
  222. m_Scale = pMapDisp->GetScale();
  223. int size = GetSize();
  224. for( int i = 0; i < size; i++ )
  225. {
  226. pMapDisp->GetFieldVector( i, v3 );
  227. SetFieldVector( i, v3 );
  228. pMapDisp->GetSubdivPosition( i, v3 );
  229. SetSubdivPosition( i, v3 );
  230. pMapDisp->GetSubdivNormal( i, v3 );
  231. SetSubdivNormal( i, v3 );
  232. SetFieldDistance( i, pMapDisp->GetFieldDistance( i ) );
  233. pMapDisp->GetVert( i, v3 );
  234. SetVert( i, v3 );
  235. pMapDisp->GetFlatVert( i, v3 );
  236. SetFlatVert( i, v3 );
  237. SetAlpha( i, pMapDisp->GetAlpha( i ) );
  238. }
  239. int renderCount = pMapDisp->m_CoreDispInfo.GetRenderIndexCount();
  240. m_CoreDispInfo.SetRenderIndexCount( renderCount );
  241. for( int i = 0; i < renderCount; i++ )
  242. {
  243. m_CoreDispInfo.SetRenderIndex( i, pMapDisp->m_CoreDispInfo.GetRenderIndex( i ) );
  244. }
  245. // Copy the triangle data.
  246. int nTriCount = GetTriCount();
  247. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  248. {
  249. unsigned short triIndices[3];
  250. pMapDisp->GetTriIndices( iTri, triIndices[0], triIndices[1], triIndices[2] );
  251. m_CoreDispInfo.SetTriIndices( iTri, triIndices[0], triIndices[1], triIndices[2] );
  252. unsigned short triValue = pMapDisp->m_CoreDispInfo.GetTriTagValue( iTri );
  253. m_CoreDispInfo.SetTriTagValue( iTri, triValue );
  254. }
  255. //
  256. // copy editor specific data
  257. //
  258. m_bSubdiv = pMapDisp->IsSubdivided();
  259. m_bReSubdiv = pMapDisp->NeedsReSubdivision();
  260. ResetTexelHitIndex();
  261. ResetDispMapHitIndex();
  262. ResetTouched();
  263. m_CoreDispInfo.AllowedVerts_Clear();
  264. //
  265. // re-build the surface??? an undo, etc...
  266. //
  267. if( bUpdateDependencies )
  268. {
  269. UpdateData();
  270. CheckAndUpdateOverlays( true );
  271. }
  272. return this;
  273. }
  274. //-----------------------------------------------------------------------------
  275. //-----------------------------------------------------------------------------
  276. void CMapDisp::UpdateSurfData( CMapFace *pFace )
  277. {
  278. InitDispSurfaceData( pFace, false );
  279. Create();
  280. }
  281. //-----------------------------------------------------------------------------
  282. //-----------------------------------------------------------------------------
  283. void CMapDisp::UpdateSurfDataAndVectorField( CMapFace *pFace )
  284. {
  285. InitDispSurfaceData( pFace, false );
  286. // ResetFieldVectors();
  287. ResetSubdivPositions();
  288. ResetSubdivNormals();
  289. Create();
  290. }
  291. //-----------------------------------------------------------------------------
  292. //-----------------------------------------------------------------------------
  293. void CMapDisp::UpdateData( void )
  294. {
  295. Create();
  296. }
  297. //-----------------------------------------------------------------------------
  298. //-----------------------------------------------------------------------------
  299. void CMapDisp::UpdateDataAndNeighborData( void )
  300. {
  301. // update itself
  302. Create();
  303. // update neighbors
  304. for( int i = 0; i < 4; i++ )
  305. {
  306. EditDispHandle_t handle = GetEdgeNeighbor( i );
  307. if( handle != EDITDISPHANDLE_INVALID )
  308. {
  309. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  310. pNeighborDisp->UpdateData();
  311. }
  312. int cornerCount = GetCornerNeighborCount( i );
  313. if( cornerCount > 0 )
  314. {
  315. for( int j = 0; j < cornerCount; j++ )
  316. {
  317. handle = GetCornerNeighbor( i, j );
  318. if( handle != EDITDISPHANDLE_INVALID )
  319. {
  320. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  321. pNeighborDisp->UpdateData();
  322. }
  323. }
  324. }
  325. }
  326. }
  327. //-----------------------------------------------------------------------------
  328. //-----------------------------------------------------------------------------
  329. void CMapDisp::UpdateLightmapExtents( void )
  330. {
  331. // Get the parent face.
  332. CMapFace *pFace = ( CMapFace* )GetParent();
  333. if( !pFace )
  334. return;
  335. // Check for valid lightmap size and correct if need be.
  336. ValidLightmapSize();
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Purpose: Returns TRUE if the lightmap scale on this face is within the acceptable range.
  340. //-----------------------------------------------------------------------------
  341. bool CMapDisp::ValidLightmapSize( void )
  342. {
  343. // Get the current face and lightmap scale.
  344. CMapFace *pFace = static_cast<CMapFace*>( GetParent() );
  345. if ( !pFace )
  346. return false;
  347. int nLightmapScale = pFace->texture.nLightmapScale;
  348. // Get the surface points.
  349. Vector vecPoints[4];
  350. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  351. {
  352. GetSurfPoint( iPoint, vecPoints[iPoint] );
  353. }
  354. // Find the largest edge.
  355. float flMaxLength = 0.0f;
  356. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  357. {
  358. float flLength = ( vecPoints[(iPoint+1)%4] - vecPoints[iPoint] ).Length();
  359. if ( flLength > flMaxLength )
  360. {
  361. flMaxLength = flLength;
  362. }
  363. }
  364. float flOOLightmapScale = 1.0f / static_cast<float>( nLightmapScale );
  365. float flSize = static_cast<float>( static_cast<int>( flMaxLength * flOOLightmapScale ) + 1 );
  366. if ( flSize > MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER )
  367. {
  368. while ( flSize > MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER )
  369. {
  370. nLightmapScale++;
  371. flOOLightmapScale = 1.0f / static_cast<float>( nLightmapScale );
  372. flSize = static_cast<float>( static_cast<int>( flMaxLength * flOOLightmapScale ) + 1 );
  373. }
  374. // Save the next to last.
  375. pFace->texture.nLightmapScale = nLightmapScale;
  376. // Re-calculate texture coordinates now.
  377. pFace->CalcTextureCoords();
  378. CFaceEditSheet *pSheet = GetMainWnd()->GetFaceEditSheet();
  379. if( pSheet )
  380. {
  381. pSheet->m_MaterialPage.UpdateDialogData();
  382. }
  383. }
  384. return true;
  385. }
  386. //-----------------------------------------------------------------------------
  387. //-----------------------------------------------------------------------------
  388. bool CMapDisp::EntityInBoundingBox( Vector const &vOrigin )
  389. {
  390. Vector vMin, vMax;
  391. for( int axis = 0; axis < 3; axis++ )
  392. {
  393. vMin[axis] = m_BBox[0][axis] - OVERLAY_CHECK_BLOAT;
  394. vMax[axis] = m_BBox[1][axis] + OVERLAY_CHECK_BLOAT;
  395. }
  396. if( ( vOrigin.x < vMin.x ) || ( vOrigin.x > vMax.x ) ||
  397. ( vOrigin.y < vMin.y ) || ( vOrigin.y > vMax.y ) ||
  398. ( vOrigin.z < vMin.z ) || ( vOrigin.z > vMax.z ) )
  399. return false;
  400. return true;
  401. }
  402. //-----------------------------------------------------------------------------
  403. //-----------------------------------------------------------------------------
  404. void CMapDisp::CheckAndUpdateOverlays( bool bFull )
  405. {
  406. CMapFace *pFace = ( CMapFace* )GetParent();
  407. if ( pFace )
  408. {
  409. CMapSolid *pSolid = ( CMapSolid* )pFace->GetParent();
  410. if ( pSolid )
  411. {
  412. if ( !bFull )
  413. {
  414. pSolid->PostUpdate(Notify_Rebuild);
  415. }
  416. else
  417. {
  418. pSolid->PostUpdate(Notify_Rebuild_Full);
  419. }
  420. }
  421. }
  422. }
  423. //-----------------------------------------------------------------------------
  424. //-----------------------------------------------------------------------------
  425. void CMapDisp::UpSample( int oldPower )
  426. {
  427. //
  428. // allocate temporary memory to hold new displacement distances
  429. //
  430. int width = GetWidth();
  431. int height = GetHeight();
  432. float *dists = new float[height*width];
  433. float *alphas = new float[height*width];
  434. Vector *dispVectors = new Vector[height*width];
  435. Vector *subdivPositions = new Vector[height*width];
  436. Vector *subdivNormals = new Vector[height*width];
  437. if( !dists || !alphas || !dispVectors || !subdivPositions || !subdivNormals )
  438. {
  439. delete [] dists;
  440. delete [] alphas;
  441. delete [] dispVectors;
  442. delete [] subdivPositions;
  443. delete [] subdivNormals;
  444. return;
  445. }
  446. //
  447. // get old width and height
  448. //
  449. int oldWidth = ( ( 1 << oldPower ) + 1 );
  450. int oldHeight = ( ( 1 << oldPower ) + 1 );
  451. for( int oh = 0, nh = 0; oh < oldHeight; oh++, nh += 2 )
  452. {
  453. for( int ow = 0, nw = 0; ow < oldWidth; ow++, nw += 2 )
  454. {
  455. bool bRight = false;
  456. bool bUp = false;
  457. int oldIndex = oh * oldHeight + ow;
  458. int newIndex = nh * height + nw;
  459. int x = oldIndex % oldWidth;
  460. int y = oldIndex / oldHeight;
  461. float dist = GetFieldDistance( oldIndex );
  462. dists[newIndex] = dist;
  463. float alpha = GetAlpha( oldIndex );
  464. alphas[newIndex] = alpha;
  465. Vector dVector[2], subPVector[2], subNVector[2];
  466. GetFieldVector( oldIndex, dVector[0] );
  467. GetSubdivPosition( oldIndex, subPVector[0] );
  468. GetSubdivNormal( oldIndex, subNVector[0] );
  469. dispVectors[newIndex] = dVector[0];
  470. subdivPositions[newIndex] = subPVector[0];
  471. subdivNormals[newIndex] = subNVector[0];
  472. if( ( x + 1 ) < oldWidth )
  473. {
  474. dist = ( GetFieldDistance( oldIndex ) + GetFieldDistance( oldIndex + 1 ) ) * 0.5f;
  475. dists[newIndex+1] = dist;
  476. alpha = ( GetAlpha( oldIndex ) + GetAlpha( oldIndex + 1 ) ) * 0.5f;
  477. alphas[newIndex+1] = alpha;
  478. GetFieldVector( oldIndex, dVector[0] );
  479. GetFieldVector( oldIndex + 1, dVector[1] );
  480. dispVectors[newIndex+1] = ( dVector[0] + dVector[1] ) * 0.5f;
  481. GetSubdivPosition( oldIndex, subPVector[0] );
  482. GetSubdivPosition( oldIndex + 1, subPVector[1] );
  483. subdivPositions[newIndex+1] = ( subPVector[0] + subPVector[1] ) * 0.5f;
  484. GetSubdivNormal( oldIndex, subNVector[0] );
  485. GetSubdivNormal( oldIndex + 1, subNVector[1] );
  486. subdivNormals[newIndex+1] = ( subNVector[0] + subNVector[1] ) * 0.5f;
  487. bRight = true;
  488. }
  489. if( ( y + 1 ) < oldHeight )
  490. {
  491. dist = ( GetFieldDistance( oldIndex ) + GetFieldDistance( oldIndex + oldHeight ) ) * 0.5f;
  492. dists[newIndex+height] = dist;
  493. alpha = ( GetAlpha( oldIndex ) + GetAlpha( oldIndex + oldHeight ) ) * 0.5f;
  494. alphas[newIndex+height] = alpha;
  495. GetFieldVector( oldIndex, dVector[0] );
  496. GetFieldVector( oldIndex + oldHeight, dVector[1] );
  497. dispVectors[newIndex+height] = ( dVector[0] + dVector[1] ) * 0.5f;
  498. GetSubdivPosition( oldIndex, subPVector[0] );
  499. GetSubdivPosition( oldIndex + oldHeight, subPVector[1] );
  500. subdivPositions[newIndex+height] = ( subPVector[0] + subPVector[1] ) * 0.5f;
  501. GetSubdivNormal( oldIndex, subNVector[0] );
  502. GetSubdivNormal( oldIndex + oldHeight, subNVector[1] );
  503. subdivNormals[newIndex+height] = ( subNVector[0] + subNVector[1] ) * 0.5f;
  504. bUp = true;
  505. }
  506. if( bRight && bUp )
  507. {
  508. dist = ( GetFieldDistance( oldIndex + 1 ) + GetFieldDistance( oldIndex + oldHeight ) ) * 0.5f;
  509. dists[newIndex+height+1] = dist;
  510. alpha = ( GetAlpha( oldIndex + 1 ) + GetAlpha( oldIndex + oldHeight ) ) * 0.5f;
  511. alphas[newIndex+height+1] = alpha;
  512. GetFieldVector( oldIndex + 1, dVector[0] );
  513. GetFieldVector( oldIndex + oldHeight, dVector[1] );
  514. dispVectors[newIndex+height+1] = ( dVector[0] + dVector[1] ) * 0.5f;
  515. GetSubdivPosition( oldIndex + 1, subPVector[0] );
  516. GetSubdivPosition( oldIndex + oldHeight, subPVector[1] );
  517. subdivPositions[newIndex+height+1] = ( subPVector[0] + subPVector[1] ) * 0.5f;
  518. GetSubdivNormal( oldIndex + 1, subNVector[0] );
  519. GetSubdivNormal( oldIndex + oldHeight, subNVector[1] );
  520. subdivNormals[newIndex+height+1] = ( subNVector[0] + subNVector[1] ) * 0.5f;
  521. }
  522. }
  523. }
  524. //
  525. // copy sampled list
  526. //
  527. int size = GetSize();
  528. for( int i = 0; i < size; i++ )
  529. {
  530. SetAlpha( i, alphas[i] );
  531. SetFieldVector( i, dispVectors[i] );
  532. SetFieldDistance( i, dists[i] );
  533. SetSubdivPosition( i, subdivPositions[i] );
  534. SetSubdivNormal( i, subdivNormals[i] );
  535. }
  536. //
  537. // free temporary memory
  538. //
  539. delete [] dists;
  540. delete [] alphas;
  541. delete [] dispVectors;
  542. delete [] subdivPositions;
  543. delete [] subdivNormals;
  544. }
  545. //-----------------------------------------------------------------------------
  546. //-----------------------------------------------------------------------------
  547. void CMapDisp::SamplePoints( int index, int width, int height, bool *pValidPoints,
  548. float *pValue, float *pAlpha, Vector& newDispVector,
  549. Vector& newSubdivPos, Vector &newSubdivNormal )
  550. {
  551. //
  552. // set initial sample values
  553. //
  554. Vector vField, vSPos, vSNormal;
  555. int value = GetFieldDistance( index );
  556. float alpha = GetAlpha( index );
  557. GetFieldVector( index, vField );
  558. GetSubdivPosition( index, vSPos );
  559. GetSubdivNormal( index, vSNormal );
  560. int count = 1;
  561. //
  562. // accumulate other sample values from around the given index
  563. //
  564. int ndx;
  565. Vector vTmp;
  566. for( int i = 0; i < 8; i++ )
  567. {
  568. if( !pValidPoints[i] )
  569. continue;
  570. switch( i )
  571. {
  572. case 0: { ndx = index - height - 1; break; } // down and left
  573. case 1: { ndx = index - 1; break; } // left
  574. case 2: { ndx = index + height - 1; break; } // up and left
  575. case 3: { ndx = index + height; break; } // up
  576. case 4: { ndx = index + height + 1; break; } // up and right
  577. case 5: { ndx = index + 1; break; } // right
  578. case 6: { ndx = index - height + 1; break; } // down and right
  579. case 7: { ndx = index - height; break; } // down
  580. default: continue;
  581. }
  582. value += GetFieldDistance( ndx );
  583. alpha += GetAlpha( ndx );
  584. GetFieldVector( ndx, vTmp );
  585. vField += vTmp;
  586. GetSubdivPosition( ndx, vTmp );
  587. vSPos += vTmp;
  588. GetSubdivNormal( ndx, vTmp );
  589. vSNormal += vTmp;
  590. // increment count
  591. count++;
  592. }
  593. // average
  594. *pValue = value / ( float )count;
  595. *pAlpha = alpha / ( float )count;
  596. newDispVector = vField / ( float )count;
  597. newSubdivPos = vSPos / ( float )count;
  598. newSubdivNormal = vSNormal / ( float )count;
  599. }
  600. //-----------------------------------------------------------------------------
  601. //-----------------------------------------------------------------------------
  602. void CMapDisp::GetValidSamplePoints( int index, int width, int height, bool *pValidPoints )
  603. {
  604. int x = index % width;
  605. int y = index / height;
  606. // down and left
  607. if( ( ( x - 1 ) >= 0 ) && ( ( y - 1 ) >= 0 ) ) { pValidPoints[0] = true; }
  608. // left
  609. if( ( x - 1 ) >= 0 ) { pValidPoints[1] = true; }
  610. // up and left
  611. if( ( ( x - 1 ) >= 0 ) && ( ( y + 1 ) < height ) ) { pValidPoints[2] = true; }
  612. // up
  613. if( ( y + 1 ) < height ) { pValidPoints[3] = true; }
  614. // up and right
  615. if( ( ( x + 1 ) < width ) && ( ( y + 1 ) < height ) ) { pValidPoints[4] = true; }
  616. // right
  617. if( ( x + 1 ) < width ) { pValidPoints[5] = true; }
  618. // down and right
  619. if( ( ( x + 1 ) < width ) && ( ( y - 1 ) >= 0 ) ) { pValidPoints[6] = true; }
  620. // down
  621. if( ( y - 1 ) >= 0 ) { pValidPoints[7] = true; }
  622. }
  623. //-----------------------------------------------------------------------------
  624. //-----------------------------------------------------------------------------
  625. void CMapDisp::DownSample( int oldPower )
  626. {
  627. //
  628. // allocate temporary memory to hold new displacement distances
  629. //
  630. int width = GetWidth();
  631. int height = GetHeight();
  632. float *dists = new float[height*width];
  633. float *alphas = new float[height*width];
  634. Vector *dispVectors = new Vector[height*width];
  635. Vector *subdivPos = new Vector[height*width];
  636. Vector *subdivNormals = new Vector[height*width];
  637. if( !dists || !alphas || !dispVectors || !subdivPos || !subdivNormals )
  638. {
  639. delete [] dists;
  640. delete [] alphas;
  641. delete [] dispVectors;
  642. delete [] subdivPos;
  643. delete [] subdivNormals;
  644. return;
  645. }
  646. //
  647. // get old width and height
  648. //
  649. int oldWidth = ( ( 1 << oldPower ) + 1 );
  650. int oldHeight = ( ( 1 << oldPower ) + 1 );
  651. for( int oh = 0, nh = 0; oh < oldHeight; oh += 2, nh++ )
  652. {
  653. for( int ow = 0, nw = 0; ow < oldWidth; ow += 2, nw++ )
  654. {
  655. int oldIndex = oh * oldHeight + ow;
  656. int newIndex = nh * height + nw;
  657. //
  658. // clear valid point list and gather valid sample points
  659. //
  660. bool validPoints[8];
  661. for( int i = 0; i < 8; i++ ) { validPoints[i] = false; }
  662. GetValidSamplePoints( oldIndex, oldWidth, oldHeight, validPoints );
  663. //
  664. // sample the points, vector field vectors, and offset vectors
  665. //
  666. float newValue;
  667. float newAlpha;
  668. Vector newDispVector;
  669. Vector newSubdivPos;
  670. Vector newSubdivNormal;
  671. SamplePoints( oldIndex, oldWidth, oldHeight, validPoints, &newValue, &newAlpha,
  672. newDispVector, newSubdivPos, newSubdivNormal );
  673. //
  674. // save sampled values
  675. //
  676. dists[newIndex] = newValue;
  677. alphas[newIndex] = newAlpha;
  678. dispVectors[newIndex] = newDispVector;
  679. subdivPos[newIndex] = newSubdivPos;
  680. subdivNormals[newIndex] = newSubdivNormal;
  681. }
  682. }
  683. //
  684. // copy sampled list
  685. //
  686. int size = GetSize();
  687. for( int i = 0; i < size; i++ )
  688. {
  689. SetAlpha( i, alphas[i] );
  690. SetFieldDistance( i, dists[i] );
  691. SetFieldVector( i, dispVectors[i] );
  692. SetSubdivPosition( i, subdivPos[i] );
  693. SetSubdivNormal( i, subdivNormals[i] );
  694. }
  695. //
  696. // free temporary memory
  697. //
  698. delete [] dists;
  699. delete [] alphas;
  700. delete [] dispVectors;
  701. delete [] subdivPos;
  702. delete [] subdivNormals;
  703. }
  704. //-----------------------------------------------------------------------------
  705. // Purpose:
  706. //-----------------------------------------------------------------------------
  707. void CMapDisp::InvertAlpha( void )
  708. {
  709. int nVertCount = GetSize();
  710. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  711. {
  712. float flAlpha = GetAlpha( iVert );
  713. float flInvAlpha = 255.0f - flAlpha;
  714. SetAlpha( iVert, flInvAlpha );
  715. }
  716. // Update the surface with new data.
  717. UpdateData();
  718. }
  719. //-----------------------------------------------------------------------------
  720. //-----------------------------------------------------------------------------
  721. void CMapDisp::Resample( int power )
  722. {
  723. //
  724. // save old power for resampling, update to new power
  725. //
  726. int oldPower = GetPower();
  727. if( oldPower > power )
  728. {
  729. int delta = oldPower - power;
  730. for( int i = 0; i < delta; i++ )
  731. {
  732. SetPower( oldPower - ( i + 1 ) );
  733. DownSample( oldPower - i );
  734. }
  735. }
  736. else
  737. {
  738. int delta = power - oldPower;
  739. for( int i = 0; i < delta; i++ )
  740. {
  741. SetPower( oldPower + ( i + 1 ) );
  742. UpSample( oldPower + i );
  743. }
  744. }
  745. // update the surface with the new data
  746. UpdateData();
  747. CheckAndUpdateOverlays( true );
  748. }
  749. //-----------------------------------------------------------------------------
  750. //-----------------------------------------------------------------------------
  751. void CMapDisp::Elevate( float elevation )
  752. {
  753. // set the new elevation
  754. SetElevation( elevation );
  755. // update the displacement
  756. UpdateData();
  757. }
  758. //-----------------------------------------------------------------------------
  759. // Purpose: Resample a displacement map to be a clipped version of this surface.
  760. // Called when we split a face with a displacement surface.
  761. // NOTE: The new surface must be a quad as well, otherwise return false;
  762. // hBuilderDisp - The displacement surface to receive the new clipped data.
  763. //-----------------------------------------------------------------------------
  764. void CMapDisp::Split( EditDispHandle_t hBuilderDisp )
  765. {
  766. #define SPLIT_EPSILON 0.001f
  767. CMapDisp *pBuilderDisp = EditDispMgr()->GetDisp( hBuilderDisp );
  768. static Vector vecSurfPoints[4];
  769. for ( int iPoint = 0; iPoint < 4; ++iPoint )
  770. {
  771. GetSurfPoint( iPoint, vecSurfPoints[iPoint] );
  772. }
  773. // Prepare the destination surface for painting.
  774. pBuilderDisp->Paint_Init( DISPPAINT_CHANNEL_POSITION );
  775. int nVertCount = pBuilderDisp->GetSize();
  776. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  777. {
  778. Vector vecVert;
  779. pBuilderDisp->GetVert( iVert, vecVert );
  780. Vector2D vecDispUV;
  781. PointInQuadToBarycentric( vecSurfPoints[0], vecSurfPoints[3], vecSurfPoints[2], vecSurfPoints[1], vecVert, vecDispUV );
  782. // A little clean-up here.
  783. for ( int iComp = 0; iComp < 2; ++iComp )
  784. {
  785. vecDispUV[iComp] = clamp( vecDispUV[iComp], 0.0f, 1.0f );
  786. }
  787. Vector vecNewVert, vecNewNormal;
  788. float flNewAlpha;
  789. m_CoreDispInfo.DispUVToSurf( vecDispUV, vecNewVert, &vecNewNormal, &flNewAlpha );
  790. pBuilderDisp->SetAlpha( iVert, flNewAlpha );
  791. pBuilderDisp->Paint_SetValue(iVert, vecNewVert );
  792. }
  793. pBuilderDisp->Paint_Update( true );
  794. #undef SPLIT_EPSILON
  795. }
  796. //-----------------------------------------------------------------------------
  797. //-----------------------------------------------------------------------------
  798. bool CMapDisp::ComparePoints( const Vector& pt1, const Vector& pt2, const float tolerance )
  799. {
  800. for( int i = 0 ; i < 3 ; i++ )
  801. {
  802. if( fabs( pt1[i] - pt2[i] ) > tolerance )
  803. return false;
  804. }
  805. return true;
  806. }
  807. //-----------------------------------------------------------------------------
  808. //-----------------------------------------------------------------------------
  809. float CMapDisp::CollideWithTriangles( const Vector& RayStart, const Vector& RayEnd, Tri_t *pTris, int triCount,
  810. Vector& surfNormal )
  811. {
  812. // create a ray
  813. Ray_t ray;
  814. ray.m_Start = RayStart;
  815. ray.m_Delta = RayEnd - RayStart;
  816. ray.m_IsRay = true;
  817. Vector vNormal;
  818. float minFraction = 1.0f;
  819. for( int ndxTri = 0; ndxTri < triCount; ndxTri++ )
  820. {
  821. Tri_t &tri = pTris[ndxTri];
  822. float fraction = IntersectRayWithTriangle( ray, tri.v[0], tri.v[2], tri.v[1], true );
  823. if( fraction == -1 )
  824. continue;
  825. if( fraction < minFraction )
  826. {
  827. minFraction = fraction;
  828. // calculate the triangle normal
  829. Vector edge1, edge2;
  830. VectorSubtract( tri.v[2], tri.v[0], edge1 );
  831. VectorSubtract( tri.v[1], tri.v[0], edge2 );
  832. CrossProduct( edge1, edge2, surfNormal );
  833. VectorNormalize( surfNormal );
  834. }
  835. }
  836. return minFraction;
  837. }
  838. //-----------------------------------------------------------------------------
  839. //-----------------------------------------------------------------------------
  840. void CMapDisp::CreatePlanesFromBoundingBox( Plane_t *planes, const Vector& bbMin, const Vector& bbMax )
  841. {
  842. for( int i = 0; i < 6; i++ )
  843. {
  844. VectorClear( planes[i].normal );
  845. }
  846. //
  847. // use pads to store minor axes
  848. //
  849. planes[0].normal[0] = -1; planes[0].dist = -bbMin[0];
  850. planes[1].normal[0] = 1; planes[1].dist = bbMax[0];
  851. planes[2].normal[1] = -1; planes[2].dist = -bbMin[1];
  852. planes[3].normal[1] = 1; planes[3].dist = bbMax[1];
  853. planes[4].normal[2] = -1; planes[4].dist = -bbMin[2];
  854. planes[5].normal[2] = 1; planes[5].dist = bbMax[2];
  855. }
  856. //-----------------------------------------------------------------------------
  857. //-----------------------------------------------------------------------------
  858. void CMapDisp::CollideWithBoundingBoxes( const Vector& rayStart, const Vector& rayEnd,
  859. BBox_t *pBBox, int bboxCount, Tri_t *pTris, int *triCount )
  860. {
  861. const float DIST_EPSILON = 0.01f;
  862. //
  863. // collide against all bounding boxes
  864. //
  865. for( int i = 0; i < bboxCount; i++ )
  866. {
  867. //
  868. // make copy of vectors so they can be cut up
  869. //
  870. Vector start, end;
  871. start = rayStart;
  872. end = rayEnd;
  873. //
  874. // make planes for bbox
  875. //
  876. Plane_t planes[6];
  877. CreatePlanesFromBoundingBox( planes, pBBox[i].min, pBBox[i].max );
  878. //
  879. // collide against bounding box planes
  880. //
  881. int j;
  882. for( j = 0; j < 6; j++ )
  883. {
  884. float dist1 = DotProduct( planes[j].normal, start ) - planes[j].dist;
  885. float dist2 = DotProduct( planes[j].normal, end ) - planes[j].dist;
  886. //
  887. // entry intersection point - move ray start up to intersection
  888. //
  889. if( ( dist1 > DIST_EPSILON ) && ( dist2 < -DIST_EPSILON ) )
  890. {
  891. float fraction = ( dist1 / ( dist1 - dist2 ) );
  892. Vector segment, addOn;
  893. VectorSubtract( end, start, segment );
  894. VectorScale( segment, fraction, addOn );
  895. VectorNormalize( segment );
  896. VectorAdd( addOn, segment, addOn );
  897. VectorAdd( start, addOn, start );
  898. }
  899. else if( ( dist1 > DIST_EPSILON ) && ( dist2 > DIST_EPSILON ) )
  900. {
  901. break;
  902. }
  903. }
  904. //
  905. // collision add triangles to list
  906. //
  907. if( j == 6 )
  908. {
  909. // gross! shouldn't know value (64) and handle error better
  910. if( *triCount >= 256 )
  911. {
  912. // error!!!!!
  913. return;
  914. }
  915. int postSpacing = m_CoreDispInfo.GetPostSpacing();
  916. int index = i + ( i / ( postSpacing - 1 ) );
  917. m_CoreDispInfo.GetVert( index, pTris[*triCount].v[0] );
  918. m_CoreDispInfo.GetVert( index+postSpacing, pTris[*triCount].v[1] );
  919. m_CoreDispInfo.GetVert( index+1, pTris[*triCount].v[2] );
  920. *triCount += 1;
  921. m_CoreDispInfo.GetVert( index+1, pTris[*triCount].v[0] );
  922. m_CoreDispInfo.GetVert( index+postSpacing, pTris[*triCount].v[1] );
  923. m_CoreDispInfo.GetVert( index+postSpacing+1, pTris[*triCount].v[2] );
  924. *triCount += 1;
  925. }
  926. }
  927. }
  928. //-----------------------------------------------------------------------------
  929. //-----------------------------------------------------------------------------
  930. void CMapDisp::CreateBoundingBoxes( BBox_t *pBBox, int count, float bloat )
  931. {
  932. //
  933. // initialize the bounding boxes
  934. //
  935. for( int i = 0; i < count; i++ )
  936. {
  937. VectorFill( pBBox[i].min, COORD_NOTINIT );
  938. VectorFill( pBBox[i].max, -COORD_NOTINIT );
  939. }
  940. // get the width and height of the displacement surface
  941. int postSpacing = m_CoreDispInfo.GetPostSpacing();
  942. //
  943. // find bounding box of every two consecutive triangles
  944. //
  945. int bboxIndex = 0;
  946. int index = 0;
  947. for( int i = 0; i < ( postSpacing - 1 ); i++ )
  948. {
  949. for( int j = 0; j < ( postSpacing - 1 ); j++ )
  950. {
  951. for( int k = 0; k < 4; k++ )
  952. {
  953. switch( k )
  954. {
  955. case 0: { index = ( postSpacing * i ) + j; break; }
  956. case 1: { index = ( postSpacing * ( i + 1 ) ) + j; break; }
  957. case 2: { index = ( postSpacing * i ) + ( j + 1 ); break; }
  958. case 3: { index = ( postSpacing * ( i + 1 ) ) + ( j + 1 ); break; }
  959. }
  960. Vector v;
  961. m_CoreDispInfo.GetVert( index, v );
  962. if( v[0] < pBBox[bboxIndex].min[0] ) { pBBox[bboxIndex].min[0] = v[0]; }
  963. if( v[1] < pBBox[bboxIndex].min[1] ) { pBBox[bboxIndex].min[1] = v[1]; }
  964. if( v[2] < pBBox[bboxIndex].min[2] ) { pBBox[bboxIndex].min[2] = v[2]; }
  965. if( v[0] > pBBox[bboxIndex].max[0] ) { pBBox[bboxIndex].max[0] = v[0]; }
  966. if( v[1] > pBBox[bboxIndex].max[1] ) { pBBox[bboxIndex].max[1] = v[1]; }
  967. if( v[2] > pBBox[bboxIndex].max[2] ) { pBBox[bboxIndex].max[2] = v[2]; }
  968. }
  969. // bloat all the boxes a little
  970. for( int axis = 0; axis < 3; axis++ )
  971. {
  972. pBBox[bboxIndex].min[axis] -= bloat;
  973. pBBox[bboxIndex].max[axis] += bloat;
  974. }
  975. bboxIndex++;
  976. }
  977. }
  978. }
  979. //-----------------------------------------------------------------------------
  980. // Purpose:
  981. // NOTE: Performance, look into it here. This is doing way more work than
  982. // necessary. We should probably update a collision representation, a
  983. // simple one at least whenever we update a displacement and use it as
  984. // a first level cull here. But for now....it works...ship, ship, ship.
  985. //-----------------------------------------------------------------------------
  986. bool CMapDisp::TraceLine( Vector &vecHitPos, Vector &vecHitNormal, Vector const &vecRayStart, Vector const &vecRayEnd )
  987. {
  988. // Just do the slow thing for now.
  989. float flFraction;
  990. int iTri = CollideWithDispTri( vecRayStart, vecRayEnd, flFraction );
  991. if ( iTri == -1 )
  992. return false;
  993. // Get hit position and normal.
  994. Vector vecRay = vecRayEnd - vecRayStart;
  995. vecRay = vecRay * flFraction;
  996. vecHitPos = vecRayStart + vecRay;
  997. Vector vecTriPoints[3];
  998. GetTriPos( iTri, vecTriPoints[0], vecTriPoints[1], vecTriPoints[2] );
  999. Vector vecEdge1 = vecTriPoints[2] - vecTriPoints[0];
  1000. Vector vecEdge2 = vecTriPoints[1] - vecTriPoints[0];
  1001. vecHitNormal = CrossProduct( vecEdge1, vecEdge2 );
  1002. VectorNormalize( vecHitNormal );
  1003. return true;
  1004. }
  1005. //-----------------------------------------------------------------------------
  1006. //-----------------------------------------------------------------------------
  1007. bool CMapDisp::TraceLineSnapTo( Vector &HitPos, Vector &HitNormal,
  1008. Vector const &RayStart, Vector const &RayEnd )
  1009. {
  1010. #define LOWER_TOLERANCE -0.1f
  1011. #define UPPER_TOLERANCE 1.1f
  1012. // get width and height
  1013. int width = GetWidth();
  1014. int height = GetHeight();
  1015. // build the ray
  1016. Ray_t ray;
  1017. ray.m_Start = RayStart;
  1018. ray.m_Delta = RayEnd - RayStart;
  1019. ray.m_IsRay = true;
  1020. float u, v;
  1021. Tri_t tri;
  1022. // test edge 0
  1023. for( int ndx = 0; ndx < ( width - 1 ); ndx++ )
  1024. {
  1025. GetVert( ndx, tri.v[0] );
  1026. GetVert( ndx + width, tri.v[1] );
  1027. GetVert( ndx + 1, tri.v[2] );
  1028. ComputeIntersectionBarycentricCoordinates( ray, tri.v[0], tri.v[1], tri.v[2], u, v );
  1029. // along edge (0.0 < v < 1.0) and below (u < 0.0)
  1030. if( ( v >= LOWER_TOLERANCE ) && ( v <= UPPER_TOLERANCE ) && ( u < 0.0f ) )
  1031. {
  1032. v = clamp( v, 0.0f, 1.0f );
  1033. // snap u (u = 0.0)
  1034. HitPos = tri.v[0] + ( tri.v[2] - tri.v[0] ) * v;
  1035. return true;
  1036. }
  1037. // special corner 0
  1038. if( ( ndx == 0 ) && ( v < 0.0f ) && ( u < 0.0f ) )
  1039. {
  1040. HitPos = tri.v[0];
  1041. return true;
  1042. }
  1043. }
  1044. // test edge 1
  1045. for( int ndx = 0; ndx < ( height - 1 ); ndx++ )
  1046. {
  1047. GetVert( ndx * width, tri.v[0] );
  1048. GetVert( ( ndx * width )+ width, tri.v[1] );
  1049. GetVert( ( ndx * width ) + 1, tri.v[2] );
  1050. ComputeIntersectionBarycentricCoordinates( ray, tri.v[0], tri.v[1], tri.v[2], u, v );
  1051. // along edge (0.0 < u < 1.0) and left (v < 0.0)
  1052. if( ( u >= LOWER_TOLERANCE ) && ( u <= UPPER_TOLERANCE ) && ( v < 0.0f ) )
  1053. {
  1054. u = clamp( u, 0.0f, 1.0f );
  1055. // snap v (v = 0.0)
  1056. HitPos = tri.v[0] + ( tri.v[1] - tri.v[0] ) * u;
  1057. return true;
  1058. }
  1059. // special corner 1
  1060. if( ( ndx == ( height - 2 ) ) && ( u > 1.0f ) && ( v < 0.0f ) )
  1061. {
  1062. HitPos = tri.v[1];
  1063. return true;
  1064. }
  1065. }
  1066. // test edge 2
  1067. for( int ndx = 0; ndx < ( width - 1 ); ndx++ )
  1068. {
  1069. GetVert( ( ( height - 1 ) * width ) + ndx + 1, tri.v[0] );
  1070. GetVert( ( ( height - 2 ) * width ) + ndx + 1, tri.v[1] );
  1071. GetVert( ( ( height - 1 ) * width ) + ndx, tri.v[2] );
  1072. ComputeIntersectionBarycentricCoordinates( ray, tri.v[0], tri.v[1], tri.v[2], u, v );
  1073. // along edge (0.0 < v < 1.0) and above (u < 0.0)
  1074. if( ( v >= LOWER_TOLERANCE ) && ( v <= UPPER_TOLERANCE ) && ( u < 0.0f ) )
  1075. {
  1076. v = clamp( v, 0.0f, 1.0f );
  1077. // snap u (u = 0.0)
  1078. HitPos = tri.v[0] + ( tri.v[2] - tri.v[0] ) * v;
  1079. return true;
  1080. }
  1081. // special corner 2
  1082. if( ( ndx == ( width - 2 ) ) && ( v < 0.0f ) && ( u < 0.0f ) )
  1083. {
  1084. HitPos = tri.v[0];
  1085. return true;
  1086. }
  1087. }
  1088. // test edge 3
  1089. for( int ndx = 0; ndx < ( height - 1 ); ndx++ )
  1090. {
  1091. GetVert( ( ndx * width ) + ( ( 2 * width ) - 1 ), tri.v[0] );
  1092. GetVert( ( ndx * width ) + ( width - 1 ), tri.v[1] );
  1093. GetVert( ( ndx * width ) + ( ( 2 * width ) - 2 ), tri.v[2] );
  1094. ComputeIntersectionBarycentricCoordinates( ray, tri.v[0], tri.v[1], tri.v[2], u, v );
  1095. // along edge (0.0 < u < 1.0) and right (v < 0.0)
  1096. if( ( u >= LOWER_TOLERANCE ) && ( u <= UPPER_TOLERANCE ) && ( v < 0.0f ) )
  1097. {
  1098. u = clamp( u, 0.0f, 1.0f );
  1099. // snap v (v = 0.0)
  1100. HitPos = tri.v[0] + ( tri.v[1] - tri.v[0] ) * u;
  1101. return true;
  1102. }
  1103. // special corner 3
  1104. if( ( ndx == 0 ) && ( u > 1.0f ) && ( v < 0.0f ) )
  1105. {
  1106. HitPos = tri.v[1];
  1107. return true;
  1108. }
  1109. }
  1110. return false;
  1111. #undef LOWER_TOLERANCE
  1112. #undef UPPER_TOLERANCE
  1113. }
  1114. //-----------------------------------------------------------------------------
  1115. //-----------------------------------------------------------------------------
  1116. void CMapDisp::Flip( int flipType )
  1117. {
  1118. int width = GetWidth();
  1119. int height = GetHeight();
  1120. switch( flipType )
  1121. {
  1122. case FLIP_HORIZONTAL:
  1123. {
  1124. return;
  1125. }
  1126. case FLIP_VERTICAL:
  1127. {
  1128. return;
  1129. }
  1130. case FLIP_TRANSPOSE:
  1131. {
  1132. for( int ndxHeight = 0; ndxHeight < height; ndxHeight++ )
  1133. {
  1134. for( int ndxWidth = ndxHeight; ndxWidth < width; ndxWidth++ )
  1135. {
  1136. float dist1 = GetFieldDistance( ( ndxHeight * width ) + ndxWidth );
  1137. float dist2 = GetFieldDistance( ( ndxWidth * height ) + ndxHeight );
  1138. SetFieldDistance( ( ndxHeight * width ) + ndxWidth, dist2 );
  1139. SetFieldDistance( ( ndxWidth * height ) + ndxHeight, dist1 );
  1140. Vector v1, v2;
  1141. GetFieldVector( ( ndxHeight * width ) + ndxWidth, v1 );
  1142. GetFieldVector( ( ndxWidth * height ) + ndxHeight, v2 );
  1143. SetFieldVector( ( ndxHeight * width ) + ndxWidth, v2 );
  1144. SetFieldVector( ( ndxWidth * height ) + ndxHeight, v1 );
  1145. GetSubdivPosition( ( ndxHeight * width ) + ndxWidth, v1 );
  1146. GetSubdivPosition( ( ndxWidth * height ) + ndxHeight, v2 );
  1147. SetSubdivPosition( ( ndxHeight * width ) + ndxWidth, v2 );
  1148. SetSubdivPosition( ( ndxWidth * height ) + ndxHeight, v1 );
  1149. GetSubdivNormal( ( ndxHeight * width ) + ndxWidth, v1 );
  1150. GetSubdivNormal( ( ndxWidth * height ) + ndxHeight, v2 );
  1151. SetSubdivNormal( ( ndxHeight * width ) + ndxWidth, v2 );
  1152. SetSubdivNormal( ( ndxWidth * height ) + ndxHeight, v1 );
  1153. float alpha1 = GetAlpha( ( ndxHeight * width ) + ndxWidth );
  1154. float alpha2 = GetAlpha( ( ndxWidth * height ) + ndxHeight );
  1155. SetAlpha( ( ndxHeight * width ) + ndxWidth, alpha2 );
  1156. SetAlpha( ( ndxWidth * height ) + ndxHeight, alpha1 );
  1157. }
  1158. }
  1159. return;
  1160. }
  1161. default:
  1162. {
  1163. return;
  1164. }
  1165. }
  1166. }
  1167. //-----------------------------------------------------------------------------
  1168. //-----------------------------------------------------------------------------
  1169. void CMapDisp::UpdateWalkable( void )
  1170. {
  1171. // Set the walkable tag.
  1172. int nTriCount = GetTriCount();
  1173. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  1174. {
  1175. Vector v1, v2, v3;
  1176. GetTriPos( iTri, v1, v2, v3 );
  1177. Vector vecEdge1, vecEdge2;
  1178. vecEdge1 = v2 - v1;
  1179. vecEdge2 = v3 - v1;
  1180. Vector vecTriNormal;
  1181. CrossProduct( vecEdge2, vecEdge1, vecTriNormal );
  1182. VectorNormalize( vecTriNormal );
  1183. ResetTriTag( iTri, COREDISPTRI_TAG_WALKABLE );
  1184. if ( vecTriNormal.z >= WALKABLE_NORMAL_VALUE )
  1185. {
  1186. SetTriTag( iTri, COREDISPTRI_TAG_WALKABLE );
  1187. }
  1188. }
  1189. // Create the walkable render list.
  1190. m_aWalkableVerts.RemoveAll();
  1191. m_aWalkableIndices.RemoveAll();
  1192. m_aForcedWalkableIndices.RemoveAll();
  1193. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  1194. {
  1195. if ( !IsTriWalkable( iTri ) )
  1196. {
  1197. unsigned short triIndices[3];
  1198. unsigned short newTriIndices[3];
  1199. GetTriIndices( iTri, triIndices[0], triIndices[1], triIndices[2] );
  1200. newTriIndices[0] = m_aWalkableVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[0] ) );
  1201. newTriIndices[1] = m_aWalkableVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[1] ) );
  1202. newTriIndices[2] = m_aWalkableVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[2] ) );
  1203. if ( IsTriTag( iTri, COREDISPTRI_TAG_FORCE_WALKABLE_BIT ) )
  1204. {
  1205. m_aForcedWalkableIndices.AddToTail( newTriIndices[0] );
  1206. m_aForcedWalkableIndices.AddToTail( newTriIndices[1] );
  1207. m_aForcedWalkableIndices.AddToTail( newTriIndices[2] );
  1208. }
  1209. else
  1210. {
  1211. m_aWalkableIndices.AddToTail( newTriIndices[0] );
  1212. m_aWalkableIndices.AddToTail( newTriIndices[1] );
  1213. m_aWalkableIndices.AddToTail( newTriIndices[2] );
  1214. }
  1215. }
  1216. }
  1217. }
  1218. //-----------------------------------------------------------------------------
  1219. //-----------------------------------------------------------------------------
  1220. void CMapDisp::UpdateBuildable( void )
  1221. {
  1222. // Set the buildable tag.
  1223. int nTriCount = GetTriCount();
  1224. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  1225. {
  1226. Vector v1, v2, v3;
  1227. GetTriPos( iTri, v1, v2, v3 );
  1228. Vector vecEdge1, vecEdge2;
  1229. vecEdge1 = v2 - v1;
  1230. vecEdge2 = v3 - v1;
  1231. Vector vecTriNormal;
  1232. CrossProduct( vecEdge2, vecEdge1, vecTriNormal );
  1233. VectorNormalize( vecTriNormal );
  1234. ResetTriTag( iTri, COREDISPTRI_TAG_BUILDABLE );
  1235. if ( vecTriNormal.z >= BUILDABLE_NORMAL_VALUE )
  1236. {
  1237. SetTriTag( iTri, COREDISPTRI_TAG_BUILDABLE );
  1238. }
  1239. }
  1240. // Create the buildable render list.
  1241. m_aBuildableVerts.RemoveAll();
  1242. m_aBuildableIndices.RemoveAll();
  1243. m_aForcedBuildableIndices.RemoveAll();
  1244. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  1245. {
  1246. if ( !IsTriBuildable( iTri ) )
  1247. {
  1248. unsigned short triIndices[3];
  1249. unsigned short newTriIndices[3];
  1250. GetTriIndices( iTri, triIndices[0], triIndices[1], triIndices[2] );
  1251. newTriIndices[0] = m_aBuildableVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[0] ) );
  1252. newTriIndices[1] = m_aBuildableVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[1] ) );
  1253. newTriIndices[2] = m_aBuildableVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[2] ) );
  1254. if ( IsTriTag( iTri, COREDISPTRI_TAG_FORCE_BUILDABLE_BIT ) )
  1255. {
  1256. m_aForcedBuildableIndices.AddToTail( newTriIndices[0] );
  1257. m_aForcedBuildableIndices.AddToTail( newTriIndices[1] );
  1258. m_aForcedBuildableIndices.AddToTail( newTriIndices[2] );
  1259. }
  1260. else
  1261. {
  1262. m_aBuildableIndices.AddToTail( newTriIndices[0] );
  1263. m_aBuildableIndices.AddToTail( newTriIndices[1] );
  1264. m_aBuildableIndices.AddToTail( newTriIndices[2] );
  1265. }
  1266. }
  1267. }
  1268. }
  1269. //-----------------------------------------------------------------------------
  1270. // Purpose:
  1271. //-----------------------------------------------------------------------------
  1272. void CMapDisp::UpdateTriRemove( void )
  1273. {
  1274. // Create the remove render list.
  1275. m_aRemoveVerts.RemoveAll();
  1276. m_aRemoveIndices.RemoveAll();
  1277. int nTriCount = GetTriCount();
  1278. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  1279. {
  1280. if ( IsTriRemove( iTri ) )
  1281. {
  1282. unsigned short triIndices[3];
  1283. unsigned short newTriIndices[3];
  1284. GetTriIndices( iTri, triIndices[0], triIndices[1], triIndices[2] );
  1285. newTriIndices[0] = m_aRemoveVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[0] ) );
  1286. newTriIndices[1] = m_aRemoveVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[1] ) );
  1287. newTriIndices[2] = m_aRemoveVerts.AddToTail( m_CoreDispInfo.GetDispVert( triIndices[2] ) );
  1288. m_aRemoveIndices.AddToTail( newTriIndices[0] );
  1289. m_aRemoveIndices.AddToTail( newTriIndices[1] );
  1290. m_aRemoveIndices.AddToTail( newTriIndices[2] );
  1291. }
  1292. }
  1293. }
  1294. //-----------------------------------------------------------------------------
  1295. // Purpose:
  1296. //-----------------------------------------------------------------------------
  1297. void CMapDisp::CreateShoreOverlays( CMapFace *pFace, Shoreline_t *pShoreline )
  1298. {
  1299. // Do the bounds volumes intersect?
  1300. Vector vecDispMin, vecDispMax;
  1301. GetBoundingBox( vecDispMin, vecDispMax );
  1302. Vector vecSolidMin, vecSolidMax;
  1303. CMapSolid *pSolid = static_cast<CMapSolid*>( pFace->GetParent() );
  1304. pSolid->GetCullBox( vecSolidMin, vecSolidMax );
  1305. if ( !IsBoxIntersectingBox( vecDispMin, vecDispMax, vecSolidMin, vecSolidMax ) )
  1306. return;
  1307. int nTriangleCount = TriangleCount();
  1308. for ( int iTri = 0; iTri < nTriangleCount; ++iTri )
  1309. {
  1310. unsigned short i[3];
  1311. GetTriIndices( iTri, i[0], i[1], i[2] );
  1312. Vector v[3];
  1313. GetVert( i[0], v[0] );
  1314. GetVert( i[1], v[1] );
  1315. GetVert( i[2], v[2] );
  1316. Vector vU, vV;
  1317. VectorSubtract( v[1], v[0], vU );
  1318. VectorSubtract( v[2], v[0], vV );
  1319. Vector2D vecIntersect[2];
  1320. Vector4D plane;
  1321. plane.Init( pFace->plane.normal.x, pFace->plane.normal.y, pFace->plane.normal.z, pFace->plane.dist );
  1322. int nCount = IntersectTriangleWithPlaneBarycentric( v[0], vU, vV, plane, vecIntersect );
  1323. if ( nCount != 2 )
  1324. continue;
  1325. // Find the normal pointing toward the shore.
  1326. Vector vecPoints[2];
  1327. vecPoints[0] = v[0] + ( vU * vecIntersect[0].x ) + ( vV * vecIntersect[0].y );
  1328. vecPoints[1] = v[0] + ( vU * vecIntersect[1].x ) + ( vV * vecIntersect[1].y );
  1329. // Create shore edge normal.
  1330. Vector vecEdge, vecNormal;
  1331. VectorSubtract( vecPoints[1], vecPoints[0], vecEdge );
  1332. VectorNormalize( vecEdge );
  1333. CrossProduct( vecEdge, pFace->plane.normal, vecNormal );
  1334. float flEdgeDist = DotProduct( vecNormal, vecPoints[0] );
  1335. for ( int iVert = 0; iVert < 3; ++iVert )
  1336. {
  1337. float flDist = DotProduct( vecNormal, v[iVert] ) - flEdgeDist;
  1338. if ( flDist > 0.0f )
  1339. {
  1340. float flDist2 = DotProduct( pFace->plane.normal, v[iVert] ) - pFace->plane.dist;
  1341. if ( flDist2 < 0.0f )
  1342. {
  1343. vecNormal.Negate();
  1344. break;
  1345. }
  1346. }
  1347. }
  1348. if ( !VectorsAreEqual( vecPoints[0], vecPoints[1], 0.1f ) )
  1349. {
  1350. pShoreline->AddSegment( vecPoints[0], vecPoints[1], vecNormal, pFace->plane.dist, pFace, GetEditHandle() );
  1351. }
  1352. }
  1353. }
  1354. //-----------------------------------------------------------------------------
  1355. //-----------------------------------------------------------------------------
  1356. static void RenderDisplacementNormals( CCoreDispInfo& coreDispInfo, int numVerts )
  1357. {
  1358. Vector points[4], normal;
  1359. CMeshBuilder meshBuilder;
  1360. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1361. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  1362. meshBuilder.Begin( pMesh, MATERIAL_LINES, numVerts );
  1363. for( int i = 0; i < numVerts; i++ )
  1364. {
  1365. coreDispInfo.GetVert( i, points[0] );
  1366. coreDispInfo.GetNormal( i, normal );
  1367. meshBuilder.Color3f( 0.0f, 1.0f, 0.0f );
  1368. meshBuilder.Position3f( points[0][0], points[0][1], points[0][2] );
  1369. meshBuilder.AdvanceVertex();
  1370. meshBuilder.Color3f( 0.0f, 1.0f, 0.0f );
  1371. meshBuilder.Position3f( points[0][0] + ( normal[0] * 10.0f ),
  1372. points[0][1] + ( normal[1] * 10.0f ),
  1373. points[0][2] + ( normal[2] * 10.0f ) );
  1374. meshBuilder.AdvanceVertex();
  1375. }
  1376. meshBuilder.End();
  1377. pMesh->Draw();
  1378. }
  1379. //-----------------------------------------------------------------------------
  1380. //-----------------------------------------------------------------------------
  1381. static void RenderDisplacementTangentsS( CCoreDispInfo &coreDispInfo, int numVerts )
  1382. {
  1383. Vector points[4], tangentS;
  1384. CMeshBuilder meshBuilder;
  1385. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1386. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1387. meshBuilder.Begin( pMesh, MATERIAL_LINES, numVerts );
  1388. for( int i = 0; i < numVerts; i++ )
  1389. {
  1390. coreDispInfo.GetVert( i, points[0] );
  1391. coreDispInfo.GetTangentS( i, tangentS );
  1392. meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
  1393. meshBuilder.Position3f( points[0][0], points[0][1], points[0][2] );
  1394. meshBuilder.AdvanceVertex();
  1395. meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
  1396. meshBuilder.Position3f( points[0][0] + ( tangentS[0] * 10.0f ),
  1397. points[0][1] + ( tangentS[1] * 10.0f ),
  1398. points[0][2] + ( tangentS[2] * 10.0f ) );
  1399. meshBuilder.AdvanceVertex();
  1400. }
  1401. meshBuilder.End();
  1402. pMesh->Draw();
  1403. }
  1404. //-----------------------------------------------------------------------------
  1405. //-----------------------------------------------------------------------------
  1406. static void RenderDisplacementTangentsT( CCoreDispInfo &coreDispInfo, int numVerts )
  1407. {
  1408. Vector points[4], tangentT;
  1409. CMeshBuilder meshBuilder;
  1410. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1411. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1412. meshBuilder.Begin( pMesh, MATERIAL_LINES, numVerts );
  1413. for( int i = 0; i < numVerts; i++ )
  1414. {
  1415. coreDispInfo.GetVert( i, points[0] );
  1416. coreDispInfo.GetTangentT( i, tangentT );
  1417. meshBuilder.Color3f( 0.0f, 0.0f, 1.0f );
  1418. meshBuilder.Position3f( points[0][0], points[0][1], points[0][2] );
  1419. meshBuilder.AdvanceVertex();
  1420. meshBuilder.Color3f( 0.0f, 0.0f, 1.0f );
  1421. meshBuilder.Position3f( points[0][0] + ( tangentT[0] * 10.0f ),
  1422. points[0][1] + ( tangentT[1] * 10.0f ),
  1423. points[0][2] + ( tangentT[2] * 10.0f ) );
  1424. meshBuilder.AdvanceVertex();
  1425. }
  1426. meshBuilder.End();
  1427. pMesh->Draw();
  1428. }
  1429. //-----------------------------------------------------------------------------
  1430. //-----------------------------------------------------------------------------
  1431. static void RenderFaceVertexNormals( CCoreDispInfo& coreDispInfo )
  1432. {
  1433. Vector points[4], normal;
  1434. CMeshBuilder meshBuilder;
  1435. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1436. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1437. meshBuilder.Begin( pMesh, MATERIAL_LINES, 4 );
  1438. CCoreDispSurface *pSurf = coreDispInfo.GetSurface();
  1439. for( int i = 0; i < 4; i++ )
  1440. {
  1441. pSurf->GetPoint( i, points[0] );
  1442. pSurf->GetPointNormal( i, normal );
  1443. meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
  1444. meshBuilder.Position3f( points[0][0], points[0][1], points[0][2] );
  1445. meshBuilder.AdvanceVertex();
  1446. meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
  1447. meshBuilder.Position3f( points[0][0] + ( normal[0] * 25.0f ),
  1448. points[0][1] + ( normal[1] * 25.0f ),
  1449. points[0][2] + ( normal[2] * 25.0f ) );
  1450. meshBuilder.AdvanceVertex();
  1451. }
  1452. meshBuilder.End();
  1453. pMesh->Draw();
  1454. }
  1455. //-----------------------------------------------------------------------------
  1456. //-----------------------------------------------------------------------------
  1457. static void RenderDisplacementVectorField( CCoreDispInfo& coreDispInfo, int numVerts )
  1458. {
  1459. Vector points[4], normal;
  1460. CMeshBuilder meshBuilder;
  1461. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1462. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1463. meshBuilder.Begin( pMesh, MATERIAL_LINES, numVerts );
  1464. for( int i = 0; i < numVerts; i++ )
  1465. {
  1466. coreDispInfo.GetVert( i, points[0] );
  1467. coreDispInfo.GetFieldVector( i, normal );
  1468. meshBuilder.Color3f( 1.0f, 1.0f, 0.0f );
  1469. meshBuilder.Position3f( points[0][0], points[0][1], points[0][2] );
  1470. meshBuilder.AdvanceVertex();
  1471. meshBuilder.Color3f( 1.0f, 1.0f, 0.0f );
  1472. meshBuilder.Position3f( points[0][0] + ( normal[0] * 50.0f ),
  1473. points[0][1] + ( normal[1] * 50.0f ),
  1474. points[0][2] + ( normal[2] * 50.0f ) );
  1475. meshBuilder.AdvanceVertex();
  1476. }
  1477. meshBuilder.End();
  1478. pMesh->Draw();
  1479. }
  1480. //-----------------------------------------------------------------------------
  1481. //-----------------------------------------------------------------------------
  1482. static void RenderSubdivPositions( CCoreDispInfo& coreDispInfo, int numVerts )
  1483. {
  1484. Vector pt, normal;
  1485. CMeshBuilder meshBuilder;
  1486. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1487. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1488. meshBuilder.Begin( pMesh, MATERIAL_LINES, numVerts );
  1489. for( int i = 0; i < numVerts; i++ )
  1490. {
  1491. coreDispInfo.GetFlatVert( i, pt );
  1492. coreDispInfo.GetSubdivPosition( i, normal );
  1493. meshBuilder.Position3f( pt[0], pt[1], pt[2] );
  1494. meshBuilder.Color3f( 1.0f, 0.0f, 1.0f );
  1495. meshBuilder.AdvanceVertex();
  1496. meshBuilder.Position3f( pt[0] + normal[0], pt[1] + normal[1], pt[2] + normal[2] );
  1497. meshBuilder.Color3f( 1.0f, 0.0f, 1.0f );
  1498. meshBuilder.AdvanceVertex();
  1499. }
  1500. meshBuilder.End();
  1501. pMesh->Draw();
  1502. }
  1503. //-----------------------------------------------------------------------------
  1504. //-----------------------------------------------------------------------------
  1505. static void RenderDisplacementEdges( CCoreDispInfo& coreDispInfo )
  1506. {
  1507. Vector points[4];
  1508. CMeshBuilder meshBuilder;
  1509. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1510. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1511. meshBuilder.Begin( pMesh, MATERIAL_LINES, 4 );
  1512. CCoreDispSurface *pSurf = coreDispInfo.GetSurface();
  1513. pSurf->GetPoint( 0, points[0] );
  1514. pSurf->GetPoint( 1, points[1] );
  1515. pSurf->GetPoint( 2, points[2] );
  1516. pSurf->GetPoint( 3, points[3] );
  1517. meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
  1518. meshBuilder.Position3f( points[0][0], points[0][1], points[0][2] );
  1519. meshBuilder.AdvanceVertex();
  1520. meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
  1521. meshBuilder.Position3f( points[1][0], points[1][1], points[1][2] );
  1522. meshBuilder.AdvanceVertex();
  1523. meshBuilder.Color3f( 0.0f, 1.0f, 0.0f );
  1524. meshBuilder.Position3f( points[1][0], points[1][1], points[1][2] );
  1525. meshBuilder.AdvanceVertex();
  1526. meshBuilder.Color3f( 0.0f, 1.0f, 0.0f );
  1527. meshBuilder.Position3f( points[2][0], points[2][1], points[2][2] );
  1528. meshBuilder.AdvanceVertex();
  1529. meshBuilder.Color3f( 0.0f, 0.0f, 1.0f );
  1530. meshBuilder.Position3f( points[2][0], points[2][1], points[2][2] );
  1531. meshBuilder.AdvanceVertex();
  1532. meshBuilder.Color3f( 0.0f, 0.0f, 1.0f );
  1533. meshBuilder.Position3f( points[3][0], points[3][1], points[3][2] );
  1534. meshBuilder.AdvanceVertex();
  1535. meshBuilder.Color3f( 1.0f, 0.0f, 1.0f );
  1536. meshBuilder.Position3f( points[3][0], points[3][1], points[3][2] );
  1537. meshBuilder.AdvanceVertex();
  1538. meshBuilder.Color3f( 1.0f, 0.0f, 1.0f );
  1539. meshBuilder.Position3f( points[0][0], points[0][1], points[0][2] );
  1540. meshBuilder.AdvanceVertex();
  1541. meshBuilder.End();
  1542. pMesh->Draw();
  1543. }
  1544. //-----------------------------------------------------------------------------
  1545. //-----------------------------------------------------------------------------
  1546. void CMapDisp::RenderDisAllowedVerts( CRender3D *pRender )
  1547. {
  1548. CBitVec<MAX_DISPVERTS> &allowedVerts = m_CoreDispInfo.GetAllowedVerts();
  1549. int nVertCount = GetSize();
  1550. for ( int iVert = 0; iVert < nVertCount; ++iVert )
  1551. {
  1552. if ( allowedVerts.Get( iVert ) == 0 )
  1553. {
  1554. Vector vecPos;
  1555. GetVert( iVert, vecPos );
  1556. // Draw a box at this point!
  1557. Vector vecPointMin, vecPointMax;
  1558. for ( int iAxis = 0; iAxis < 3; ++iAxis )
  1559. {
  1560. vecPointMin[iAxis] = vecPos[iAxis] - 5.0f;
  1561. vecPointMax[iAxis] = vecPos[iAxis] + 5.0f;
  1562. }
  1563. pRender->RenderBox( vecPointMin, vecPointMax, 255, 0, 255, SELECT_NONE );
  1564. }
  1565. }
  1566. }
  1567. //-----------------------------------------------------------------------------
  1568. //-----------------------------------------------------------------------------
  1569. void CMapDisp::Render3DDebug( CRender3D *pRender, bool isSelected )
  1570. {
  1571. #if 0
  1572. pRender->SetRenderMode( RENDER_MODE_WIREFRAME );
  1573. RenderDisplacementNormals( m_CoreDispInfo, MAPDISP_MAX_VERTS );
  1574. RenderDisplacementTangentsS( m_CoreDispInfo, MAPDISP_MAX_VERTS );
  1575. RenderDisplacementTangentsT( m_CoreDispInfo, MAPDISP_MAX_VERTS );
  1576. // RenderFaceVertexNormals( m_CoreDispInfo );
  1577. RenderDisplacementVectorField( m_CoreDispInfo, MAPDISP_MAX_VERTS );
  1578. RenderSubdivPositions( m_CoreDispInfo, GetSize() );
  1579. // RenderDisplacementEdges( m_CoreDispInfo );
  1580. #endif
  1581. }
  1582. //-----------------------------------------------------------------------------
  1583. //-----------------------------------------------------------------------------
  1584. void CMapDisp::CalcColor( CRender3D *pRender, bool bIsSelected,
  1585. SelectionState_t faceSelectionState,
  1586. Color &pColor )
  1587. {
  1588. // Get the current render mode.
  1589. EditorRenderMode_t renderMode = pRender->GetCurrentRenderMode();
  1590. switch ( renderMode )
  1591. {
  1592. case RENDER_MODE_TEXTURED:
  1593. case RENDER_MODE_TEXTURED_SHADED:
  1594. case RENDER_MODE_LIGHT_PREVIEW2:
  1595. case RENDER_MODE_LIGHT_PREVIEW_RAYTRACED:
  1596. {
  1597. break;
  1598. }
  1599. case RENDER_MODE_SELECTION_OVERLAY:
  1600. {
  1601. if ( faceSelectionState == SELECT_MULTI_PARTIAL )
  1602. {
  1603. pColor[2] = 100;
  1604. pColor[3] = 64;
  1605. }
  1606. else if ( ( faceSelectionState == SELECT_NORMAL ) || bIsSelected )
  1607. {
  1608. SelectFaceColor( pColor );
  1609. pColor[3] = 64;
  1610. }
  1611. break;
  1612. }
  1613. case RENDER_MODE_LIGHTMAP_GRID:
  1614. {
  1615. CMapFace *pFace = ( CMapFace* )GetParent();
  1616. if ( bIsSelected )
  1617. {
  1618. SelectFaceColor( pColor );
  1619. }
  1620. else if (pFace->texture.nLightmapScale > DEFAULT_LIGHTMAP_SCALE)
  1621. {
  1622. pColor[0] = 150;
  1623. }
  1624. else if (pFace->texture.nLightmapScale < DEFAULT_LIGHTMAP_SCALE)
  1625. {
  1626. pColor[2] = 100;
  1627. }
  1628. break;
  1629. }
  1630. case RENDER_MODE_TRANSLUCENT_FLAT:
  1631. case RENDER_MODE_FLAT:
  1632. {
  1633. if ( bIsSelected )
  1634. {
  1635. SelectFaceColor( pColor );
  1636. }
  1637. break;
  1638. }
  1639. case RENDER_MODE_WIREFRAME:
  1640. {
  1641. if ( bIsSelected )
  1642. {
  1643. SelectEdgeColor( pColor );
  1644. }
  1645. break;
  1646. }
  1647. case RENDER_MODE_SMOOTHING_GROUP:
  1648. {
  1649. // Render the non-smoothing group faces in white, yellow for the others.
  1650. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  1651. if ( pDoc )
  1652. {
  1653. CMapFace *pFace = ( CMapFace* )GetParent();
  1654. int iGroup = pDoc->GetSmoothingGroupVisual();
  1655. if ( pFace->InSmoothingGroup( iGroup ) )
  1656. {
  1657. pColor[2] = 0;
  1658. }
  1659. }
  1660. break;
  1661. }
  1662. default:
  1663. {
  1664. assert( 0 );
  1665. break;
  1666. }
  1667. }
  1668. }
  1669. void CMapDisp::Render2D(CRender2D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  1670. {
  1671. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  1672. pRender->DrawDisplacement( &m_CoreDispInfo );
  1673. pRender->PopRenderMode();
  1674. }
  1675. void CMapDisp::AddShadowingTriangles( CUtlVector<Vector> &tri_list )
  1676. {
  1677. // add lighting preview triangles
  1678. CoreDispVert_t *pVert = m_CoreDispInfo.GetDispVertList();
  1679. unsigned short *pIndex = m_CoreDispInfo.GetRenderIndexList();
  1680. int numIndices = m_CoreDispInfo.GetRenderIndexCount();
  1681. for ( int i = 0; i < numIndices; i += 3 )
  1682. {
  1683. for( int v = 0; v < 3; v++ )
  1684. tri_list.AddToTail( pVert[pIndex[i+v]].m_Vert );
  1685. }
  1686. }
  1687. //-----------------------------------------------------------------------------
  1688. // NOTE: most of the rendering mode is set in the parent face render call!!!
  1689. //-----------------------------------------------------------------------------
  1690. void CMapDisp::Render3D( CRender3D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  1691. {
  1692. // Get the current rendermode.
  1693. EditorRenderMode_t renderMode = pRender->GetCurrentRenderMode();
  1694. if ( renderMode == RENDER_MODE_SELECTION_OVERLAY )
  1695. {
  1696. RenderOverlaySurface( pRender, bIsSelected, faceSelectionState );
  1697. }
  1698. else
  1699. {
  1700. RenderSurface( pRender, bIsSelected, faceSelectionState );
  1701. // Note: This will cause the wireframe to render twice in selection due to
  1702. // the multiplass operations at the solid and face levels (the render
  1703. // portion of the hammer code needs to be reworked there).
  1704. if ( renderMode != RENDER_MODE_WIREFRAME && bIsSelected )
  1705. {
  1706. // This renders wireframe twice in selection!
  1707. RenderWireframeSurface( pRender, bIsSelected, faceSelectionState );
  1708. }
  1709. }
  1710. // Note: the rendermode == textured is so that this only gets rendered
  1711. // once per frame.
  1712. bool bDispWalkableMode = CMapDoc::GetActiveMapDoc()->IsDispDrawWalkable();
  1713. if ( bDispWalkableMode && RenderingModeIsTextured(renderMode))
  1714. {
  1715. RenderWalkableSurface( pRender, bIsSelected, faceSelectionState );
  1716. }
  1717. // Note: the rendermode == textured is so that this only gets rendered
  1718. // once per frame.
  1719. bool bDispBuildableMode = CMapDoc::GetActiveMapDoc()->IsDispDrawBuildable();
  1720. if ( bDispBuildableMode && RenderingModeIsTextured( renderMode ))
  1721. {
  1722. RenderBuildableSurface( pRender, bIsSelected, faceSelectionState );
  1723. }
  1724. // Note: the rendermode == textured is so that this only gets rendered
  1725. // once per frame.
  1726. bool bDispRemoveMode = CMapDoc::GetActiveMapDoc()->IsDispDrawRemove();
  1727. if ( bDispRemoveMode && RenderingModeIsTextured( renderMode ))
  1728. {
  1729. RenderRemoveSurface( pRender, bIsSelected, faceSelectionState );
  1730. }
  1731. bool bDispRemovedVertMode = CMapDoc::GetActiveMapDoc()->IsDispDrawRemovedVerts();
  1732. if ( bDispRemovedVertMode && RenderingModeIsTextured( renderMode ) )
  1733. {
  1734. RenderDisAllowedVerts( pRender );
  1735. }
  1736. // Render debug information.
  1737. // Render3DDebug( pRender, bIsSelected );
  1738. }
  1739. //-----------------------------------------------------------------------------
  1740. // Purpose: Render the displacement surface.
  1741. //-----------------------------------------------------------------------------
  1742. void CMapDisp::RenderOverlaySurface( CRender3D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  1743. {
  1744. if ( HasSelectMask() )
  1745. return;
  1746. Color color( 255, 255, 255, 255 );
  1747. CalcColor( pRender, bIsSelected, faceSelectionState, color );
  1748. int nVertCount = m_CoreDispInfo.GetSize();
  1749. int nIndexCount = m_CoreDispInfo.GetRenderIndexCount();
  1750. CMeshBuilder meshBuilder;
  1751. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1752. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1753. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertCount, nIndexCount );
  1754. CoreDispVert_t *pVert = m_CoreDispInfo.GetDispVertList();
  1755. for (int i = 0; i < nVertCount; ++i )
  1756. {
  1757. meshBuilder.Position3fv( pVert[i].m_Vert.Base() );
  1758. meshBuilder.Color4ub( color[0], color[1], color[2], color[3] );
  1759. meshBuilder.Normal3fv( pVert[i].m_Normal.Base() );
  1760. meshBuilder.AdvanceVertex();
  1761. }
  1762. unsigned short *pIndex = m_CoreDispInfo.GetRenderIndexList();
  1763. for ( int i = 0; i < nIndexCount; ++i )
  1764. {
  1765. meshBuilder.Index( pIndex[i] );
  1766. meshBuilder.AdvanceIndex();
  1767. }
  1768. meshBuilder.End();
  1769. pMesh->Draw();
  1770. }
  1771. //-----------------------------------------------------------------------------
  1772. // Purpose: Render the displacement surface with a vertex alpha (blending).
  1773. //-----------------------------------------------------------------------------
  1774. void CMapDisp::RenderSurface( CRender3D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  1775. {
  1776. Color color( 255, 255, 255, 255 );
  1777. CalcColor( pRender, bIsSelected, faceSelectionState, color );
  1778. int numVerts = m_CoreDispInfo.GetSize();
  1779. int numIndices = m_CoreDispInfo.GetRenderIndexCount();
  1780. CMeshBuilder meshBuilder;
  1781. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1782. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1783. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numVerts, numIndices );
  1784. CoreDispVert_t *pVert = m_CoreDispInfo.GetDispVertList();
  1785. for (int i = 0; i < numVerts; ++i )
  1786. {
  1787. meshBuilder.Position3fv( pVert[i].m_Vert.Base() );
  1788. meshBuilder.Color4ub( color[0], color[1], color[2], 255 - ( unsigned char )( pVert[i].m_Alpha ) );
  1789. meshBuilder.Normal3fv( pVert[i].m_Normal.Base() );
  1790. meshBuilder.TangentS3fv( pVert[i].m_TangentS.Base() );
  1791. meshBuilder.TangentT3fv( pVert[i].m_TangentT.Base() );
  1792. meshBuilder.TexCoord2fv( 0, pVert[i].m_TexCoord.Base() );
  1793. meshBuilder.TexCoord2fv( 1, pVert[i].m_LuxelCoords[0].Base() );
  1794. meshBuilder.AdvanceVertex();
  1795. }
  1796. unsigned short *pIndex = m_CoreDispInfo.GetRenderIndexList();
  1797. int nTriCount = numIndices / 3;
  1798. for ( int nTri = 0; nTri < nTriCount; ++nTri )
  1799. {
  1800. if ( !IsTriRemove( nTri ) )
  1801. {
  1802. int nIndex = nTri * 3;
  1803. meshBuilder.Index( pIndex[nIndex] );
  1804. meshBuilder.AdvanceIndex();
  1805. meshBuilder.Index( pIndex[nIndex+1] );
  1806. meshBuilder.AdvanceIndex();
  1807. meshBuilder.Index( pIndex[nIndex+2] );
  1808. meshBuilder.AdvanceIndex();
  1809. }
  1810. }
  1811. meshBuilder.End();
  1812. pMesh->Draw();
  1813. }
  1814. //-----------------------------------------------------------------------------
  1815. // Purpose: Render the displacement surface with walkable data.
  1816. //-----------------------------------------------------------------------------
  1817. void CMapDisp::RenderWalkableSurface( CRender3D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  1818. {
  1819. // Normal
  1820. for ( int iPass = 0; iPass < 2; ++iPass )
  1821. {
  1822. Color color;
  1823. if ( iPass == 0 )
  1824. {
  1825. pRender->PushRenderMode( RENDER_MODE_TRANSLUCENT_FLAT );
  1826. color.SetColor( 255, 255, 0, 64 );
  1827. CalcColor( pRender, false, faceSelectionState, color );
  1828. }
  1829. else
  1830. {
  1831. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  1832. color.SetColor( 255, 255, 0, 255 );
  1833. CalcColor( pRender, false, faceSelectionState, color );
  1834. }
  1835. int nVertCount = m_aWalkableVerts.Count();
  1836. int nIndexCount = m_aWalkableIndices.Count();
  1837. CMeshBuilder meshBuilder;
  1838. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1839. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1840. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertCount, nIndexCount );
  1841. CoreDispVert_t **ppVerts = m_aWalkableVerts.Base();
  1842. for (int i = 0; i < nVertCount; ++i )
  1843. {
  1844. CoreDispVert_t *pVert = ppVerts[i];
  1845. meshBuilder.Position3fv( pVert->m_Vert.Base() );
  1846. meshBuilder.Color4ub( color[0], color[1], color[2], color[3] );
  1847. meshBuilder.Normal3fv( pVert->m_Normal.Base() );
  1848. meshBuilder.AdvanceVertex();
  1849. }
  1850. unsigned short *pIndex = m_aWalkableIndices.Base();
  1851. for ( int i = 0; i < nIndexCount; ++i )
  1852. {
  1853. meshBuilder.Index( pIndex[i] );
  1854. meshBuilder.AdvanceIndex();
  1855. }
  1856. meshBuilder.End();
  1857. pMesh->Draw();
  1858. pRender->PopRenderMode();
  1859. }
  1860. // Forced
  1861. for ( int iPass = 0; iPass < 2; ++iPass )
  1862. {
  1863. Color color;
  1864. if ( iPass == 0 )
  1865. {
  1866. pRender->PushRenderMode( RENDER_MODE_TRANSLUCENT_FLAT );
  1867. color.SetColor( 0, 255, 0, 64 );
  1868. CalcColor( pRender, false, faceSelectionState, color );
  1869. }
  1870. else
  1871. {
  1872. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  1873. color.SetColor( 0, 255, 0, 255 );
  1874. CalcColor( pRender, false, faceSelectionState, color );
  1875. }
  1876. int nVertCount = m_aWalkableVerts.Count();
  1877. int nIndexCount = m_aForcedWalkableIndices.Count();
  1878. CMeshBuilder meshBuilder;
  1879. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1880. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1881. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertCount, nIndexCount );
  1882. CoreDispVert_t **ppVerts = m_aWalkableVerts.Base();
  1883. for (int i = 0; i < nVertCount; ++i )
  1884. {
  1885. CoreDispVert_t *pVert = ppVerts[i];
  1886. meshBuilder.Position3fv( pVert->m_Vert.Base() );
  1887. meshBuilder.Color4ub( color[0], color[1], color[2], color[3] );
  1888. meshBuilder.Normal3fv( pVert->m_Normal.Base() );
  1889. meshBuilder.AdvanceVertex();
  1890. }
  1891. unsigned short *pIndex = m_aForcedWalkableIndices.Base();
  1892. for ( int i = 0; i < nIndexCount; ++i )
  1893. {
  1894. meshBuilder.Index( pIndex[i] );
  1895. meshBuilder.AdvanceIndex();
  1896. }
  1897. meshBuilder.End();
  1898. pMesh->Draw();
  1899. pRender->PopRenderMode();
  1900. }
  1901. }
  1902. //-----------------------------------------------------------------------------
  1903. // Purpose: Render the displacement surface with buildable data.
  1904. //-----------------------------------------------------------------------------
  1905. void CMapDisp::RenderBuildableSurface( CRender3D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  1906. {
  1907. // Normal
  1908. for ( int iPass = 0; iPass < 2; ++iPass )
  1909. {
  1910. Color color;
  1911. if ( iPass == 0 )
  1912. {
  1913. pRender->PushRenderMode( RENDER_MODE_TRANSLUCENT_FLAT );
  1914. color.SetColor( 255, 100, 25, 64 );
  1915. CalcColor( pRender, false, faceSelectionState, color );
  1916. }
  1917. else
  1918. {
  1919. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  1920. color.SetColor( 255, 255, 0, 255 );
  1921. CalcColor( pRender, false, faceSelectionState, color );
  1922. }
  1923. int nVertCount = m_aBuildableVerts.Count();
  1924. int nIndexCount = m_aBuildableIndices.Count();
  1925. CMeshBuilder meshBuilder;
  1926. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1927. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1928. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertCount, nIndexCount );
  1929. CoreDispVert_t **ppVerts = m_aBuildableVerts.Base();
  1930. for (int i = 0; i < nVertCount; ++i )
  1931. {
  1932. CoreDispVert_t *pVert = ppVerts[i];
  1933. meshBuilder.Position3fv( pVert->m_Vert.Base() );
  1934. meshBuilder.Color4ub( color[0], color[1], color[2], color[3] );
  1935. meshBuilder.Normal3fv( pVert->m_Normal.Base() );
  1936. meshBuilder.AdvanceVertex();
  1937. }
  1938. unsigned short *pIndex = m_aBuildableIndices.Base();
  1939. for ( int i = 0; i < nIndexCount; ++i )
  1940. {
  1941. meshBuilder.Index( pIndex[i] );
  1942. meshBuilder.AdvanceIndex();
  1943. }
  1944. meshBuilder.End();
  1945. pMesh->Draw();
  1946. pRender->PopRenderMode();
  1947. }
  1948. // Forced
  1949. for ( int iPass = 0; iPass < 2; ++iPass )
  1950. {
  1951. Color color;
  1952. if ( iPass == 0 )
  1953. {
  1954. pRender->PushRenderMode( RENDER_MODE_TRANSLUCENT_FLAT );
  1955. color.SetColor( 0, 0, 255, 64 );
  1956. CalcColor( pRender, false, faceSelectionState, color );
  1957. }
  1958. else
  1959. {
  1960. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  1961. color.SetColor( 0, 0, 255, 255 );
  1962. CalcColor( pRender, false, faceSelectionState, color );
  1963. }
  1964. int nVertCount = m_aBuildableVerts.Count();
  1965. int nIndexCount = m_aForcedBuildableIndices.Count();
  1966. CMeshBuilder meshBuilder;
  1967. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  1968. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  1969. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertCount, nIndexCount );
  1970. CoreDispVert_t **ppVerts = m_aBuildableVerts.Base();
  1971. for (int i = 0; i < nVertCount; ++i )
  1972. {
  1973. CoreDispVert_t *pVert = ppVerts[i];
  1974. meshBuilder.Position3fv( pVert->m_Vert.Base() );
  1975. meshBuilder.Color4ub( color[0], color[1], color[2], color[3] );
  1976. meshBuilder.Normal3fv( pVert->m_Normal.Base() );
  1977. meshBuilder.AdvanceVertex();
  1978. }
  1979. unsigned short *pIndex = m_aForcedBuildableIndices.Base();
  1980. for ( int i = 0; i < nIndexCount; ++i )
  1981. {
  1982. meshBuilder.Index( pIndex[i] );
  1983. meshBuilder.AdvanceIndex();
  1984. }
  1985. meshBuilder.End();
  1986. pMesh->Draw();
  1987. pRender->PopRenderMode();
  1988. }
  1989. }
  1990. //-----------------------------------------------------------------------------
  1991. // Purpose: Render the displacement surface removed faces.
  1992. //-----------------------------------------------------------------------------
  1993. void CMapDisp::RenderRemoveSurface( CRender3D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  1994. {
  1995. // Remove Faces
  1996. for ( int iPass = 0; iPass < 2; ++iPass )
  1997. {
  1998. Color color;
  1999. if ( iPass == 0 )
  2000. {
  2001. pRender->PushRenderMode( RENDER_MODE_TRANSLUCENT_FLAT );
  2002. color.SetColor( 0, 0, 255, 64 );
  2003. CalcColor( pRender, false, faceSelectionState, color );
  2004. }
  2005. else
  2006. {
  2007. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  2008. color.SetColor( 0, 0, 255, 255 );
  2009. CalcColor( pRender, false, faceSelectionState, color );
  2010. }
  2011. int nVertCount = m_aRemoveVerts.Count();
  2012. int nIndexCount = m_aRemoveIndices.Count();
  2013. CMeshBuilder meshBuilder;
  2014. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  2015. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  2016. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nVertCount, nIndexCount );
  2017. CoreDispVert_t **ppVerts = m_aRemoveVerts.Base();
  2018. for (int i = 0; i < nVertCount; ++i )
  2019. {
  2020. CoreDispVert_t *pVert = ppVerts[i];
  2021. meshBuilder.Position3fv( pVert->m_Vert.Base() );
  2022. meshBuilder.Color4ub( color[0], color[1], color[2], color[3] );
  2023. meshBuilder.Normal3fv( pVert->m_Normal.Base() );
  2024. meshBuilder.AdvanceVertex();
  2025. }
  2026. unsigned short *pIndex = m_aRemoveIndices.Base();
  2027. for ( int i = 0; i < nIndexCount; ++i )
  2028. {
  2029. meshBuilder.Index( pIndex[i] );
  2030. meshBuilder.AdvanceIndex();
  2031. }
  2032. meshBuilder.End();
  2033. pMesh->Draw();
  2034. pRender->PopRenderMode();
  2035. }
  2036. }
  2037. //-----------------------------------------------------------------------------
  2038. // Purpose: Render the white wireframe overlay.
  2039. //-----------------------------------------------------------------------------
  2040. void CMapDisp::RenderWireframeSurface( CRender3D *pRender, bool bIsSelected, SelectionState_t faceSelectionState )
  2041. {
  2042. if ( HasGridMask() )
  2043. return;
  2044. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  2045. Color color( 255, 255, 255, 255 );
  2046. CalcColor( pRender, bIsSelected, faceSelectionState, color );
  2047. int numVerts = m_CoreDispInfo.GetSize();
  2048. int numIndices = m_CoreDispInfo.GetRenderIndexCount();
  2049. CMeshBuilder meshBuilder;
  2050. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  2051. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  2052. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numVerts, numIndices );
  2053. CoreDispVert_t *pVert = m_CoreDispInfo.GetDispVertList();
  2054. for (int i = 0; i < numVerts; ++i )
  2055. {
  2056. meshBuilder.Position3fv( pVert[i].m_Vert.Base() );
  2057. meshBuilder.Color3ub( 255, 255, 255 );
  2058. meshBuilder.TexCoord2fv( 0, pVert[i].m_TexCoord.Base() );
  2059. meshBuilder.TexCoord2fv( 1, pVert[i].m_LuxelCoords[0].Base() );
  2060. meshBuilder.AdvanceVertex();
  2061. }
  2062. unsigned short *pIndex = m_CoreDispInfo.GetRenderIndexList();
  2063. for ( int i = 0; i < numIndices; ++i )
  2064. {
  2065. meshBuilder.Index( pIndex[i] );
  2066. meshBuilder.AdvanceIndex();
  2067. }
  2068. meshBuilder.End();
  2069. pMesh->Draw();
  2070. // Reset the render mode.
  2071. pRender->PopRenderMode();
  2072. }
  2073. //-----------------------------------------------------------------------------
  2074. //-----------------------------------------------------------------------------
  2075. void CMapDisp::UpdateNeighborDependencies( bool bDestroy )
  2076. {
  2077. if( !bDestroy )
  2078. {
  2079. // reset and find new neighbors
  2080. ResetNeighbors();
  2081. FindNeighbors();
  2082. }
  2083. else
  2084. {
  2085. //
  2086. // update edge neighbors
  2087. //
  2088. for( int i = 0; i < 4; i++ )
  2089. {
  2090. EditDispHandle_t handle = GetEdgeNeighbor( i );
  2091. if( handle == EDITDISPHANDLE_INVALID )
  2092. continue;
  2093. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  2094. pNeighborDisp->UpdateNeighborDependencies( false );
  2095. }
  2096. //
  2097. // update corner neighbors
  2098. //
  2099. for( int i = 0; i < 4; i++ )
  2100. {
  2101. int cornerCount = GetCornerNeighborCount( i );
  2102. for( int j = 0; j < cornerCount; j++ )
  2103. {
  2104. EditDispHandle_t handle = GetCornerNeighbor( i, j );
  2105. if( handle != EDITDISPHANDLE_INVALID )
  2106. {
  2107. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  2108. pNeighborDisp->UpdateNeighborDependencies( false );
  2109. }
  2110. }
  2111. }
  2112. }
  2113. }
  2114. void CMapDisp::UpdateNeighborsOfDispsIntersectingBox( const Vector &bbMin, const Vector &bbMax, float flPadding )
  2115. {
  2116. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2117. if( !pDispMgr )
  2118. return;
  2119. Vector bbPaddedMin = bbMin - Vector( flPadding, flPadding, flPadding );
  2120. Vector bbPaddedMax = bbMax + Vector( flPadding, flPadding, flPadding );
  2121. int count = pDispMgr->WorldCount();
  2122. for ( int i=0; i < count; i++ )
  2123. {
  2124. CMapDisp *pDisp = pDispMgr->GetFromWorld( i );
  2125. // Do the bbox test.
  2126. Vector testbbmin, testbbmax;
  2127. pDisp->GetBoundingBox( testbbmin, testbbmax );
  2128. if ( QuickBoxIntersectTest( testbbmin, testbbmax, bbPaddedMin, bbPaddedMax ) )
  2129. {
  2130. pDisp->ResetNeighbors();
  2131. pDispMgr->FindWorldNeighbors( pDisp->GetEditHandle() );
  2132. }
  2133. }
  2134. }
  2135. //-----------------------------------------------------------------------------
  2136. //-----------------------------------------------------------------------------
  2137. void CMapDisp::FindNeighbors( void )
  2138. {
  2139. //
  2140. // find the current neighbors to "this" displacement
  2141. //
  2142. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2143. if( !pDispMgr )
  2144. return;
  2145. pDispMgr->FindWorldNeighbors( m_EditHandle );
  2146. //
  2147. // generate the vector field for neighboring surfaces (edges and corners)
  2148. //
  2149. for( int i = 0; i < NUM_EDGES_CORNERS; i++ )
  2150. {
  2151. EditDispHandle_t handle = m_EdgeNeighbors[i];
  2152. if( handle != EDITDISPHANDLE_INVALID )
  2153. {
  2154. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  2155. pNeighborDisp->ResetNeighbors();
  2156. pDispMgr->FindWorldNeighbors( pNeighborDisp->GetEditHandle() );
  2157. }
  2158. int cornerCount = m_CornerNeighborCounts[i];
  2159. if( cornerCount != 0 )
  2160. {
  2161. for( int j = 0; j < cornerCount; j++ )
  2162. {
  2163. handle = m_CornerNeighbors[i][j];
  2164. if( handle != EDITDISPHANDLE_INVALID )
  2165. {
  2166. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  2167. pNeighborDisp->ResetNeighbors();
  2168. pDispMgr->FindWorldNeighbors( pNeighborDisp->GetEditHandle() );
  2169. }
  2170. }
  2171. }
  2172. }
  2173. }
  2174. //-----------------------------------------------------------------------------
  2175. //-----------------------------------------------------------------------------
  2176. void CMapDisp::UpdateBoundingBox( void )
  2177. {
  2178. Vector v;
  2179. VectorFill( m_BBox[0], COORD_NOTINIT );
  2180. VectorFill( m_BBox[1], -COORD_NOTINIT );
  2181. int size = GetSize();
  2182. for( int i = 0; i < size; i++ )
  2183. {
  2184. m_CoreDispInfo.GetVert( i, v );
  2185. if( v[0] < m_BBox[0][0] ) { m_BBox[0][0] = v[0]; }
  2186. if( v[1] < m_BBox[0][1] ) { m_BBox[0][1] = v[1]; }
  2187. if( v[2] < m_BBox[0][2] ) { m_BBox[0][2] = v[2]; }
  2188. if( v[0] > m_BBox[1][0] ) { m_BBox[1][0] = v[0]; }
  2189. if( v[1] > m_BBox[1][1] ) { m_BBox[1][1] = v[1]; }
  2190. if( v[2] > m_BBox[1][2] ) { m_BBox[1][2] = v[2]; }
  2191. }
  2192. }
  2193. //-----------------------------------------------------------------------------
  2194. //-----------------------------------------------------------------------------
  2195. void CMapDisp::Scale( float scale )
  2196. {
  2197. // check for a change in scale
  2198. if( scale == m_Scale )
  2199. return;
  2200. int size = GetSize();
  2201. // scale the surface back to its original state and re-scale with the new
  2202. // value
  2203. if( m_Scale != 1.0f )
  2204. {
  2205. float adj = 1.0f / m_Scale;
  2206. for( int i = 0; i < size; i++ )
  2207. {
  2208. // scale the vector field distance
  2209. float dist = GetFieldDistance( i );
  2210. dist *= adj;
  2211. SetFieldDistance( i, dist );
  2212. // scale the subdivision pos
  2213. Vector vPos;
  2214. GetSubdivPosition( i, vPos );
  2215. vPos *= adj;
  2216. SetSubdivPosition( i, vPos );
  2217. }
  2218. }
  2219. for( int i = 0; i < size; i++ )
  2220. {
  2221. // scale the vector field distance
  2222. float dist = GetFieldDistance( i );
  2223. dist *= scale;
  2224. SetFieldDistance( i, dist );
  2225. // scale the subdivision pos
  2226. Vector vPos;
  2227. GetSubdivPosition( i, vPos );
  2228. vPos *= scale;
  2229. SetSubdivPosition( i, vPos );
  2230. }
  2231. m_Scale = scale;
  2232. UpdateData();
  2233. }
  2234. //-----------------------------------------------------------------------------
  2235. //-----------------------------------------------------------------------------
  2236. void CMapDisp::ApplyNoise( float min, float max, float rockiness )
  2237. {
  2238. if( min == max )
  2239. return;
  2240. // initialize the paint data
  2241. Paint_Init( DISPPAINT_CHANNEL_POSITION );
  2242. //
  2243. // clamp rockiness value between 0.0 and 1.0
  2244. //
  2245. if( rockiness < 0.0f ) { rockiness = 0.0f; }
  2246. if( rockiness > 1.0f ) { rockiness = 1.0f; }
  2247. float delta = max - min;
  2248. float deltaBy2 = delta / 2.0f;
  2249. int size = GetSize();
  2250. for( int i = 0; i < size; i++ )
  2251. {
  2252. //
  2253. // get a noise value based on the points position
  2254. //
  2255. Vector v;
  2256. GetVert( i, v );
  2257. float noiseX = v.x + v.z;
  2258. float noiseY = v.y + v.z;
  2259. float noise = PerlinNoise2D( noiseX, noiseY, rockiness );
  2260. //
  2261. // clamp noise (can go a little higher and lower due to precision)
  2262. //
  2263. if( noise < -1.0f ) { noise = -1.0f; }
  2264. if( noise > 1.0f ) { noise = 1.0f; }
  2265. noise *= deltaBy2;
  2266. noise += ( deltaBy2 + min );
  2267. // apply noise to the subdivision normal direction
  2268. Vector vNoise;
  2269. GetFieldVector( i, vNoise );
  2270. if( ( vNoise.x == 0 ) && ( vNoise.y == 0 ) && ( vNoise.z == 0 ) )
  2271. {
  2272. GetSubdivNormal( i, vNoise );
  2273. }
  2274. vNoise *= noise;
  2275. vNoise += v;
  2276. // set the paint value
  2277. Paint_SetValue( i, vNoise );
  2278. }
  2279. Paint_Update( false );
  2280. }
  2281. //=============================================================================
  2282. //
  2283. // Load/Save Functions
  2284. //
  2285. //-----------------------------------------------------------------------------
  2286. //-----------------------------------------------------------------------------
  2287. void CMapDisp::PostLoad( void )
  2288. {
  2289. Vector v;
  2290. //
  2291. // check the subdivision normals -- clean them up (old files)
  2292. //
  2293. bool bUpdateSubdivNormals = false;
  2294. int size = GetSize();
  2295. for( int i = 0; i < size; i++ )
  2296. {
  2297. GetSubdivNormal( i, v );
  2298. if( ( v.x == 0.0f ) && ( v.y == 0.0f ) && ( v.z == 0.0f ) )
  2299. {
  2300. bUpdateSubdivNormals = true;
  2301. break;
  2302. }
  2303. }
  2304. if( bUpdateSubdivNormals )
  2305. {
  2306. Vector vNormal;
  2307. GetSurfNormal( vNormal );
  2308. for( int i = 0; i < size; i++ )
  2309. {
  2310. SetSubdivNormal( i, vNormal );
  2311. }
  2312. }
  2313. }
  2314. //-----------------------------------------------------------------------------
  2315. // Purpose:
  2316. // Input : *pFile -
  2317. // *pDisp -
  2318. // Output : ChunkFileResult_t
  2319. //-----------------------------------------------------------------------------
  2320. ChunkFileResult_t CMapDisp::LoadDispDistancesCallback(CChunkFile *pFile, CMapDisp *pDisp)
  2321. {
  2322. return(pFile->ReadChunk((KeyHandler_t)LoadDispDistancesKeyCallback, pDisp));
  2323. }
  2324. //-----------------------------------------------------------------------------
  2325. // Purpose:
  2326. // Input : szKey -
  2327. // szValue -
  2328. // pDisp -
  2329. // Output : ChunkFileResult_t
  2330. //-----------------------------------------------------------------------------
  2331. ChunkFileResult_t CMapDisp::LoadDispDistancesKeyCallback(const char *szKey, const char *szValue, CMapDisp *pDisp)
  2332. {
  2333. float dispDistance;
  2334. if (!strnicmp(szKey, "row", 3))
  2335. {
  2336. char szBuf[MAX_KEYVALUE_LEN];
  2337. strcpy(szBuf, szValue);
  2338. int nCols = (1 << pDisp->GetPower()) + 1;
  2339. int nRow = atoi(&szKey[3]);
  2340. char *pszNext = strtok(szBuf, " ");
  2341. int nIndex = nRow * nCols;
  2342. while (pszNext != NULL)
  2343. {
  2344. dispDistance = (float)atof(pszNext);
  2345. pDisp->m_CoreDispInfo.SetFieldDistance( nIndex, dispDistance );
  2346. pszNext = strtok(NULL, " ");
  2347. nIndex++;
  2348. }
  2349. }
  2350. return(ChunkFile_Ok);
  2351. }
  2352. //-----------------------------------------------------------------------------
  2353. // Purpose:
  2354. // Input : *pFile -
  2355. // *pDisp -
  2356. // Output : ChunkFileResult_t
  2357. //-----------------------------------------------------------------------------
  2358. ChunkFileResult_t CMapDisp::LoadDispOffsetsCallback(CChunkFile *pFile, CMapDisp *pDisp)
  2359. {
  2360. return(pFile->ReadChunk((KeyHandler_t)LoadDispOffsetsKeyCallback, pDisp));
  2361. }
  2362. //-----------------------------------------------------------------------------
  2363. // Purpose:
  2364. // Input : szKey -
  2365. // szValue -
  2366. // pDisp -
  2367. // Output : ChunkFileResult_t
  2368. //-----------------------------------------------------------------------------
  2369. ChunkFileResult_t CMapDisp::LoadDispOffsetsKeyCallback(const char *szKey, const char *szValue, CMapDisp *pDisp)
  2370. {
  2371. Vector subdivVector;
  2372. if( !strnicmp( szKey, "row", 3 ) )
  2373. {
  2374. char szBuf[MAX_KEYVALUE_LEN];
  2375. strcpy( szBuf, szValue );
  2376. int nCols = ( 1 << pDisp->GetPower() ) + 1;
  2377. int nRow = atoi( &szKey[3] );
  2378. char *pszNext0 = strtok( szBuf, " " );
  2379. char *pszNext1 = strtok( NULL, " " );
  2380. char *pszNext2 = strtok( NULL, " " );
  2381. int nIndex = nRow * nCols;
  2382. while( ( pszNext0 != NULL ) && ( pszNext1 != NULL ) && ( pszNext2 != NULL ) )
  2383. {
  2384. subdivVector[0] = ( float )atof( pszNext0 );
  2385. subdivVector[1] = ( float )atof( pszNext1 );
  2386. subdivVector[2] = ( float )atof( pszNext2 );
  2387. pDisp->m_CoreDispInfo.SetSubdivPosition( nIndex, subdivVector );
  2388. pszNext0 = strtok( NULL, " " );
  2389. pszNext1 = strtok( NULL, " " );
  2390. pszNext2 = strtok( NULL, " " );
  2391. nIndex++;
  2392. }
  2393. }
  2394. return( ChunkFile_Ok );
  2395. }
  2396. //-----------------------------------------------------------------------------
  2397. // Purpose:
  2398. // Input : *pFile -
  2399. // *pDisp -
  2400. // Output : ChunkFileResult_t
  2401. //-----------------------------------------------------------------------------
  2402. ChunkFileResult_t CMapDisp::LoadDispOffsetNormalsCallback(CChunkFile *pFile, CMapDisp *pDisp)
  2403. {
  2404. return(pFile->ReadChunk((KeyHandler_t)LoadDispOffsetNormalsKeyCallback, pDisp ));
  2405. }
  2406. //-----------------------------------------------------------------------------
  2407. // Purpose:
  2408. // Input : szKey -
  2409. // szValue -
  2410. // pDisp -
  2411. // Output : ChunkFileResult_t
  2412. //-----------------------------------------------------------------------------
  2413. ChunkFileResult_t CMapDisp::LoadDispOffsetNormalsKeyCallback(const char *szKey, const char *szValue,
  2414. CMapDisp *pDisp)
  2415. {
  2416. Vector normalVector;
  2417. if( !strnicmp( szKey, "row", 3 ) )
  2418. {
  2419. char szBuf[MAX_KEYVALUE_LEN];
  2420. strcpy( szBuf, szValue );
  2421. int nCols = ( 1 << pDisp->GetPower() ) + 1;
  2422. int nRow = atoi( &szKey[3] );
  2423. char *pszNext0 = strtok( szBuf, " " );
  2424. char *pszNext1 = strtok( NULL, " " );
  2425. char *pszNext2 = strtok( NULL, " " );
  2426. int nIndex = nRow * nCols;
  2427. while( ( pszNext0 != NULL ) && ( pszNext1 != NULL ) && ( pszNext2 != NULL ) )
  2428. {
  2429. normalVector[0] = ( float )atof( pszNext0 );
  2430. normalVector[1] = ( float )atof( pszNext1 );
  2431. normalVector[2] = ( float )atof( pszNext2 );
  2432. pDisp->m_CoreDispInfo.SetSubdivNormal( nIndex, normalVector );
  2433. pszNext0 = strtok( NULL, " " );
  2434. pszNext1 = strtok( NULL, " " );
  2435. pszNext2 = strtok( NULL, " " );
  2436. nIndex++;
  2437. }
  2438. }
  2439. return( ChunkFile_Ok );
  2440. }
  2441. //-----------------------------------------------------------------------------
  2442. // Purpose:
  2443. // Input : szKey -
  2444. // szValue -
  2445. // pWorld -
  2446. // Output :
  2447. //-----------------------------------------------------------------------------
  2448. ChunkFileResult_t CMapDisp::LoadDispKeyCallback(const char *szKey, const char *szValue, CMapDisp *pDisp)
  2449. {
  2450. if (!stricmp(szKey, "power"))
  2451. {
  2452. int power;
  2453. CChunkFile::ReadKeyValueInt( szValue, power );
  2454. pDisp->SetPower( power );
  2455. }
  2456. else if (!stricmp(szKey, "uaxis"))
  2457. {
  2458. Vector mapAxis;
  2459. CChunkFile::ReadKeyValueVector3( szValue, mapAxis );
  2460. pDisp->SetHasMappingAxes( true );
  2461. pDisp->m_MapAxes[0] = mapAxis;
  2462. }
  2463. else if (!stricmp(szKey, "vaxis"))
  2464. {
  2465. Vector mapAxis;
  2466. CChunkFile::ReadKeyValueVector3( szValue, mapAxis );
  2467. pDisp->SetHasMappingAxes( true );
  2468. pDisp->m_MapAxes[1] = mapAxis;
  2469. }
  2470. else if( !stricmp( szKey, "startposition" ) )
  2471. {
  2472. Vector startPosition;
  2473. CChunkFile::ReadKeyValueVector3( szValue, startPosition );
  2474. CCoreDispSurface *pSurf = pDisp->m_CoreDispInfo.GetSurface();
  2475. pSurf->SetPointStart( startPosition );
  2476. }
  2477. else if (!stricmp(szKey, "flags"))
  2478. {
  2479. int nFlags;
  2480. CChunkFile::ReadKeyValueInt( szValue, nFlags );
  2481. pDisp->SetFlags( nFlags );
  2482. }
  2483. #if 0
  2484. else if (!stricmp(szKey, "mintess"))
  2485. {
  2486. int minTess;
  2487. CChunkFile::ReadKeyValueInt( szValue, minTess );
  2488. pDisp->SetMinTess( minTess );
  2489. }
  2490. else if (!stricmp(szKey, "smooth"))
  2491. {
  2492. float smoothingAngle;
  2493. CChunkFile::ReadKeyValueFloat( szValue, smoothingAngle );
  2494. pDisp->SetSmoothingAngle( smoothingAngle );
  2495. }
  2496. else if( !stricmp( szKey, "alpha" ) )
  2497. {
  2498. Vector4D alphaValues;
  2499. CChunkFile::ReadKeyValueVector4( szValue, alphaValues );
  2500. for( int i = 0; i < 4; i++ )
  2501. {
  2502. pDisp->m_CoreDispInfo.SetSurfPointAlpha( i, alphaValues[i] );
  2503. }
  2504. }
  2505. #endif
  2506. else if( !stricmp( szKey, "elevation" ) )
  2507. {
  2508. float elevation;
  2509. CChunkFile::ReadKeyValueFloat( szValue, elevation );
  2510. pDisp->SetElevation( elevation );
  2511. }
  2512. else if( !stricmp( szKey, "subdiv" ) )
  2513. {
  2514. int bSubdivided;
  2515. CChunkFile::ReadKeyValueInt( szValue, bSubdivided );
  2516. bool bSubdiv = ( bSubdivided != 0 );
  2517. pDisp->SetSubdivided( bSubdiv );
  2518. }
  2519. return(ChunkFile_Ok);
  2520. }
  2521. //-----------------------------------------------------------------------------
  2522. // Purpose:
  2523. // Input : *pFile -
  2524. // *pDisp -
  2525. // Output : ChunkFileResult_t
  2526. //-----------------------------------------------------------------------------
  2527. ChunkFileResult_t CMapDisp::LoadDispAlphasCallback(CChunkFile *pFile, CMapDisp *pDisp)
  2528. {
  2529. return(pFile->ReadChunk((KeyHandler_t)LoadDispAlphasKeyCallback, pDisp));
  2530. }
  2531. //-----------------------------------------------------------------------------
  2532. // Purpose:
  2533. // Input : *pFile -
  2534. // *pDisp -
  2535. // Output : ChunkFileResult_t
  2536. //-----------------------------------------------------------------------------
  2537. ChunkFileResult_t CMapDisp::LoadDispAlphasKeyCallback(const char *szKey, const char *szValue, CMapDisp *pDisp)
  2538. {
  2539. float alpha;
  2540. if (!strnicmp(szKey, "row", 3))
  2541. {
  2542. char szBuf[MAX_KEYVALUE_LEN];
  2543. strcpy(szBuf, szValue);
  2544. int nCols = (1 << pDisp->GetPower()) + 1;
  2545. int nRow = atoi(&szKey[3]);
  2546. char *pszNext = strtok(szBuf, " ");
  2547. int nIndex = nRow * nCols;
  2548. while (pszNext != NULL)
  2549. {
  2550. alpha = (float)atof(pszNext);
  2551. pDisp->m_CoreDispInfo.SetAlpha( nIndex, alpha );
  2552. pszNext = strtok(NULL, " ");
  2553. nIndex++;
  2554. }
  2555. }
  2556. return(ChunkFile_Ok);
  2557. }
  2558. //-----------------------------------------------------------------------------
  2559. //-----------------------------------------------------------------------------
  2560. ChunkFileResult_t CMapDisp::LoadDispTriangleTagsCallback(CChunkFile *pFile, CMapDisp *pDisp)
  2561. {
  2562. return(pFile->ReadChunk((KeyHandler_t)LoadDispTriangleTagsKeyCallback, pDisp));
  2563. }
  2564. //-----------------------------------------------------------------------------
  2565. //-----------------------------------------------------------------------------
  2566. ChunkFileResult_t CMapDisp::LoadDispTriangleTagsKeyCallback(const char *szKey, const char *szValue, CMapDisp *pDisp)
  2567. {
  2568. unsigned short nTriTag;
  2569. if ( !strnicmp( szKey, "row", 3 ) )
  2570. {
  2571. char szBuf[MAX_KEYVALUE_LEN];
  2572. strcpy( szBuf, szValue );
  2573. int nCols = ( 1 << pDisp->GetPower() );
  2574. int nRow = atoi( &szKey[3] );
  2575. char *pszNext = strtok( szBuf, " " );
  2576. int nIndex = nRow * nCols;
  2577. int iTri = nIndex * 2;
  2578. while ( pszNext != NULL )
  2579. {
  2580. nTriTag = ( unsigned int )atoi( pszNext );
  2581. pDisp->m_CoreDispInfo.SetTriTagValue( iTri, nTriTag );
  2582. pszNext = strtok( NULL, " " );
  2583. iTri++;
  2584. }
  2585. }
  2586. return( ChunkFile_Ok );
  2587. }
  2588. //-----------------------------------------------------------------------------
  2589. //-----------------------------------------------------------------------------
  2590. ChunkFileResult_t CMapDisp::LoadDispAllowedVertsCallback( CChunkFile *pFile, CMapDisp *pDisp )
  2591. {
  2592. return( pFile->ReadChunk( ( KeyHandler_t )LoadDispAllowedVertsKeyCallback, pDisp ) );
  2593. }
  2594. //-----------------------------------------------------------------------------
  2595. //-----------------------------------------------------------------------------
  2596. ChunkFileResult_t CMapDisp::LoadDispAllowedVertsKeyCallback( const char *szKey, const char *szValue, CMapDisp *pDisp )
  2597. {
  2598. if ( !strnicmp( szKey, "10", 2 ) )
  2599. {
  2600. char szBuf[MAX_KEYVALUE_LEN];
  2601. strcpy( szBuf, szValue );
  2602. int iValue = 0;
  2603. char *pszNext = strtok( szBuf, " " );
  2604. while ( pszNext != NULL )
  2605. {
  2606. unsigned int nValue = ( unsigned int )atoi( pszNext );
  2607. unsigned long ulValue = ( unsigned long )nValue;
  2608. pDisp->m_CoreDispInfo.AllowedVerts_SetDWord( iValue, ulValue );
  2609. pszNext = strtok( NULL, " " );
  2610. iValue++;
  2611. }
  2612. }
  2613. return( ChunkFile_Ok );
  2614. }
  2615. //-----------------------------------------------------------------------------
  2616. // Purpose:
  2617. // Input : *pFile -
  2618. // *pDisp -
  2619. // Output : ChunkFileResult_t
  2620. //-----------------------------------------------------------------------------
  2621. ChunkFileResult_t CMapDisp::LoadDispNormalsCallback(CChunkFile *pFile, CMapDisp *pDisp)
  2622. {
  2623. return(pFile->ReadChunk((KeyHandler_t)LoadDispNormalsKeyCallback, pDisp));
  2624. }
  2625. //-----------------------------------------------------------------------------
  2626. // Purpose:
  2627. // Input : *szKey -
  2628. // *szValue -
  2629. // *pDisp -
  2630. // Output : ChunkFileResult_t
  2631. //-----------------------------------------------------------------------------
  2632. ChunkFileResult_t CMapDisp::LoadDispNormalsKeyCallback(const char *szKey, const char *szValue, CMapDisp *pDisp)
  2633. {
  2634. Vector vectorFieldVector;
  2635. if (!strnicmp(szKey, "row", 3))
  2636. {
  2637. char szBuf[MAX_KEYVALUE_LEN];
  2638. strcpy(szBuf, szValue);
  2639. int nCols = (1 << pDisp->GetPower()) + 1;
  2640. int nRow = atoi(&szKey[3]);
  2641. char *pszNext0 = strtok(szBuf, " ");
  2642. char *pszNext1 = strtok(NULL, " ");
  2643. char *pszNext2 = strtok(NULL, " ");
  2644. int nIndex = nRow * nCols;
  2645. while ((pszNext0 != NULL) && (pszNext1 != NULL) && (pszNext2 != NULL))
  2646. {
  2647. vectorFieldVector[0] = (float)atof(pszNext0);
  2648. vectorFieldVector[1] = (float)atof(pszNext1);
  2649. vectorFieldVector[2] = (float)atof(pszNext2);
  2650. pDisp->m_CoreDispInfo.SetFieldVector( nIndex, vectorFieldVector );
  2651. pszNext0 = strtok(NULL, " ");
  2652. pszNext1 = strtok(NULL, " ");
  2653. pszNext2 = strtok(NULL, " ");
  2654. nIndex++;
  2655. }
  2656. }
  2657. return(ChunkFile_Ok);
  2658. }
  2659. //-----------------------------------------------------------------------------
  2660. // Purpose:
  2661. // Input : *pFile -
  2662. // Output : ChunkFileResult_t
  2663. //-----------------------------------------------------------------------------
  2664. ChunkFileResult_t CMapDisp::LoadVMF(CChunkFile *pFile)
  2665. {
  2666. //
  2667. // Set up handlers for the subchunks that we are interested in.
  2668. //
  2669. CChunkHandlerMap Handlers;
  2670. Handlers.AddHandler("normals", (ChunkHandler_t)LoadDispNormalsCallback, this);
  2671. Handlers.AddHandler("distances", (ChunkHandler_t)LoadDispDistancesCallback, this);
  2672. Handlers.AddHandler("offsets", (ChunkHandler_t)LoadDispOffsetsCallback, this);
  2673. Handlers.AddHandler("offset_normals", (ChunkHandler_t)LoadDispOffsetNormalsCallback, this);
  2674. Handlers.AddHandler("alphas", (ChunkHandler_t)LoadDispAlphasCallback, this);
  2675. Handlers.AddHandler("triangle_tags", (ChunkHandler_t)LoadDispTriangleTagsCallback, this );
  2676. Handlers.AddHandler("allowed_verts", (ChunkHandler_t)LoadDispAllowedVertsCallback, this );
  2677. pFile->PushHandlers(&Handlers);
  2678. ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadDispKeyCallback, this);
  2679. pFile->PopHandlers();
  2680. return(eResult);
  2681. }
  2682. //-----------------------------------------------------------------------------
  2683. // Purpose: Saves the displacement info into a special chunk in the MAP file.
  2684. // Input : *pFile -
  2685. // Output : ChunkFileResult_t
  2686. //-----------------------------------------------------------------------------
  2687. ChunkFileResult_t CMapDisp::SaveVMF(CChunkFile *pFile, CSaveInfo *pSaveInfo)
  2688. {
  2689. ChunkFileResult_t eResult = pFile->BeginChunk("dispinfo");
  2690. int power = GetPower();
  2691. float elevation = GetElevation();
  2692. int nFlags = GetFlags();
  2693. Vector startPosition;
  2694. CCoreDispSurface *pSurf = m_CoreDispInfo.GetSurface();
  2695. pSurf->GetPoint( 0, startPosition );
  2696. int bSubdivided = ( int )IsSubdivided();
  2697. #if 0 // old
  2698. Vector4D alphaValues;
  2699. for( int i = 0; i < 4; i++ )
  2700. {
  2701. alphaValues[i] = m_CoreDispInfo.GetSurfPointAlpha( i );
  2702. }
  2703. #endif
  2704. if (eResult == ChunkFile_Ok)
  2705. {
  2706. eResult = pFile->WriteKeyValueInt("power", power);
  2707. }
  2708. #if 0 // old
  2709. if (eResult == ChunkFile_Ok)
  2710. {
  2711. eResult = pFile->WriteKeyValueVector3("uaxis", m_BDSurf.uAxis);
  2712. }
  2713. if (eResult == ChunkFile_Ok)
  2714. {
  2715. eResult = pFile->WriteKeyValueVector3("vaxis", m_BDSurf.vAxis);
  2716. }
  2717. #endif
  2718. if( eResult == ChunkFile_Ok )
  2719. {
  2720. eResult = pFile->WriteKeyValueVector3( "startposition", startPosition );
  2721. }
  2722. if (eResult == ChunkFile_Ok)
  2723. {
  2724. eResult = pFile->WriteKeyValueInt("flags", nFlags );
  2725. }
  2726. #if 0
  2727. // old
  2728. if (eResult == ChunkFile_Ok)
  2729. {
  2730. eResult = pFile->WriteKeyValueInt("mintess", minTess);
  2731. }
  2732. if (eResult == ChunkFile_Ok)
  2733. {
  2734. eResult = pFile->WriteKeyValueFloat("smooth", smoothingAngle);
  2735. }
  2736. //
  2737. // save the corner alpha values
  2738. //
  2739. if( eResult == ChunkFile_Ok )
  2740. {
  2741. eResult = pFile->WriteKeyValueVector4( "alpha", alphaValues );
  2742. }
  2743. #endif
  2744. if( eResult == ChunkFile_Ok )
  2745. {
  2746. eResult = pFile->WriteKeyValueFloat( "elevation", elevation );
  2747. }
  2748. if (eResult == ChunkFile_Ok)
  2749. {
  2750. eResult = pFile->WriteKeyValueInt( "subdiv", bSubdivided );
  2751. }
  2752. //
  2753. // Save displacement map normals.
  2754. //
  2755. if (eResult == ChunkFile_Ok)
  2756. {
  2757. Vector vectorFieldVector;
  2758. eResult = pFile->BeginChunk("normals");
  2759. if (eResult == ChunkFile_Ok)
  2760. {
  2761. char szBuf[MAX_KEYVALUE_LEN];
  2762. char szTemp[80];
  2763. int nRows = (1 << power) + 1;;
  2764. int nCols = nRows;
  2765. for (int nRow = 0; nRow < nRows; nRow++)
  2766. {
  2767. bool bFirst = true;
  2768. szBuf[0] = '\0';
  2769. for (int nCol = 0; nCol < nCols; nCol++)
  2770. {
  2771. int nIndex = nRow * nCols + nCol;
  2772. if (!bFirst)
  2773. {
  2774. strcat(szBuf, " ");
  2775. }
  2776. bFirst = false;
  2777. m_CoreDispInfo.GetFieldVector( nIndex, vectorFieldVector );
  2778. sprintf(szTemp, "%g %g %g", (double)vectorFieldVector[0], (double)vectorFieldVector[1], (double)vectorFieldVector[2]);
  2779. strcat(szBuf, szTemp);
  2780. }
  2781. char szKey[10];
  2782. sprintf(szKey, "row%d", nRow);
  2783. eResult = pFile->WriteKeyValue(szKey, szBuf);
  2784. }
  2785. }
  2786. if (eResult == ChunkFile_Ok)
  2787. {
  2788. eResult = pFile->EndChunk();
  2789. }
  2790. }
  2791. //
  2792. // Save displacement map distances.
  2793. //
  2794. if (eResult == ChunkFile_Ok)
  2795. {
  2796. float dispDistance;
  2797. eResult = pFile->BeginChunk("distances");
  2798. if (eResult == ChunkFile_Ok)
  2799. {
  2800. char szBuf[MAX_KEYVALUE_LEN];
  2801. char szTemp[80];
  2802. int nRows = (1 << power) + 1;
  2803. int nCols = nRows;
  2804. for (int nRow = 0; nRow < nRows; nRow++)
  2805. {
  2806. bool bFirst = true;
  2807. szBuf[0] = '\0';
  2808. for (int nCol = 0; nCol < nCols; nCol++)
  2809. {
  2810. int nIndex = nRow * nCols + nCol;
  2811. if (!bFirst)
  2812. {
  2813. strcat(szBuf, " ");
  2814. }
  2815. bFirst = false;
  2816. dispDistance = m_CoreDispInfo.GetFieldDistance( nIndex );
  2817. sprintf(szTemp, "%g", (double)dispDistance);
  2818. strcat(szBuf, szTemp);
  2819. }
  2820. char szKey[10];
  2821. sprintf(szKey, "row%d", nRow);
  2822. eResult = pFile->WriteKeyValue(szKey, szBuf);
  2823. }
  2824. }
  2825. if (eResult == ChunkFile_Ok)
  2826. {
  2827. eResult = pFile->EndChunk();
  2828. }
  2829. }
  2830. //
  2831. // Save displacement map offset.
  2832. //
  2833. if (eResult == ChunkFile_Ok)
  2834. {
  2835. Vector subdivPos;
  2836. eResult = pFile->BeginChunk( "offsets" );
  2837. if( eResult == ChunkFile_Ok )
  2838. {
  2839. char szBuf[MAX_KEYVALUE_LEN];
  2840. char szTemp[80];
  2841. int nRows = (1 << power) + 1;
  2842. int nCols = nRows;
  2843. for (int nRow = 0; nRow < nRows; nRow++)
  2844. {
  2845. bool bFirst = true;
  2846. szBuf[0] = '\0';
  2847. for (int nCol = 0; nCol < nCols; nCol++)
  2848. {
  2849. int nIndex = nRow * nCols + nCol;
  2850. if (!bFirst)
  2851. {
  2852. strcat(szBuf, " ");
  2853. }
  2854. bFirst = false;
  2855. m_CoreDispInfo.GetSubdivPosition( nIndex, subdivPos );
  2856. sprintf(szTemp, "%g %g %g", (double)subdivPos[0], (double)subdivPos[1], (double)subdivPos[2]);
  2857. strcat(szBuf, szTemp);
  2858. }
  2859. char szKey[10];
  2860. sprintf(szKey, "row%d", nRow);
  2861. eResult = pFile->WriteKeyValue(szKey, szBuf);
  2862. }
  2863. }
  2864. if (eResult == ChunkFile_Ok)
  2865. {
  2866. eResult = pFile->EndChunk();
  2867. }
  2868. }
  2869. //
  2870. // Save displacement subdivision normals
  2871. //
  2872. if (eResult == ChunkFile_Ok)
  2873. {
  2874. Vector subdivNormal;
  2875. eResult = pFile->BeginChunk( "offset_normals" );
  2876. if( eResult == ChunkFile_Ok )
  2877. {
  2878. char szBuf[MAX_KEYVALUE_LEN];
  2879. char szTemp[80];
  2880. int nRows = (1 << power) + 1;
  2881. int nCols = nRows;
  2882. for (int nRow = 0; nRow < nRows; nRow++)
  2883. {
  2884. bool bFirst = true;
  2885. szBuf[0] = '\0';
  2886. for (int nCol = 0; nCol < nCols; nCol++)
  2887. {
  2888. int nIndex = nRow * nCols + nCol;
  2889. if (!bFirst)
  2890. {
  2891. strcat(szBuf, " ");
  2892. }
  2893. bFirst = false;
  2894. m_CoreDispInfo.GetSubdivNormal( nIndex, subdivNormal );
  2895. sprintf(szTemp, "%g %g %g", (double)subdivNormal[0], (double)subdivNormal[1], (double)subdivNormal[2]);
  2896. strcat(szBuf, szTemp);
  2897. }
  2898. char szKey[10];
  2899. sprintf(szKey, "row%d", nRow);
  2900. eResult = pFile->WriteKeyValue(szKey, szBuf);
  2901. }
  2902. }
  2903. if (eResult == ChunkFile_Ok)
  2904. {
  2905. eResult = pFile->EndChunk();
  2906. }
  2907. }
  2908. //
  2909. // Save displacement alphas
  2910. //
  2911. if (eResult == ChunkFile_Ok)
  2912. {
  2913. float alpha;
  2914. eResult = pFile->BeginChunk( "alphas" );
  2915. if( eResult == ChunkFile_Ok )
  2916. {
  2917. char szBuf[MAX_KEYVALUE_LEN];
  2918. char szTemp[80];
  2919. int nRows = (1 << power) + 1;
  2920. int nCols = nRows;
  2921. for (int nRow = 0; nRow < nRows; nRow++)
  2922. {
  2923. bool bFirst = true;
  2924. szBuf[0] = '\0';
  2925. for (int nCol = 0; nCol < nCols; nCol++)
  2926. {
  2927. int nIndex = nRow * nCols + nCol;
  2928. if (!bFirst)
  2929. {
  2930. strcat(szBuf, " ");
  2931. }
  2932. bFirst = false;
  2933. alpha = m_CoreDispInfo.GetAlpha( nIndex );
  2934. sprintf(szTemp, "%g", (double)alpha);
  2935. strcat(szBuf, szTemp);
  2936. }
  2937. char szKey[10];
  2938. sprintf(szKey, "row%d", nRow);
  2939. eResult = pFile->WriteKeyValue(szKey, szBuf);
  2940. }
  2941. }
  2942. if (eResult == ChunkFile_Ok)
  2943. {
  2944. eResult = pFile->EndChunk();
  2945. }
  2946. }
  2947. // Save Triangle data.
  2948. if (eResult == ChunkFile_Ok)
  2949. {
  2950. unsigned short nTriTag;
  2951. eResult = pFile->BeginChunk( "triangle_tags" );
  2952. if( eResult == ChunkFile_Ok )
  2953. {
  2954. char szBuf[MAX_KEYVALUE_LEN];
  2955. char szTemp[80];
  2956. int nRows = ( 1 << power ); // ( 1 << power ) + 1 - 1
  2957. int nCols = nRows;
  2958. for ( int iRow = 0; iRow < nRows; ++iRow )
  2959. {
  2960. bool bFirst = true;
  2961. szBuf[0] = '\0';
  2962. for ( int iCol = 0; iCol < nCols; ++iCol )
  2963. {
  2964. int nIndex = iRow * nCols + iCol;
  2965. int iTri = nIndex * 2;
  2966. if ( !bFirst )
  2967. {
  2968. strcat( szBuf, " " );
  2969. }
  2970. bFirst = false;
  2971. nTriTag = m_CoreDispInfo.GetTriTagValue( iTri );
  2972. sprintf( szTemp, "%d", (int)nTriTag );
  2973. strcat( szBuf, szTemp );
  2974. nTriTag = m_CoreDispInfo.GetTriTagValue( iTri + 1 );
  2975. sprintf( szTemp, " %d", (int)nTriTag );
  2976. strcat( szBuf, szTemp );
  2977. }
  2978. char szKey[10];
  2979. sprintf( szKey, "row%d", iRow );
  2980. eResult = pFile->WriteKeyValue( szKey, szBuf );
  2981. }
  2982. }
  2983. if (eResult == ChunkFile_Ok)
  2984. {
  2985. eResult = pFile->EndChunk();
  2986. }
  2987. }
  2988. // Save allowed vert data.
  2989. if ( eResult == ChunkFile_Ok )
  2990. {
  2991. eResult = pFile->BeginChunk( "allowed_verts" );
  2992. if ( eResult == ChunkFile_Ok )
  2993. {
  2994. char szBuf[MAX_KEYVALUE_LEN];
  2995. char szTemp[80];
  2996. szBuf[0] = '\0';
  2997. int nCount = m_CoreDispInfo.AllowedVerts_GetNumDWords();
  2998. for ( int iCount = 0; iCount < nCount; ++iCount )
  2999. {
  3000. if ( iCount != 0 )
  3001. {
  3002. strcat( szBuf, " " );
  3003. }
  3004. unsigned long ulValue = m_CoreDispInfo.AllowedVerts_GetDWord( iCount );
  3005. sprintf( szTemp, "%d", ( int )ulValue );
  3006. strcat( szBuf, szTemp );
  3007. }
  3008. char szKey[8];
  3009. sprintf( szKey, "%d", nCount );
  3010. eResult = pFile->WriteKeyValue( szKey, szBuf );
  3011. }
  3012. if (eResult == ChunkFile_Ok)
  3013. {
  3014. eResult = pFile->EndChunk();
  3015. }
  3016. }
  3017. if (eResult == ChunkFile_Ok)
  3018. {
  3019. eResult = pFile->EndChunk();
  3020. }
  3021. return(eResult);
  3022. }
  3023. //-----------------------------------------------------------------------------
  3024. //-----------------------------------------------------------------------------
  3025. bool CMapDisp::SerializedLoadMAP( std::fstream &file, CMapFace *pFace, UINT version )
  3026. {
  3027. int power;
  3028. float maxData = 1.0f;
  3029. int minTess;
  3030. float smoothingAngle;
  3031. Vector vectorFieldVector;
  3032. float distance;
  3033. //
  3034. // read off the first line -- burn it!!! and get the second
  3035. //
  3036. static char buf[256];
  3037. file.getline( buf, 256 );
  3038. file.getline( buf, 256 );
  3039. if( version < 350 )
  3040. {
  3041. sscanf( buf, "%d [ %f %f %f ] [ %f %f %f ] %f %d %f",
  3042. &power,
  3043. &m_MapAxes[0][0], &m_MapAxes[0][1], &m_MapAxes[0][2],
  3044. &m_MapAxes[1][0], &m_MapAxes[1][1], &m_MapAxes[1][2],
  3045. &maxData,
  3046. &minTess,
  3047. &smoothingAngle );
  3048. }
  3049. else
  3050. {
  3051. sscanf( buf, "%d [ %f %f %f ] [ %f %f %f ] %d %f",
  3052. &power,
  3053. &m_MapAxes[0][0], &m_MapAxes[0][1], &m_MapAxes[0][2],
  3054. &m_MapAxes[1][0], &m_MapAxes[1][1], &m_MapAxes[1][2],
  3055. &minTess,
  3056. &smoothingAngle );
  3057. }
  3058. m_CoreDispInfo.SetPower( power );
  3059. m_bHasMappingAxes = true;
  3060. //
  3061. // displacement normals
  3062. //
  3063. int size = GetSize();
  3064. for( int i = 0; i < size; i++ )
  3065. {
  3066. file >> vectorFieldVector[0];
  3067. file >> vectorFieldVector[1];
  3068. file >> vectorFieldVector[2];
  3069. m_CoreDispInfo.SetFieldVector( i, vectorFieldVector );
  3070. }
  3071. file.getline( buf, 256 );
  3072. //
  3073. // displacement distances
  3074. //
  3075. for( int i = 0; i < size; i++ )
  3076. {
  3077. if( version < 350 )
  3078. {
  3079. file >> distance;
  3080. distance *= maxData;
  3081. }
  3082. else
  3083. {
  3084. file >> distance;
  3085. }
  3086. m_CoreDispInfo.SetFieldDistance( i, distance );
  3087. }
  3088. file.getline( buf, 256 );
  3089. // finish the last bit of the "chunk"
  3090. file.getline( buf, 256 );
  3091. // save the parent info
  3092. SetParent( pFace );
  3093. return true;
  3094. }
  3095. //-----------------------------------------------------------------------------
  3096. //-----------------------------------------------------------------------------
  3097. bool CMapDisp::SerializedLoadRMF( std::fstream &file, CMapFace *pFace, float version )
  3098. {
  3099. int power;
  3100. int minTess;
  3101. float smoothingAngle;
  3102. Vector vectorFieldVectors[MAPDISP_MAX_VERTS];
  3103. float distances[MAPDISP_MAX_VERTS];
  3104. //
  3105. // get displacement information
  3106. //
  3107. file.read( ( char* )&power, sizeof( int ) );
  3108. file.read( ( char* )m_MapAxes[0].Base(), 3 * sizeof( float ) );
  3109. file.read( ( char* )m_MapAxes[1].Base(), 3 * sizeof( float ) );
  3110. file.read( ( char* )&minTess, sizeof( int ) );
  3111. file.read( ( char* )&smoothingAngle, sizeof( float ) );
  3112. m_CoreDispInfo.SetPower( power );
  3113. m_bHasMappingAxes = true;
  3114. //
  3115. // get displacement map normals and distances
  3116. //
  3117. int size = GetSize();
  3118. int i;
  3119. for ( i = 0; i < size; ++i)
  3120. {
  3121. file.read( ( char* )&vectorFieldVectors[i], 3 * sizeof( float ) );
  3122. }
  3123. file.read( ( char* )distances, size * sizeof( float ) );
  3124. for( i = 0; i < size; i++ )
  3125. {
  3126. m_CoreDispInfo.SetFieldVector( i, vectorFieldVectors[i] );
  3127. m_CoreDispInfo.SetFieldDistance( i, distances[i] );
  3128. }
  3129. // set the parent
  3130. SetParent( pFace );
  3131. // displacement info loaded
  3132. return true;
  3133. }
  3134. //-----------------------------------------------------------------------------
  3135. //-----------------------------------------------------------------------------
  3136. int CMapDisp::GetEndIndexFromLevel( int levelIndex )
  3137. {
  3138. switch( levelIndex )
  3139. {
  3140. case 2: { return 20; }
  3141. case 3: { return 84; }
  3142. case 4: { return 340; }
  3143. default: { return 0; }
  3144. }
  3145. }
  3146. //-----------------------------------------------------------------------------
  3147. //-----------------------------------------------------------------------------
  3148. int CMapDisp::GetStartIndexFromLevel( int levelIndex )
  3149. {
  3150. switch( levelIndex )
  3151. {
  3152. case 2: { return 5; }
  3153. case 3: { return 21; }
  3154. case 4: { return 85; }
  3155. default: { return 0; }
  3156. }
  3157. }
  3158. //-----------------------------------------------------------------------------
  3159. //-----------------------------------------------------------------------------
  3160. void CMapDisp::DoTransform(const VMatrix &matrix)
  3161. {
  3162. // get the face
  3163. CCoreDispSurface *pSurf = m_CoreDispInfo.GetSurface();
  3164. CMapFace *pFace = ( CMapFace* )GetParent();
  3165. if( !pFace || !pSurf )
  3166. return;
  3167. Assert( pFace->GetPointCount() == 4 );
  3168. bool bFlip = (matrix[0][0]*matrix[1][1]*matrix[2][2]) < 0;
  3169. if ( bFlip )
  3170. {
  3171. // get the displacement starting point, relative to the newly "flipped" points
  3172. // NOTE: this seems a bit hacky -- if flip goes NUTS later -- look here!!!
  3173. int iStartIndex = pSurf->GetPointStartIndex();
  3174. pSurf->SetPointStartIndex( 3-iStartIndex );
  3175. Flip( FLIP_TRANSPOSE );
  3176. }
  3177. Vector v;
  3178. int size = GetSize();
  3179. for( int i = 0; i < size; i++ )
  3180. {
  3181. GetFieldVector( i, v );
  3182. TransformPoint( matrix, v );
  3183. SetFieldVector( i, v );
  3184. GetSubdivPosition( i, v );
  3185. TransformPoint( matrix, v );
  3186. SetSubdivPosition( i, v );
  3187. GetSubdivNormal( i, v );
  3188. TransformPoint( matrix, v );
  3189. SetSubdivNormal( i, v );
  3190. }
  3191. UpdateSurfData( pFace );
  3192. }
  3193. //-----------------------------------------------------------------------------
  3194. //-----------------------------------------------------------------------------
  3195. bool SphereTriEdgePlanesIntersection( Vector const &ptCenter, float radius, cplane_t *pPlanes )
  3196. {
  3197. // check all planes
  3198. for( int ndxPlane = 0; ndxPlane < 3; ndxPlane++ )
  3199. {
  3200. float dist = pPlanes[ndxPlane].normal.Dot( ptCenter ) - pPlanes[ndxPlane].dist;
  3201. if( dist > radius )
  3202. return false;
  3203. }
  3204. return true;
  3205. }
  3206. //-----------------------------------------------------------------------------
  3207. //-----------------------------------------------------------------------------
  3208. bool CMapDisp::PointSurfIntersection( Vector const &ptCenter, float radius, float &distMin,
  3209. Vector &ptMin )
  3210. {
  3211. // initialize the min data
  3212. distMin = radius;
  3213. ptMin.Init();
  3214. //
  3215. // get the render list size -- created triangles
  3216. //
  3217. unsigned short *pTriList = m_CoreDispInfo.GetRenderIndexList();
  3218. int listSize = m_CoreDispInfo.GetRenderIndexCount();
  3219. for( int i = 0; i < listSize; i += 3 )
  3220. {
  3221. // get the triangle
  3222. Vector v[3];
  3223. GetVert( pTriList[i], v[0] );
  3224. GetVert( pTriList[i+1], v[1] );
  3225. GetVert( pTriList[i+2], v[2] );
  3226. //
  3227. // create a triangle plane
  3228. //
  3229. Vector seg0, seg1;
  3230. seg0 = v[1] - v[0];
  3231. seg1 = v[2] - v[0];
  3232. cplane_t triPlane;
  3233. triPlane.normal = seg1.Cross( seg0 );
  3234. VectorNormalize( triPlane.normal );
  3235. triPlane.dist = triPlane.normal.Dot( v[0] );
  3236. //
  3237. // plane sphere intersection
  3238. //
  3239. float dist = triPlane.normal.Dot( ptCenter ) - triPlane.dist;
  3240. if( fabs( dist ) < distMin )
  3241. {
  3242. //
  3243. // create edge plane data
  3244. //
  3245. cplane_t edgePlanes[3];
  3246. Vector edges[3];
  3247. edges[0] = v[1] - v[0];
  3248. edges[1] = v[2] - v[1];
  3249. edges[2] = v[0] - v[2];
  3250. for( int j = 0; j < 3; j++ )
  3251. {
  3252. edgePlanes[j].normal = triPlane.normal.Cross( edges[j] );
  3253. VectorNormalize( edgePlanes[j].normal );
  3254. edgePlanes[j].dist = edgePlanes[j].normal.Dot( v[j] );
  3255. // check normal facing
  3256. float distPt = edgePlanes[j].normal.Dot( v[(j+2)%3] ) - edgePlanes[j].dist;
  3257. if( distPt > 0.0f )
  3258. {
  3259. edgePlanes[j].normal.Negate();
  3260. edgePlanes[j].dist = -edgePlanes[j].dist;
  3261. }
  3262. }
  3263. // intersect sphere with triangle
  3264. bool bSphereIntersect = SphereTriEdgePlanesIntersection( ptCenter, distMin, edgePlanes );
  3265. //
  3266. // check to see if the center lies behind all the edge planes
  3267. //
  3268. if( bSphereIntersect )
  3269. {
  3270. bool bPointInside = SphereTriEdgePlanesIntersection( ptCenter, 0.0f, edgePlanes );
  3271. if( bPointInside )
  3272. {
  3273. distMin = fabs( dist );
  3274. ptMin = ptCenter - ( triPlane.normal * dist );
  3275. }
  3276. else
  3277. {
  3278. // check distance to points
  3279. for( int k = 0; k < 3; k++ )
  3280. {
  3281. Vector vTmp;
  3282. vTmp = ptCenter - v[k];
  3283. float distPt = ( float )sqrt( vTmp.Dot( vTmp ) );
  3284. if( distPt < distMin )
  3285. {
  3286. distMin = distPt;
  3287. ptMin = v[k];
  3288. }
  3289. }
  3290. }
  3291. }
  3292. }
  3293. }
  3294. if( distMin != radius )
  3295. return true;
  3296. return false;
  3297. }
  3298. //-----------------------------------------------------------------------------
  3299. //-----------------------------------------------------------------------------
  3300. EditDispHandle_t CMapDisp::GetHitDispMap( void )
  3301. {
  3302. if( m_HitDispIndex == -1 )
  3303. {
  3304. CMapFace *pFace = ( CMapFace* )GetParent();
  3305. return pFace->GetDisp();
  3306. }
  3307. if( m_HitDispIndex <= 3 )
  3308. {
  3309. return m_EdgeNeighbors[m_HitDispIndex];
  3310. }
  3311. return m_CornerNeighbors[m_HitDispIndex-4][2];
  3312. }
  3313. //-----------------------------------------------------------------------------
  3314. // Purpose: UNDO is messy to begin with, and now with handles it gets even
  3315. // more fun!!! Call through here to setup undo!!
  3316. //-----------------------------------------------------------------------------
  3317. void EditDisp_ForUndo( EditDispHandle_t editHandle, char *pszPositionName,
  3318. bool bNeighborsUndo )
  3319. {
  3320. // sanity check on handle
  3321. if( editHandle == EDITDISPHANDLE_INVALID )
  3322. return;
  3323. // get the current displacement given the handle
  3324. CMapDisp *pDisp = EditDispMgr()->GetDisp( editHandle );
  3325. //
  3326. // set the undo name if necessary
  3327. //
  3328. if( pszPositionName )
  3329. {
  3330. GetHistory()->MarkUndoPosition( NULL, pszPositionName );
  3331. }
  3332. //
  3333. // get the solid (face) for the UNDO history
  3334. //
  3335. CMapFace *pFace = ( CMapFace* )pDisp->GetParent();
  3336. CMapSolid *pSolid = ( CMapSolid* )pFace->GetParent();
  3337. GetHistory()->Keep( ( CMapClass* )pSolid );
  3338. //
  3339. // neighbors in undo as well
  3340. //
  3341. if ( bNeighborsUndo )
  3342. {
  3343. for ( int ndxNeighbor = 0; ndxNeighbor < 4; ndxNeighbor++ )
  3344. {
  3345. // displacement pointer could have changed due to the undo/copyfrom above
  3346. pDisp = EditDispMgr()->GetDisp( editHandle );
  3347. //
  3348. // edge neighbors
  3349. //
  3350. int neighborOrient;
  3351. EditDispHandle_t neighborHandle;
  3352. pDisp->GetEdgeNeighbor( ndxNeighbor, neighborHandle, neighborOrient );
  3353. if( neighborHandle != EDITDISPHANDLE_INVALID )
  3354. {
  3355. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( neighborHandle );
  3356. CMapFace *pNeighborFace = ( CMapFace* )pNeighborDisp->GetParent();
  3357. CMapSolid *pNeighborSolid = ( CMapSolid* )pNeighborFace->GetParent();
  3358. GetHistory()->Keep( ( CMapClass* )pNeighborSolid );
  3359. // displacement pointer could have changed due to the undo/copyfrom above
  3360. pDisp = EditDispMgr()->GetDisp( editHandle );
  3361. }
  3362. //
  3363. // corner neighbors
  3364. //
  3365. int cornerCount = pDisp->GetCornerNeighborCount( ndxNeighbor );
  3366. if( cornerCount > 0 )
  3367. {
  3368. for( int ndxCorner = 0; ndxCorner < cornerCount; ndxCorner++ )
  3369. {
  3370. pDisp->GetCornerNeighbor( ndxNeighbor, ndxCorner, neighborHandle, neighborOrient );
  3371. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( neighborHandle );
  3372. CMapFace *pNeighborFace = ( CMapFace* )pNeighborDisp->GetParent();
  3373. CMapSolid *pNeighborSolid = ( CMapSolid* )pNeighborFace->GetParent();
  3374. GetHistory()->Keep( ( CMapClass* )pNeighborSolid );
  3375. // displacement pointer could have changed due to the undo/copyfrom above
  3376. pDisp = EditDispMgr()->GetDisp( editHandle );
  3377. }
  3378. }
  3379. }
  3380. }
  3381. }
  3382. //=============================================================================
  3383. //
  3384. // Painting Functions
  3385. //
  3386. //-----------------------------------------------------------------------------
  3387. //-----------------------------------------------------------------------------
  3388. void CMapDisp::Paint_Init( int nType )
  3389. {
  3390. m_Canvas.m_nType = nType;
  3391. m_Canvas.m_bDirty = false;
  3392. int nVertCount = GetSize();
  3393. for( int iVert = 0; iVert < nVertCount; iVert++ )
  3394. {
  3395. m_Canvas.m_Values[iVert].Init();
  3396. m_Canvas.m_bValuesDirty[iVert] = false;
  3397. }
  3398. }
  3399. //-----------------------------------------------------------------------------
  3400. //-----------------------------------------------------------------------------
  3401. void CMapDisp::Paint_InitSelfAndNeighbors( int nType )
  3402. {
  3403. // Initialiuze self.
  3404. Paint_Init( nType );
  3405. // Initialize neighbors.
  3406. for( int iEdge = 0; iEdge < 4; iEdge++ )
  3407. {
  3408. EditDispHandle_t handle = GetEdgeNeighbor( iEdge );
  3409. if( handle != EDITDISPHANDLE_INVALID )
  3410. {
  3411. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  3412. pNeighborDisp->Paint_Init( nType );
  3413. }
  3414. int nCornerCount = GetCornerNeighborCount( iEdge );
  3415. if( nCornerCount > 0 )
  3416. {
  3417. for( int iCorner = 0; iCorner < nCornerCount; iCorner++ )
  3418. {
  3419. handle = GetCornerNeighbor( iEdge, iCorner );
  3420. if( handle != EDITDISPHANDLE_INVALID )
  3421. {
  3422. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  3423. pNeighborDisp->Paint_Init( nType );
  3424. }
  3425. }
  3426. }
  3427. }
  3428. }
  3429. //-----------------------------------------------------------------------------
  3430. //-----------------------------------------------------------------------------
  3431. void CMapDisp::Paint_SetValue( int iVert, Vector const &vPaint )
  3432. {
  3433. Assert( iVert >= 0 );
  3434. Assert( iVert < MAPDISP_MAX_VERTS );
  3435. VectorCopy( vPaint, m_Canvas.m_Values[iVert] );
  3436. m_Canvas.m_bValuesDirty[iVert] = true;
  3437. m_Canvas.m_bDirty = true;
  3438. }
  3439. //-----------------------------------------------------------------------------
  3440. //-----------------------------------------------------------------------------
  3441. void CMapDisp::PaintAlpha_Update( int iVert )
  3442. {
  3443. SetAlpha( iVert, m_Canvas.m_Values[iVert].x );
  3444. }
  3445. //-----------------------------------------------------------------------------
  3446. //-----------------------------------------------------------------------------
  3447. void CMapDisp::PaintPosition_Update( int iVert )
  3448. {
  3449. Vector vSPos, vFlat;
  3450. GetFlatVert( iVert, vFlat );
  3451. GetSubdivPosition( iVert, vSPos );
  3452. Vector vSeg;
  3453. vSeg = m_Canvas.m_Values[iVert] - vFlat;
  3454. vSeg -= vSPos;
  3455. // Subtract out the elevation.
  3456. float elev = GetElevation();
  3457. if( elev != 0.0 )
  3458. {
  3459. Vector vNormal;
  3460. GetSurfNormal( vNormal );
  3461. vNormal *= elev;
  3462. vSeg -= vNormal;
  3463. }
  3464. float flDistance = VectorNormalize( vSeg );
  3465. SetFieldVector( iVert, vSeg );
  3466. SetFieldDistance( iVert, flDistance );
  3467. }
  3468. void CMapDisp::UpdateVertPositionForSubdiv( int iVert, const Vector &vecNewSubdivPos )
  3469. {
  3470. Vector vecSubdivPos, vecFlatPos, vecPos;
  3471. GetFlatVert( iVert, vecFlatPos );
  3472. GetSubdivPosition( iVert, vecSubdivPos );
  3473. GetVert( iVert, vecPos );
  3474. Vector vecSegment1;
  3475. vecPos -= vecSubdivPos;
  3476. vecSegment1 = vecPos - vecFlatPos;
  3477. // Subtract out the elevation.
  3478. float flElevation = GetElevation();
  3479. Vector vecFaceNormal( 0.0f, 0.0f, 0.0f );
  3480. if( flElevation != 0.0 )
  3481. {
  3482. GetSurfNormal( vecFaceNormal );
  3483. vecFaceNormal *= flElevation;
  3484. vecSegment1 -= vecFaceNormal;
  3485. }
  3486. float flDistance = VectorNormalize( vecSegment1 );
  3487. SetFieldVector( iVert, vecSegment1 );
  3488. SetFieldDistance( iVert, flDistance );
  3489. SetSubdivPosition( iVert, vecNewSubdivPos );
  3490. // Have to update in place.
  3491. Vector vecNewPos = vecFlatPos;
  3492. vecNewPos += ( vecFaceNormal * flElevation );
  3493. vecNewPos += vecNewSubdivPos;
  3494. vecNewPos += ( vecSegment1 * flDistance );
  3495. SetVert( iVert, vecNewPos );
  3496. }
  3497. //-----------------------------------------------------------------------------
  3498. //-----------------------------------------------------------------------------
  3499. void CMapDisp::Paint_Update( bool bSplit )
  3500. {
  3501. // Check for changes to the canvas.
  3502. if ( !m_Canvas.m_bDirty )
  3503. return;
  3504. int nVertCount = GetSize();
  3505. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  3506. {
  3507. // Check for changes at the vertex.
  3508. if ( m_Canvas.m_bValuesDirty[iVert] )
  3509. {
  3510. if ( m_Canvas.m_nType == DISPPAINT_CHANNEL_POSITION )
  3511. {
  3512. PaintPosition_Update( iVert );
  3513. }
  3514. else if ( m_Canvas.m_nType == DISPPAINT_CHANNEL_ALPHA )
  3515. {
  3516. PaintAlpha_Update( iVert );
  3517. }
  3518. }
  3519. }
  3520. // Update the displacement surface.
  3521. UpdateData();
  3522. if ( !bSplit )
  3523. {
  3524. CheckAndUpdateOverlays( false );
  3525. }
  3526. }
  3527. //-----------------------------------------------------------------------------
  3528. //-----------------------------------------------------------------------------
  3529. void CMapDisp::Paint_UpdateSelfAndNeighbors( bool bSplit )
  3530. {
  3531. // Update self.
  3532. Paint_Update( bSplit );
  3533. // Update neighbors.
  3534. for( int iEdge = 0; iEdge < 4; iEdge++ )
  3535. {
  3536. EditDispHandle_t handle = GetEdgeNeighbor( iEdge );
  3537. if( handle != EDITDISPHANDLE_INVALID )
  3538. {
  3539. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  3540. pNeighborDisp->Paint_Update( bSplit );
  3541. }
  3542. int nCornerCount = GetCornerNeighborCount( iEdge );
  3543. if( nCornerCount > 0 )
  3544. {
  3545. for( int iCorner = 0; iCorner < nCornerCount; iCorner++ )
  3546. {
  3547. handle = GetCornerNeighbor( iEdge, iCorner );
  3548. if( handle != EDITDISPHANDLE_INVALID )
  3549. {
  3550. CMapDisp *pNeighborDisp = EditDispMgr()->GetDisp( handle );
  3551. pNeighborDisp->Paint_Update( bSplit );
  3552. }
  3553. }
  3554. }
  3555. }
  3556. }
  3557. //-----------------------------------------------------------------------------
  3558. //-----------------------------------------------------------------------------
  3559. void CMapDisp::SetSelectMask( bool bSelectMask )
  3560. {
  3561. m_bSelectMask = bSelectMask;
  3562. }
  3563. //-----------------------------------------------------------------------------
  3564. //-----------------------------------------------------------------------------
  3565. bool CMapDisp::HasSelectMask( void )
  3566. {
  3567. return m_bSelectMask;
  3568. }
  3569. //-----------------------------------------------------------------------------
  3570. //-----------------------------------------------------------------------------
  3571. void CMapDisp::SetGridMask( bool bGridMask )
  3572. {
  3573. m_bGridMask = bGridMask;
  3574. }
  3575. //-----------------------------------------------------------------------------
  3576. //-----------------------------------------------------------------------------
  3577. bool CMapDisp::HasGridMask( void )
  3578. {
  3579. return m_bGridMask;
  3580. }
  3581. //-----------------------------------------------------------------------------
  3582. // Purpose: Do the slow thing first and optimize later??
  3583. //-----------------------------------------------------------------------------
  3584. int CMapDisp::CollideWithDispTri( const Vector &rayStart, const Vector &rayEnd, float &flFraction, bool OneSided )
  3585. {
  3586. int iTriangle = -1;
  3587. flFraction = 1.0f;
  3588. int nTriCount = GetTriCount();
  3589. for ( int iTri = 0; iTri < nTriCount; ++iTri )
  3590. {
  3591. unsigned short v1, v2, v3;
  3592. GetTriIndices( iTri, v1, v2, v3 );
  3593. Vector vec1, vec2, vec3;
  3594. GetVert( v1, vec1 );
  3595. GetVert( v2, vec2 );
  3596. GetVert( v3, vec3 );
  3597. Ray_t ray;
  3598. ray.Init( rayStart, rayEnd, Vector( 0.0f, 0.0f, 0.0f ), Vector ( 0.0f, 0.0f, 0.0f ) );
  3599. float flFrac = IntersectRayWithTriangle( ray, vec1, vec2, vec3, OneSided );
  3600. if ( flFrac == -1.0f )
  3601. continue;
  3602. if ( flFrac < flFraction )
  3603. {
  3604. flFraction = flFrac;
  3605. iTriangle = iTri;
  3606. }
  3607. }
  3608. return iTriangle;
  3609. }
  3610. bool CMapDisp::SaveDXF(ExportDXFInfo_s *pInfo)
  3611. {
  3612. char szName[128];
  3613. sprintf(szName, "OBJECT%03d", pInfo->nObject);
  3614. // count number of triangulated faces
  3615. int nVertCount = GetSize();
  3616. int nTriFaces = TriangleCount();
  3617. fprintf(pInfo->fp,"0\nPOLYLINE\n8\n%s\n66\n1\n70\n64\n71\n%u\n72\n%u\n",
  3618. szName, nVertCount, nTriFaces);
  3619. fprintf(pInfo->fp,"62\n50\n");
  3620. // Write out vertices...
  3621. int i;
  3622. for (i = 0; i < nVertCount; i++)
  3623. {
  3624. Vector pos;
  3625. GetVert( i, pos );
  3626. fprintf(pInfo->fp, "0\nVERTEX\n8\n%s\n10\n%.6f\n20\n%.6f\n30\n%.6f\n70\n192\n", szName, pos[0], pos[1], pos[2]);
  3627. }
  3628. // triangulate each face and write
  3629. int nWidth = GetWidth();
  3630. int nHeight = GetHeight();
  3631. for (i = 0; i < nHeight - 1; ++i)
  3632. {
  3633. for (int j = 0; j < nWidth - 1; ++j)
  3634. {
  3635. // DXF files are 1 based, not 0 based. That's what the extra 1 is for
  3636. int idx = i * nHeight + j + 1;
  3637. fprintf(pInfo->fp, "0\nVERTEX\n8\n%s\n10\n0\n20\n0\n30\n"
  3638. "0\n70\n128\n71\n%d\n72\n%d\n73\n%d\n", szName,
  3639. idx, idx + nHeight, idx + nHeight + 1 );
  3640. fprintf(pInfo->fp, "0\nVERTEX\n8\n%s\n10\n0\n20\n0\n30\n"
  3641. "0\n70\n128\n71\n%d\n72\n%d\n73\n%d\n", szName,
  3642. idx, idx + nHeight + 1, idx + 1 );
  3643. }
  3644. }
  3645. fprintf(pInfo->fp, "0\nSEQEND\n8\n%s\n", szName);
  3646. return true;
  3647. }