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

4708 lines
126 KiB

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