Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3933 lines
111 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. // SculptOptions.cpp : implementation file
  3. //
  4. #include <stdafx.h>
  5. #include "hammer.h"
  6. #include "CollisionUtils.h"
  7. #include "resource.h"
  8. #include "ToolDisplace.h"
  9. #include "MainFrm.h"
  10. #include "FaceEditSheet.h"
  11. #include "GlobalFunctions.h"
  12. #include "MapAtom.h"
  13. #include "MapSolid.h"
  14. #include "MapView3D.h"
  15. #include "History.h"
  16. #include "Camera.h"
  17. #include "MapDoc.h"
  18. #include "ChunkFile.h"
  19. #include "ToolManager.h"
  20. #include "bitmap/tgaloader.h"
  21. #include "tier1/utlbuffer.h"
  22. #include "Material.h"
  23. #include "materialsystem/imaterial.h"
  24. #include "materialsystem/imaterialsystem.h"
  25. #include "materialsystem/MaterialSystemUtil.h"
  26. #include "materialsystem/itexture.h"
  27. #include "../materialsystem/itextureinternal.h"
  28. #include "pixelwriter.h"
  29. #include "TextureSystem.h"
  30. #include "SculptOptions.h"
  31. // memdbgon must be the last include file in a .cpp file!!!
  32. #include <tier0/memdbgon.h>
  33. extern CToolDisplace* GetDisplacementTool();
  34. extern void FaceListSewEdges( void );
  35. CUtlMap<EditDispHandle_t, CMapDisp *> CSculptTool::m_OrigMapDisp( 3, 3, CSculptTool::MapDispLessFunc );
  36. //-----------------------------------------------------------------------------
  37. // Purpose: constructor
  38. //-----------------------------------------------------------------------------
  39. CSculptTool::CSculptTool()
  40. {
  41. m_PaintOwner = NULL;
  42. m_MousePoint.Init();
  43. m_StartingCollisionNormal.Init();
  44. m_OriginalCollisionPoint.Init();
  45. m_bAltDown = m_bCtrlDown = m_bShiftDown = false;
  46. m_bLMBDown = m_bRMBDown = false;
  47. m_ValidPaintingSpot = false;
  48. m_BrushSize = 50;
  49. m_StartingProjectedRadius = m_OriginalProjectedRadius = 10.0f;
  50. m_OriginalCollisionValid = m_CurrentCollisionValid = false;
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose: destructor
  54. //-----------------------------------------------------------------------------
  55. CSculptTool::~CSculptTool()
  56. {
  57. FOR_EACH_MAP( m_OrigMapDisp, pos )
  58. {
  59. delete m_OrigMapDisp.Element( pos );
  60. }
  61. m_OrigMapDisp.Purge();
  62. }
  63. //-----------------------------------------------------------------------------
  64. // Purpose: setup for starting to paint on the displacement
  65. // Input : pView - the 3d view
  66. // vPoint - the initial click point
  67. // Output : returns true if successful
  68. //-----------------------------------------------------------------------------
  69. bool CSculptTool::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  70. {
  71. DuplicateSelectedDisp();
  72. GetStartingSpot( pView, vPoint );
  73. return true;
  74. }
  75. //-----------------------------------------------------------------------------
  76. // Purpose: main routine called when mouse move has happened to start painting
  77. // Input : pView - the 3d view
  78. // vPoint - the mouse point
  79. // SpatialData - the spatial data ( mostly ignored )
  80. // Output : returns true if successful
  81. //-----------------------------------------------------------------------------
  82. bool CSculptTool::Paint( CMapView3D *pView, const Vector2D &vPoint, SpatialPaintData_t &SpatialData )
  83. {
  84. m_SpatialData = SpatialData;
  85. // Successful paint operation.
  86. return true;
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose: determines if any of the special keys ( control, shift, alt ) are pressed
  90. //-----------------------------------------------------------------------------
  91. void CSculptTool::DetermineKeysDown()
  92. {
  93. m_bCtrlDown = ( ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) != 0 );
  94. m_bShiftDown = ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) != 0 );
  95. m_bAltDown = ( ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) != 0 );
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose: handles the left mouse button up in the 3d view
  99. // Input : pView - the 3d view
  100. // nFlags - the button flags
  101. // vPoint - the mouse point
  102. // Output : returns true if successful
  103. //-----------------------------------------------------------------------------
  104. bool CSculptTool::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  105. {
  106. DetermineKeysDown();
  107. // left button up
  108. m_bLMBDown = false;
  109. m_MousePoint = vPoint;
  110. return true;
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Purpose: handles the left mouse button down in the 3d view
  114. // Input : pView - the 3d view
  115. // nFlags - the button flags
  116. // vPoint - the mouse point
  117. // Output : returns true if successful
  118. //-----------------------------------------------------------------------------
  119. bool CSculptTool::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  120. {
  121. DetermineKeysDown();
  122. // left button down
  123. m_bLMBDown = true;
  124. m_MousePoint = vPoint;
  125. return true;
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Purpose: handles the right mouse button up in the 3d view
  129. // Input : pView - the 3d view
  130. // nFlags - the button flags
  131. // vPoint - the mouse point
  132. // Output : returns true if successful
  133. //-----------------------------------------------------------------------------
  134. bool CSculptTool::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  135. {
  136. DetermineKeysDown();
  137. // right button up
  138. m_bRMBDown = false;
  139. m_MousePoint = vPoint;
  140. return true;
  141. }
  142. //-----------------------------------------------------------------------------
  143. // Purpose: handles the right mouse button down in the 3d view
  144. // Input : pView - the 3d view
  145. // nFlags - the button flags
  146. // vPoint - the mouse point
  147. // Output : returns true if successful
  148. //-----------------------------------------------------------------------------
  149. bool CSculptTool::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  150. {
  151. DetermineKeysDown();
  152. // right button down
  153. m_bRMBDown = true;
  154. m_MousePoint = vPoint;
  155. return true;
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Purpose: handles the mouse move in the 3d view
  159. // Input : pView - the 3d view
  160. // nFlags - the button flags
  161. // vPoint - the mouse point
  162. // Output : returns true if successful
  163. //-----------------------------------------------------------------------------
  164. bool CSculptTool::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  165. {
  166. DetermineKeysDown();
  167. m_MousePoint = vPoint;
  168. return true;
  169. }
  170. //-----------------------------------------------------------------------------
  171. // Purpose: called just before painting begins to gather reference information
  172. // Input : pView - the 3d view
  173. // vPoint - the mouse point
  174. // Output : returns true if successful
  175. //-----------------------------------------------------------------------------
  176. bool CSculptTool::PrePaint( CMapView3D *pView, const Vector2D &vPoint )
  177. {
  178. Vector2D RadiusPoint = vPoint;
  179. Vector vecStart, vecEnd;
  180. RadiusPoint.x += m_BrushSize;
  181. pView->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  182. m_OriginalCollisionValid = FindCollisionIntercept( pView->GetCamera(), vPoint, true, m_OriginalCollisionPoint, m_OriginalCollisionNormal, m_OriginalCollisionIntercept );
  183. if ( m_OriginalCollisionValid )
  184. {
  185. m_OriginalProjectedRadius = CalcDistanceToLine( m_OriginalCollisionPoint, vecStart, vecEnd );
  186. }
  187. m_CurrentCollisionValid = FindCollisionIntercept( pView->GetCamera(), vPoint, false, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept );
  188. if ( m_CurrentCollisionValid )
  189. {
  190. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  191. }
  192. m_SpatialData.m_flRadius = 128.0f;
  193. m_SpatialData.m_flRadius2 = ( m_SpatialData.m_flRadius * m_SpatialData.m_flRadius );
  194. m_SpatialData.m_flOORadius2 = 1.0f / m_SpatialData.m_flRadius2;
  195. return true;
  196. }
  197. //-----------------------------------------------------------------------------
  198. // Purpose: called after painting finishes to finalize things
  199. // Input : bAutoSew - should we sew the edges
  200. // Output : returns true if successful
  201. //-----------------------------------------------------------------------------
  202. bool CSculptTool::PostPaint( bool bAutoSew )
  203. {
  204. // Get the displacement manager from the active map document.
  205. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  206. if( !pDispMgr )
  207. return false;
  208. // Update the modified displacements.
  209. int nDispCount = pDispMgr->SelectCount();
  210. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  211. {
  212. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  213. if ( pDisp )
  214. {
  215. pDisp->Paint_Update( false );
  216. }
  217. }
  218. // Auto "sew" if necessary.
  219. if ( bAutoSew )
  220. {
  221. FaceListSewEdges();
  222. }
  223. return true;
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Purpose: called to dispatch the painting routine across all selected displacements
  227. // Input : pView - the 3d view
  228. // vPoint - the mouse point
  229. // Output : returns true if successful
  230. //-----------------------------------------------------------------------------
  231. bool CSculptTool::DoPaint( CMapView3D *pView, const Vector2D &vPoint )
  232. {
  233. // Get the displacement manager from the active map document.
  234. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  235. if( !pDispMgr )
  236. return false;
  237. // For each displacement surface is the selection list attempt to paint on it.
  238. int nDispCount = pDispMgr->SelectCount();
  239. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  240. {
  241. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  242. if ( pDisp )
  243. {
  244. CMapDisp *OrigDisp = NULL;
  245. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  246. if ( index != m_OrigMapDisp.InvalidIndex() )
  247. {
  248. OrigDisp = m_OrigMapDisp[ index ];
  249. }
  250. DoPaintOperation( pView, vPoint, pDisp, OrigDisp );
  251. }
  252. }
  253. // Successful paint.
  254. return true;
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Purpose: checks to see if a given displacement vert lies within the 2d screenspace of the circle
  258. // Input : pView - the 3d view
  259. // pDisp - the displacement the vert belongs to
  260. // pOrigDisp - the displacement prior to any moving
  261. // nVertIndex - the vert index
  262. // bUseOrigDisplacement - should we use the vert from the original displacement
  263. // bUseCurrentPosition - should we use the current collision test point
  264. // Output : returns true if the point is within the circle
  265. //-----------------------------------------------------------------------------
  266. bool CSculptTool::IsPointInScreenCircle( CMapView3D *pView, CMapDisp *pDisp, CMapDisp *pOrigDisp, int nVertIndex, bool bUseOrigDisplacement, bool bUseCurrentPosition, float *pflLengthPercent )
  267. {
  268. Vector vVert, vTestVert;
  269. pDisp->GetVert( nVertIndex, vVert );
  270. if ( pOrigDisp && bUseOrigDisplacement )
  271. {
  272. pOrigDisp->GetVert( nVertIndex, vTestVert );
  273. }
  274. else
  275. {
  276. vTestVert = vVert;
  277. }
  278. #if 0
  279. Vector2D ViewVert;
  280. pView->GetCamera()->WorldToView( vTestVert, ViewVert );
  281. Vector2D Offset = ViewVert - m_MousePoint;
  282. float Length = Offset.Length();
  283. return ( Length <= m_BrushSize );
  284. #else
  285. if ( bUseCurrentPosition )
  286. {
  287. if ( !m_CurrentCollisionValid )
  288. {
  289. return false;
  290. }
  291. Vector Offset = m_CurrentCollisionPoint - vTestVert;
  292. float Length = Offset.Length();
  293. if ( pflLengthPercent )
  294. {
  295. *pflLengthPercent = Length / m_CurrentProjectedRadius;
  296. }
  297. return ( Length <= m_CurrentProjectedRadius );
  298. }
  299. else
  300. {
  301. if ( !m_OriginalCollisionValid )
  302. {
  303. return false;
  304. }
  305. Vector Offset = m_OriginalCollisionPoint - vTestVert;
  306. float Length = Offset.Length();
  307. if ( pflLengthPercent )
  308. {
  309. *pflLengthPercent = Length / m_OriginalProjectedRadius;
  310. }
  311. #if 0
  312. if ( Length <= m_OriginalProjectedRadius || vertIndex == 66 )
  313. {
  314. Msg( "%d: ( %g %g %g ) from %g <= %g at ( %g %g %g )\n", vertIndex, vTestVert.x, vTestVert.y, vTestVert.z, Length, m_OriginalProjectedRadius, m_OriginalCollisionPoint.x, m_OriginalCollisionPoint.y, m_OriginalCollisionPoint.z );
  315. }
  316. #endif
  317. return ( Length <= m_OriginalProjectedRadius );
  318. }
  319. #endif
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Purpose: Adds a displacement to the undo manager
  323. // Input : pDisp - the displacement
  324. //-----------------------------------------------------------------------------
  325. void CSculptTool::AddToUndo( CMapDisp **pDisp )
  326. {
  327. CMapDisp *pUndoDisp = *pDisp;
  328. if ( pUndoDisp->Paint_IsDirty() )
  329. return;
  330. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  331. if( pDispMgr )
  332. {
  333. EditDispHandle_t handle = pUndoDisp->GetEditHandle();
  334. pDispMgr->Undo( handle, false );
  335. *pDisp = EditDispMgr()->GetDisp( handle );
  336. }
  337. }
  338. #if 0
  339. //-----------------------------------------------------------------------------
  340. // Purpose:
  341. // Input :
  342. // Output :
  343. //-----------------------------------------------------------------------------
  344. void CSculptTool::DoPaintEqual( SpatialPaintData_t &spatialData, CMapDisp *pDisp )
  345. {
  346. Vector vPaintPos, vVert, vFlatVert;
  347. float flDistance2;
  348. int nVertCount = pDisp->GetSize();
  349. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  350. {
  351. // Get the current vert.
  352. pDisp->GetVert( iVert, vVert );
  353. if ( IsInSphereRadius( spatialData.m_vCenter, spatialData.m_flRadius2, vVert, flDistance2 ) )
  354. {
  355. // Get the base vert.
  356. pDisp->GetFlatVert( iVert, vFlatVert );
  357. // Build the new position (paint value) and set it.
  358. DoPaintOne( spatialData, vFlatVert, vPaintPos );
  359. AddToUndo( &pDisp );
  360. pDisp->Paint_SetValue( iVert, vPaintPos );
  361. }
  362. }
  363. }
  364. #endif
  365. //-----------------------------------------------------------------------------
  366. // Purpose: this routine does the smoothing operation
  367. // Input : pView - the 3d view
  368. // vPoint - the mouse point
  369. // pDisp - the displacement to smooth
  370. // pOrigDisp - the displacement prior to the paint operation
  371. // Output :
  372. //-----------------------------------------------------------------------------
  373. void CSculptTool::DoPaintSmooth( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  374. {
  375. Vector vPaintPos, vVert;
  376. pDisp->GetSurfNormal( m_SpatialData.m_vPaintAxis );
  377. int nVertCount = pDisp->GetSize();
  378. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  379. {
  380. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, false, true ) )
  381. {
  382. // Msg( "Checking Vert %d\n", iVert );
  383. // Get the current vert.
  384. pDisp->GetVert( iVert, vVert );
  385. // Build the new smoothed position and set it.
  386. if ( DoPaintSmoothOneOverExp( vVert, vPaintPos ) )
  387. {
  388. AddToUndo( &pDisp );
  389. pDisp->Paint_SetValue( iVert, vPaintPos );
  390. // Msg( "Vert %d Updated: from %g %g %g to %g %g %g\n", iVert, vVert.x, vVert.y, vVert.z, vPaintPos.x, vPaintPos.y, vPaintPos.z );
  391. }
  392. }
  393. }
  394. }
  395. //-----------------------------------------------------------------------------
  396. // Purpose: checks to see if the paint sphere is within the bounding box
  397. // Input : vCenter - center of the sphere
  398. // flRadius - sphere radius
  399. // vBBoxMin - bounding box mins
  400. // vBBoxMax - bounding box maxs
  401. // Output : returns two if the two intersect
  402. //-----------------------------------------------------------------------------
  403. bool CSculptTool::PaintSphereDispBBoxOverlap( const Vector &vCenter, float flRadius, const Vector &vBBoxMin, const Vector &vBBoxMax )
  404. {
  405. return IsBoxIntersectingSphere( vBBoxMin, vBBoxMax, vCenter, flRadius );
  406. }
  407. //-----------------------------------------------------------------------------
  408. // Purpose: checkes to see if the two spheres intersect
  409. // Input : vCenter - center of the sphere
  410. // flRadius2 - sphere radius squared
  411. // vPos - point to test
  412. // flDistance2 - radius of point
  413. // Output : returns true if the two spheres intersect
  414. //-----------------------------------------------------------------------------
  415. bool CSculptTool::IsInSphereRadius( const Vector &vCenter, float flRadius2, const Vector &vPos, float &flDistance2 )
  416. {
  417. Vector vTmp;
  418. VectorSubtract( vPos, vCenter, vTmp );
  419. flDistance2 = ( vTmp.x * vTmp.x ) + ( vTmp.y * vTmp.y ) + ( vTmp.z * vTmp.z );
  420. return ( flDistance2 < flRadius2 );
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Purpose: calculates the smoothing radius squared
  424. // Input : vPoint - the point to be smoothed
  425. // Output : returns the smoothing radius squared
  426. //-----------------------------------------------------------------------------
  427. float CSculptTool::CalcSmoothRadius2( const Vector &vPoint )
  428. {
  429. Vector vTmp;
  430. VectorSubtract( m_SpatialData.m_vCenter, vPoint, vTmp );
  431. float flDistance2 = ( vTmp.x * vTmp.x ) + ( vTmp.y * vTmp.y ) + ( vTmp.z * vTmp.z );
  432. float flRatio = flDistance2 / m_SpatialData.m_flRadius2;
  433. flRatio = 1.0f - flRatio;
  434. float flRadius = flRatio * m_SpatialData.m_flRadius;
  435. return ( flRadius * flRadius );
  436. }
  437. //-----------------------------------------------------------------------------
  438. // Purpose: smooths all displacements
  439. // Input : vNewCenter - calculate the smoothing center
  440. // Output : returns true if successful
  441. // vPaintPos - the new smoothing position
  442. //-----------------------------------------------------------------------------
  443. bool CSculptTool::DoPaintSmoothOneOverExp( const Vector &vNewCenter, Vector &vPaintPos )
  444. {
  445. // Get the displacement manager from the active map document.
  446. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  447. if( !pDispMgr )
  448. return false;
  449. // Calculate the smoothing radius.
  450. float flNewRadius2 = CalcSmoothRadius2( vNewCenter );
  451. flNewRadius2 *= 2.0f;
  452. float flNewRadius = ( float )sqrt( flNewRadius2 );
  453. // Test all selected surfaces for smoothing.
  454. float flWeight = 0.0f;
  455. float flSmoothDist = 0.0f;
  456. // Calculate the plane dist.
  457. float flPaintDist = m_SpatialData.m_vPaintAxis.Dot( vNewCenter );
  458. int nDispCount = pDispMgr->SelectCount();
  459. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  460. {
  461. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  462. if ( pDisp )
  463. {
  464. // Test paint sphere displacement bbox for overlap.
  465. Vector vBBoxMin, vBBoxMax;
  466. pDisp->GetBoundingBox( vBBoxMin, vBBoxMax );
  467. if ( PaintSphereDispBBoxOverlap( vNewCenter, flNewRadius, vBBoxMin, vBBoxMax ) )
  468. {
  469. Vector vVert;
  470. int nVertCount = pDisp->GetSize();
  471. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  472. {
  473. // Get the current vert.
  474. pDisp->GetVert( iVert, vVert );
  475. float flDistance2 = 0.0f;
  476. if ( IsInSphereRadius( vNewCenter, flNewRadius2, vVert, flDistance2 ) )
  477. {
  478. float flRatio = flDistance2 / flNewRadius2;
  479. float flFactor = 1.0f / exp( flRatio );
  480. if ( flFactor != 1.0f )
  481. {
  482. flFactor *= 1.0f / ( m_SpatialData.m_flScalar * 2.0f );
  483. }
  484. Vector vProjectVert;
  485. float flProjectDist = DotProduct( vVert, m_SpatialData.m_vPaintAxis ) - flPaintDist;
  486. flSmoothDist += ( flProjectDist * flFactor );
  487. flWeight += flFactor;
  488. // Msg( "Factoring %d: %g %g %g at %g\n", iVert, vVert.x, vVert.y, vVert.z, flNewRadius2 );
  489. }
  490. }
  491. }
  492. }
  493. }
  494. if ( flWeight == 0.0f )
  495. {
  496. return false;
  497. }
  498. // Re-normalize the smoothing position.
  499. flSmoothDist /= flWeight;
  500. vPaintPos = vNewCenter + ( m_SpatialData.m_vPaintAxis * flSmoothDist );
  501. return true;
  502. }
  503. //-----------------------------------------------------------------------------
  504. // Purpose: gets the starting position when the paint operation begins
  505. // Input : pView - the 3d view
  506. // vPoint - the mouse point
  507. // Output : returns the starting position
  508. //-----------------------------------------------------------------------------
  509. bool CSculptTool::GetStartingSpot( CMapView3D *pView, const Vector2D &vPoint )
  510. {
  511. m_ValidPaintingSpot = FindCollisionIntercept( pView->GetCamera(), vPoint, false, m_StartingCollisionPoint, m_StartingCollisionNormal, m_StartingCollisionIntercept );
  512. if ( m_ValidPaintingSpot )
  513. {
  514. Vector2D RadiusPoint = vPoint;
  515. Vector vecStart, vecEnd;
  516. RadiusPoint.x += m_BrushSize;
  517. pView->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  518. m_StartingProjectedRadius = CalcDistanceToLine( m_StartingCollisionPoint, vecStart, vecEnd );
  519. }
  520. return m_ValidPaintingSpot;
  521. }
  522. //-----------------------------------------------------------------------------
  523. // Purpose: Draws a 2d line to represent the direction
  524. // Input : pRender - the renderer
  525. // Direction - direction / normal
  526. // Towards - the color to be used if the direction is towards the viewer
  527. // Away - the color to be used if the direction is away from the view
  528. //-----------------------------------------------------------------------------
  529. void CSculptTool::DrawDirection( CRender3D *pRender, Vector Direction, Color Towards, Color Away )
  530. {
  531. Vector ViewPoint, ViewDir;
  532. Vector2D ViewVert;
  533. VMatrix Matrix;
  534. pRender->GetCamera()->GetViewProjMatrix( Matrix );
  535. Matrix.SetTranslation( Vector( 0.0f, 0.0f, 0.0f ) );
  536. Vector3DMultiply( Matrix, Direction, ViewDir );
  537. VectorNormalize( ViewDir );
  538. ViewVert = m_MousePoint + ( Vector2D( ViewDir.x, -ViewDir.y ) * m_BrushSize );
  539. if ( ViewDir.z > 0.0f )
  540. {
  541. pRender->SetDrawColor( Away.r(), Away.g(), Away.b() );
  542. }
  543. else
  544. {
  545. pRender->SetDrawColor( Towards.r(), Towards.g(), Towards.b() );
  546. }
  547. bool bPopMode = pRender->BeginClientSpace();
  548. pRender->DrawLine( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( ViewVert.x, ViewVert.y, 0.0f ) );
  549. if ( bPopMode )
  550. {
  551. pRender->EndClientSpace();
  552. }
  553. }
  554. //-----------------------------------------------------------------------------
  555. // Purpose: this function will copy all the selected displacements
  556. //-----------------------------------------------------------------------------
  557. void CSculptTool::DuplicateSelectedDisp( )
  558. {
  559. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  560. if( !pDispMgr )
  561. {
  562. return;
  563. }
  564. FOR_EACH_MAP( m_OrigMapDisp, pos )
  565. {
  566. delete m_OrigMapDisp.Element( pos );
  567. }
  568. m_OrigMapDisp.Purge();
  569. int nDispCount = pDispMgr->SelectCount();
  570. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  571. {
  572. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  573. if ( pDisp )
  574. {
  575. CMapDisp *pCopy = new CMapDisp();
  576. pCopy->CopyFrom( pDisp, false );
  577. m_OrigMapDisp.Insert( pDisp->GetEditHandle(), pCopy );
  578. }
  579. }
  580. }
  581. //-----------------------------------------------------------------------------
  582. // Purpose: this function will initialize all selected displacements for updating
  583. //-----------------------------------------------------------------------------
  584. void CSculptTool::PrepareDispForPainting( )
  585. {
  586. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  587. if( !pDispMgr )
  588. {
  589. return;
  590. }
  591. int nDispCount = pDispMgr->SelectCount();
  592. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  593. {
  594. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  595. if ( pDisp )
  596. {
  597. pDisp->Paint_Init( DISPPAINT_CHANNEL_POSITION );
  598. }
  599. }
  600. }
  601. //-----------------------------------------------------------------------------
  602. // Purpose: this function will find the collision location within the selected displacements
  603. // Input : pCamera - the camera
  604. // vPoint - the 2d point on screen
  605. // bUseOrigPosition - should we use the original displacements prior to updating
  606. // Output : returns true if the point intercepted one of the selected displacements
  607. // vCollisionPoint the 3d interception point
  608. // vCollisionNormal - the normal of the tri hit
  609. // flCollisionIntercept - the intercept
  610. //-----------------------------------------------------------------------------
  611. bool CSculptTool::FindCollisionIntercept( CCamera *pCamera, const Vector2D &vPoint, bool bUseOrigPosition, Vector &vCollisionPoint, Vector &vCollisionNormal, float &flCollisionIntercept )
  612. {
  613. Vector vecStart, vecEnd;
  614. float flFraction, flLeastFraction;
  615. flLeastFraction = -1.0f;
  616. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  617. if( !pDispMgr )
  618. {
  619. return false;
  620. }
  621. int nDispCount = pDispMgr->SelectCount();
  622. pCamera->BuildRay( vPoint, vecStart, vecEnd );
  623. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  624. {
  625. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  626. if ( pDisp )
  627. {
  628. if ( bUseOrigPosition )
  629. {
  630. CMapDisp *OrigDisp = NULL;
  631. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  632. if ( index != m_OrigMapDisp.InvalidIndex() )
  633. {
  634. OrigDisp = m_OrigMapDisp[ index ];
  635. }
  636. if ( OrigDisp )
  637. {
  638. pDisp = OrigDisp;
  639. }
  640. }
  641. int iTri = pDisp->CollideWithDispTri( vecStart, vecEnd, flFraction, false );
  642. if ( iTri != -1 && ( flLeastFraction == -1.0f || flFraction < flLeastFraction ) )
  643. {
  644. flLeastFraction = flFraction;
  645. vCollisionPoint = vecStart + ( ( vecEnd - vecStart ) * flFraction );
  646. unsigned short v1, v2, v3;
  647. Vector vec1, vec2, vec3;
  648. pDisp->GetTriIndices( iTri, v1, v2, v3 );
  649. pDisp->GetVert( v1, vec1 );
  650. pDisp->GetVert( v2, vec2 );
  651. pDisp->GetVert( v3, vec3 );
  652. ComputeTrianglePlane( vec1, vec2, vec3, vCollisionNormal, flCollisionIntercept );
  653. }
  654. }
  655. }
  656. return ( flLeastFraction != -1.0f );
  657. }
  658. //-----------------------------------------------------------------------------
  659. // Purpose: constructor
  660. //-----------------------------------------------------------------------------
  661. CSculptPainter::CSculptPainter() :
  662. CSculptTool()
  663. {
  664. m_InSizingMode = m_InPaintingMode = false;
  665. m_OrigBrushSize = m_BrushSize;
  666. }
  667. //-----------------------------------------------------------------------------
  668. // Purpose: destructor
  669. //-----------------------------------------------------------------------------
  670. CSculptPainter::~CSculptPainter( )
  671. {
  672. }
  673. //-----------------------------------------------------------------------------
  674. // Purpose: setup for starting to paint on the displacement
  675. // Input : pView - the 3d view
  676. // vPoint - the initial click point
  677. // Output : returns true if successful
  678. //-----------------------------------------------------------------------------
  679. bool CSculptPainter::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  680. {
  681. CSculptTool::BeginPaint( pView, vPoint );
  682. PrepareDispForPainting();
  683. return true;
  684. }
  685. //-----------------------------------------------------------------------------
  686. // Purpose: main routine called when mouse move has happened to start painting
  687. // Input : pView - the 3d view
  688. // vPoint - the mouse point
  689. // SpatialData - the spatial data ( mostly ignored )
  690. // Output : returns true if successful
  691. //-----------------------------------------------------------------------------
  692. bool CSculptPainter::Paint( CMapView3D *pView, const Vector2D &vPoint, SpatialPaintData_t &SpatialData )
  693. {
  694. __super::Paint( pView, vPoint, SpatialData );
  695. if ( m_bRMBDown )
  696. {
  697. if ( !m_bAltDown )
  698. {
  699. DoSizing( vPoint );
  700. }
  701. }
  702. else if ( m_bLMBDown )
  703. {
  704. if ( !m_ValidPaintingSpot )
  705. {
  706. if ( !GetStartingSpot( pView, vPoint ) )
  707. {
  708. return false;
  709. }
  710. }
  711. // Setup painting.
  712. if ( !PrePaint( pView, vPoint ) )
  713. {
  714. return false;
  715. }
  716. // Handle painting.
  717. if ( !DoPaint( pView, vPoint ) )
  718. {
  719. return false;
  720. }
  721. // Finish painting.
  722. if ( !PostPaint( m_PaintOwner->GetAutoSew() ) )
  723. {
  724. return false;
  725. }
  726. }
  727. // Successful paint operation.
  728. return true;
  729. }
  730. //-----------------------------------------------------------------------------
  731. // Purpose: handles the left mouse button up in the 3d view
  732. // Input : pView - the 3d view
  733. // nFlags - the button flags
  734. // vPoint - the mouse point
  735. // Output : returns true if successful
  736. //-----------------------------------------------------------------------------
  737. bool CSculptPainter::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  738. {
  739. CSculptTool::OnLMouseUp3D( pView, nFlags, vPoint );
  740. m_InPaintingMode = false;
  741. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  742. if( pDispMgr )
  743. {
  744. pDispMgr->PostUndo();
  745. }
  746. return true;
  747. }
  748. //-----------------------------------------------------------------------------
  749. // Purpose: handles the left mouse button down in the 3d view
  750. // Input : pView - the 3d view
  751. // nFlags - the button flags
  752. // vPoint - the mouse point
  753. // Output : returns true if successful
  754. //-----------------------------------------------------------------------------
  755. bool CSculptPainter::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  756. {
  757. CSculptTool::OnLMouseDown3D( pView, nFlags, vPoint );
  758. m_InPaintingMode = true;
  759. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  760. if( pDispMgr )
  761. {
  762. pDispMgr->PreUndo( "Displacement Modifier" );
  763. }
  764. return true;
  765. }
  766. //-----------------------------------------------------------------------------
  767. // Purpose: handles the right mouse button up in the 3d view
  768. // Input : pView - the 3d view
  769. // nFlags - the button flags
  770. // vPoint - the mouse point
  771. // Output : returns true if successful
  772. //-----------------------------------------------------------------------------
  773. bool CSculptPainter::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  774. {
  775. CSculptTool::OnRMouseUp3D( pView, nFlags, vPoint );
  776. m_InSizingMode = false;
  777. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  778. if( pDispMgr )
  779. {
  780. pDispMgr->PostUndo();
  781. }
  782. return true;
  783. }
  784. //-----------------------------------------------------------------------------
  785. // Purpose: handles the right mouse button down in the 3d view
  786. // Input : pView - the 3d view
  787. // nFlags - the button flags
  788. // vPoint - the mouse point
  789. // Output : returns true if successful
  790. //-----------------------------------------------------------------------------
  791. bool CSculptPainter::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  792. {
  793. CSculptTool::OnRMouseDown3D( pView, nFlags, vPoint );
  794. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  795. if( pDispMgr )
  796. {
  797. pDispMgr->PreUndo( "Displacement Modifier" );
  798. }
  799. return true;
  800. }
  801. //-----------------------------------------------------------------------------
  802. // Purpose: handles the mouse move in the 3d view
  803. // Input : pView - the 3d view
  804. // nFlags - the button flags
  805. // vPoint - the mouse point
  806. // Output : returns true if successful
  807. //-----------------------------------------------------------------------------
  808. bool CSculptPainter::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  809. {
  810. return CSculptTool::OnMouseMove3D( pView, nFlags, vPoint );
  811. }
  812. //-----------------------------------------------------------------------------
  813. // Purpose: toggles the sizing mode
  814. // Input : vPoint - the mouse point
  815. // Output : returns true if successful
  816. //-----------------------------------------------------------------------------
  817. bool CSculptPainter::DoSizing( const Vector2D &vPoint )
  818. {
  819. if ( !m_InSizingMode )
  820. {
  821. m_InSizingMode = true;
  822. m_StartSizingPoint = vPoint;
  823. m_OrigBrushSize = m_BrushSize;
  824. }
  825. else
  826. {
  827. m_BrushSize = m_OrigBrushSize + ( vPoint.x - m_StartSizingPoint.x );
  828. if ( m_BrushSize < 1.0f )
  829. {
  830. m_BrushSize = 1.0f;
  831. }
  832. }
  833. return true;
  834. }
  835. // CSculptPushOptions dialog
  836. IMPLEMENT_DYNAMIC(CSculptPushOptions, CDialog)
  837. //-----------------------------------------------------------------------------
  838. // Purpose: constructor
  839. //-----------------------------------------------------------------------------
  840. CSculptPushOptions::CSculptPushOptions(CWnd* pParent /*=NULL*/) :
  841. CDialog(CSculptPushOptions::IDD, pParent),
  842. CSculptPainter()
  843. {
  844. m_OffsetMode = OFFSET_MODE_ABSOLUTE;
  845. m_NormalMode = NORMAL_MODE_Z;
  846. m_DensityMode = DENSITY_MODE_ADDITIVE;
  847. m_OffsetDistance = 10.0f;
  848. m_OffsetAmount = 1.0f;
  849. m_SmoothAmount = 0.2f;
  850. m_Direction = 1.0f;
  851. m_SelectedNormal.Init( 0.0f, 0.0f, 0.0f );
  852. m_flFalloffSpot = 0.5f;
  853. m_flFalloffEndingValue = 0.0f;
  854. }
  855. //-----------------------------------------------------------------------------
  856. // Purpose: destructor
  857. //-----------------------------------------------------------------------------
  858. CSculptPushOptions::~CSculptPushOptions()
  859. {
  860. }
  861. //-----------------------------------------------------------------------------
  862. // Purpose: initializes the dialog
  863. // Output : returns true if successful
  864. //-----------------------------------------------------------------------------
  865. BOOL CSculptPushOptions::OnInitDialog( void )
  866. {
  867. char temp[ 1024 ];
  868. CDialog::OnInitDialog();
  869. m_OffsetModeControl.InsertString( -1, "Adaptive" );
  870. m_OffsetModeControl.InsertString( -1, "Absolute" );
  871. m_OffsetModeControl.SetCurSel( m_OffsetMode );
  872. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  873. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  874. sprintf( temp, "%g", m_OffsetDistance );
  875. m_OffsetDistanceControl.SetWindowText( temp );
  876. sprintf( temp, "%g%%", m_OffsetAmount * 100.0f );
  877. m_OffsetAmountControl.SetWindowText( temp );
  878. sprintf( temp, "%g%%", m_SmoothAmount * 100.0f );
  879. m_SmoothAmountControl.SetWindowText( temp );
  880. sprintf( temp, "%g%%", m_flFalloffSpot * 100.0f );
  881. m_FalloffPositionControl.SetWindowText( temp );
  882. sprintf( temp, "%g%%", m_flFalloffEndingValue * 100.0f );
  883. m_FalloffFinalControl.SetWindowText( temp );
  884. m_NormalModeControl.InsertString( -1, "Brush Center" );
  885. m_NormalModeControl.InsertString( -1, "Screen" );
  886. m_NormalModeControl.InsertString( -1, "Screen XY" );
  887. m_NormalModeControl.InsertString( -1, "X" );
  888. m_NormalModeControl.InsertString( -1, "Y" );
  889. m_NormalModeControl.InsertString( -1, "Z" );
  890. m_NormalModeControl.InsertString( -1, "Selected" );
  891. m_NormalModeControl.SetCurSel( m_NormalMode );
  892. m_DensityModeControl.InsertString( -1, "Additive" );
  893. m_DensityModeControl.InsertString( -1, "Attenuated" );
  894. m_DensityModeControl.SetCurSel( m_DensityMode );
  895. return TRUE;
  896. }
  897. //-----------------------------------------------------------------------------
  898. // Purpose: prevent the dialog from closing
  899. //-----------------------------------------------------------------------------
  900. void CSculptPushOptions::OnOK()
  901. {
  902. }
  903. //-----------------------------------------------------------------------------
  904. // Purpose: prevent the dialog from closing
  905. //-----------------------------------------------------------------------------
  906. void CSculptPushOptions::OnCancel()
  907. {
  908. }
  909. //-----------------------------------------------------------------------------
  910. // Purpose: set up the data exchange for the variables
  911. // Input : pDX - the data exchange object
  912. //-----------------------------------------------------------------------------
  913. void CSculptPushOptions::DoDataExchange(CDataExchange* pDX)
  914. {
  915. CDialog::DoDataExchange(pDX);
  916. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, m_OffsetModeControl);
  917. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, m_OffsetDistanceControl);
  918. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, m_OffsetAmountControl);
  919. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, m_SmoothAmountControl);
  920. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, m_DensityModeControl);
  921. DDX_Control(pDX, IDC_IDC_SCULPT_PUSH_OPTION_NORMAL_MODE, m_NormalModeControl);
  922. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_FALLOFF_POSITION, m_FalloffPositionControl);
  923. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_FALLOFF_FINAL, m_FalloffFinalControl);
  924. }
  925. BEGIN_MESSAGE_MAP(CSculptPushOptions, CDialog)
  926. ON_CBN_SELCHANGE(IDC_IDC_SCULPT_PUSH_OPTION_NORMAL_MODE, &CSculptPushOptions::OnCbnSelchangeIdcSculptPushOptionNormalMode)
  927. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, &CSculptPushOptions::OnCbnSelchangeSculptPushOptionOffsetMode)
  928. ON_EN_CHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, &CSculptPushOptions::OnEnChangeSculptPushOptionOffsetDistance)
  929. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, &CSculptPushOptions::OnCbnSelchangeSculptPushOptionDensityMode)
  930. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, &CSculptPushOptions::OnEnKillfocusSculptPushOptionSmoothAmount)
  931. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, &CSculptPushOptions::OnEnKillfocusSculptPushOptionOffsetAmount)
  932. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_FALLOFF_POSITION, &CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffPosition)
  933. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_FALLOFF_FINAL, &CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffFinal)
  934. END_MESSAGE_MAP()
  935. //-----------------------------------------------------------------------------
  936. // Purpose: sets the normal mode of the sculpt operation
  937. //-----------------------------------------------------------------------------
  938. void CSculptPushOptions::OnCbnSelchangeIdcSculptPushOptionNormalMode()
  939. {
  940. m_NormalMode = ( NormalMode )m_NormalModeControl.GetCurSel();
  941. }
  942. //-----------------------------------------------------------------------------
  943. // Purpose: sets the offset mode of the sculpt operation
  944. //-----------------------------------------------------------------------------
  945. void CSculptPushOptions::OnCbnSelchangeSculptPushOptionOffsetMode()
  946. {
  947. m_OffsetMode = ( OffsetMode )m_OffsetModeControl.GetCurSel();
  948. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  949. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  950. }
  951. //-----------------------------------------------------------------------------
  952. // Purpose: setup for starting to paint on the displacement
  953. // Input : pView - the 3d view
  954. // vPoint - the initial click point
  955. // Output : returns true if successful
  956. //-----------------------------------------------------------------------------
  957. bool CSculptPushOptions::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  958. {
  959. __super::BeginPaint( pView, vPoint );
  960. if ( m_bCtrlDown )
  961. {
  962. m_Direction = -1.0f;
  963. }
  964. else
  965. {
  966. m_Direction = 1.0f;
  967. }
  968. return true;
  969. }
  970. //-----------------------------------------------------------------------------
  971. // Purpose: draws the tool in the 3d view
  972. // Input : pRender - the 3d renderer
  973. //-----------------------------------------------------------------------------
  974. void CSculptPushOptions::RenderTool3D( CRender3D *pRender )
  975. {
  976. // pRender->DrawText( "mouse", m_MousePoint.x, m_MousePoint.y, 0 );
  977. // Msg( "%g %g\n", m_MousePoint.x, m_MousePoint.y );
  978. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  979. if ( m_InSizingMode )
  980. { // yellow for sizing mode
  981. pRender->BeginClientSpace();
  982. pRender->SetDrawColor( 255, 255, 0 );
  983. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  984. if ( m_flFalloffSpot > 0.0f )
  985. {
  986. pRender->SetDrawColor( 192, 192, 0 );
  987. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  988. }
  989. pRender->EndClientSpace();
  990. }
  991. else if ( m_bShiftDown )
  992. { // purple for smoothing
  993. pRender->SetDrawColor( 255, 0, 255 );
  994. pRender->BeginClientSpace();
  995. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  996. pRender->EndClientSpace();
  997. }
  998. else if ( m_bCtrlDown )
  999. { // red for negative sculpting
  1000. pRender->BeginClientSpace();
  1001. pRender->SetDrawColor( 255, 0, 0 );
  1002. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  1003. if ( m_flFalloffSpot > 0.0f )
  1004. {
  1005. pRender->SetDrawColor( 192, 0, 0 );
  1006. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  1007. }
  1008. pRender->EndClientSpace();
  1009. Vector vPaintAxis;
  1010. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  1011. DrawDirection( pRender, -vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  1012. }
  1013. else
  1014. { // green for positive sculpting
  1015. pRender->BeginClientSpace();
  1016. pRender->SetDrawColor( 0, 255, 0 );
  1017. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  1018. if ( m_flFalloffSpot > 0.0f )
  1019. {
  1020. pRender->SetDrawColor( 0, 192, 0 );
  1021. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  1022. }
  1023. pRender->EndClientSpace();
  1024. Vector vPaintAxis;
  1025. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  1026. DrawDirection( pRender, vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  1027. }
  1028. #if 0
  1029. FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept );
  1030. Vector2D RadiusPoint = m_MousePoint;
  1031. Vector vecStart, vecEnd;
  1032. RadiusPoint.x += m_BrushSize;
  1033. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  1034. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  1035. pRender->RenderWireframeSphere( m_CurrentCollisionPoint, m_CurrentProjectedRadius, 12, 12, 0, 255, 255 );
  1036. #endif
  1037. #if 0
  1038. // Get the displacement manager from the active map document.
  1039. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  1040. // For each displacement surface is the selection list attempt to paint on it.
  1041. int nDispCount = pDispMgr->SelectCount();
  1042. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  1043. {
  1044. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  1045. if ( pDisp )
  1046. {
  1047. CMapDisp *OrigDisp = NULL;
  1048. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  1049. if ( index != m_OrigMapDisp.InvalidIndex() )
  1050. {
  1051. OrigDisp = m_OrigMapDisp[ index ];
  1052. }
  1053. Vector vPaintPos, vVert;
  1054. int nVertCount = pDisp->GetSize();
  1055. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  1056. {
  1057. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, false ) )
  1058. {
  1059. // Get the current vert.
  1060. pDisp->GetVert( iVert, vVert );
  1061. }
  1062. }
  1063. }
  1064. }
  1065. #endif
  1066. pRender->PopRenderMode();
  1067. #if 0
  1068. if ( !FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept ) )
  1069. {
  1070. return;
  1071. }
  1072. Vector2D RadiusPoint = m_MousePoint;
  1073. Vector vecStart, vecEnd;
  1074. RadiusPoint.x += m_BrushSize;
  1075. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  1076. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  1077. Msg( "Dist = %g at %g,%g,%g\n", m_CurrentProjectedRadius, m_CurrentCollisionPoint.x, m_CurrentCollisionPoint.y, m_CurrentCollisionPoint.z );
  1078. #endif
  1079. }
  1080. //-----------------------------------------------------------------------------
  1081. // Purpose: handles the right mouse button down in the 3d view
  1082. // Input : pView - the 3d view
  1083. // nFlags - the button flags
  1084. // vPoint - the mouse point
  1085. // Output : returns true if successful
  1086. //-----------------------------------------------------------------------------
  1087. bool CSculptPushOptions::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  1088. {
  1089. CSculptTool::OnRMouseDown3D( pView, nFlags, vPoint );
  1090. if ( m_bAltDown )
  1091. {
  1092. m_NormalMode = NORMAL_MODE_Z;
  1093. m_NormalModeControl.SetCurSel( m_NormalMode );
  1094. #if 0
  1095. //
  1096. // check for closest solid object
  1097. //
  1098. ULONG ulFace;
  1099. CMapClass *pObject;
  1100. if( ( ( pObject = pView->NearestObjectAt( vPoint, ulFace ) ) != NULL ) )
  1101. {
  1102. if( pObject->IsMapClass( MAPCLASS_TYPE( CMapSolid ) ) )
  1103. {
  1104. // get the solid
  1105. CMapSolid *pSolid = ( CMapSolid* )pObject;
  1106. if( !pSolid )
  1107. {
  1108. return true;
  1109. }
  1110. // trace a line and get the normal -- will get a displacement normal
  1111. // if one exists
  1112. CMapFace *pFace = pSolid->GetFace( ulFace );
  1113. if( !pFace )
  1114. {
  1115. return true;
  1116. }
  1117. Vector vRayStart, vRayEnd;
  1118. pView->GetCamera()->BuildRay( vPoint, vRayStart, vRayEnd );
  1119. Vector vHitPos, vHitNormal;
  1120. if( pFace->TraceLine( vHitPos, vHitNormal, vRayStart, vRayEnd ) )
  1121. {
  1122. // set the paint direction
  1123. m_SelectedNormal = vHitNormal;
  1124. m_NormalMode = NORMAL_MODE_SELECTED;
  1125. m_NormalModeControl.SetCurSel( m_NormalMode );
  1126. }
  1127. }
  1128. }
  1129. #else
  1130. Vector CollisionPoint, CollisionNormal;
  1131. float CollisionIntercept;
  1132. if ( FindCollisionIntercept( pView->GetCamera(), vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept ) )
  1133. {
  1134. // set the paint direction
  1135. m_SelectedNormal = -CollisionNormal;
  1136. m_NormalMode = NORMAL_MODE_SELECTED;
  1137. m_NormalModeControl.SetCurSel( m_NormalMode );
  1138. }
  1139. #endif
  1140. }
  1141. return true;
  1142. }
  1143. //-----------------------------------------------------------------------------
  1144. // Purpose: returns the painting direction
  1145. // Input : pCamera - the 3d camera
  1146. // vPoint - the 2d mouse point
  1147. // Output : vPaintAxis - the direction the painting should go
  1148. //-----------------------------------------------------------------------------
  1149. void CSculptPushOptions::GetPaintAxis( CCamera *pCamera, const Vector2D &vPoint, Vector &vPaintAxis )
  1150. {
  1151. switch( m_NormalMode )
  1152. {
  1153. case NORMAL_MODE_SCREEN:
  1154. pCamera->GetViewForward( vPaintAxis );
  1155. vPaintAxis = -vPaintAxis;
  1156. break;
  1157. case NORMAL_MODE_SCREEN_XY:
  1158. pCamera->GetViewForward( vPaintAxis );
  1159. vPaintAxis = -vPaintAxis;
  1160. vPaintAxis.z = 0.f;
  1161. break;
  1162. case NORMAL_MODE_BRUSH_CENTER:
  1163. if ( !m_InPaintingMode )
  1164. {
  1165. Vector CollisionPoint, CollisionNormal;
  1166. float CollisionIntercept;
  1167. FindCollisionIntercept( pCamera, vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept );
  1168. vPaintAxis = -CollisionNormal;
  1169. }
  1170. else
  1171. {
  1172. vPaintAxis = -m_StartingCollisionNormal;
  1173. }
  1174. break;
  1175. case NORMAL_MODE_X:
  1176. vPaintAxis.Init( 1.0f, 0.0f, 0.0f );
  1177. break;
  1178. case NORMAL_MODE_Y:
  1179. vPaintAxis.Init( 0.0f, 1.0f, 0.0f );
  1180. break;
  1181. case NORMAL_MODE_Z:
  1182. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  1183. break;
  1184. case NORMAL_MODE_SELECTED:
  1185. vPaintAxis = m_SelectedNormal;
  1186. break;
  1187. default:
  1188. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  1189. }
  1190. }
  1191. //-----------------------------------------------------------------------------
  1192. // Purpose: applies the specific push operation onto the displacement
  1193. // Input : pView - the 3d view
  1194. // vPoint - the mouse point
  1195. // pDisp - the displacement to apply the push to
  1196. // pOrigDisp - the original displacement prior to any adjustments
  1197. //-----------------------------------------------------------------------------
  1198. void CSculptPushOptions::DoPaintOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  1199. {
  1200. Vector vPaintPos, vVert, vDirection;
  1201. float flMaxDistance = 0.0f;
  1202. float flDistance;
  1203. float flLengthPercent;
  1204. Vector vPaintAxis;
  1205. if ( m_bShiftDown )
  1206. {
  1207. // DoSmoothOperation( pView, vPoint, pDisp, pOrigDisp );
  1208. // m_SpatialData.m_flRadius = 256.0f;
  1209. // m_SpatialData.m_flScalar = 5.0f / m_SmoothAmount;
  1210. // m_SpatialData.m_flRadius = m_StartingProjectedRadius * 1.5f;
  1211. m_SpatialData.m_flRadius = m_CurrentProjectedRadius * 2.0f;
  1212. m_SpatialData.m_flRadius2 = ( m_SpatialData.m_flRadius * m_SpatialData.m_flRadius );
  1213. m_SpatialData.m_flOORadius2 = 1.0f / m_SpatialData.m_flRadius2;
  1214. m_SpatialData.m_flScalar = 10.0f / m_SmoothAmount;
  1215. m_SpatialData.m_vCenter = m_CurrentCollisionPoint;
  1216. DoPaintSmooth( pView, vPoint, pDisp, pOrigDisp );
  1217. return;
  1218. }
  1219. GetPaintAxis( pView->GetCamera(), vPoint, vPaintAxis );
  1220. vDirection = vPaintAxis * m_Direction;
  1221. switch( m_OffsetMode )
  1222. {
  1223. case OFFSET_MODE_ADAPTIVE:
  1224. flMaxDistance = m_StartingProjectedRadius * m_OffsetAmount;
  1225. break;
  1226. case OFFSET_MODE_ABSOLUTE:
  1227. flMaxDistance = m_OffsetDistance;
  1228. break;
  1229. }
  1230. int nVertCount = pDisp->GetSize();
  1231. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  1232. {
  1233. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, true, false, &flLengthPercent ) )
  1234. {
  1235. pDisp->GetVert( iVert, vVert );
  1236. if ( flLengthPercent > m_flFalloffSpot )
  1237. {
  1238. flLengthPercent = ( flLengthPercent - m_flFalloffSpot ) / ( 1.0f - m_flFalloffSpot );
  1239. flLengthPercent = 1.0 - flLengthPercent;
  1240. flDistance = ( ( 1.0f - m_flFalloffEndingValue ) * flLengthPercent * flMaxDistance ) + ( m_flFalloffEndingValue * flMaxDistance );
  1241. }
  1242. else
  1243. {
  1244. flDistance = flMaxDistance;
  1245. }
  1246. if ( flDistance == 0.0f )
  1247. {
  1248. continue;
  1249. }
  1250. switch( m_DensityMode )
  1251. {
  1252. case DENSITY_MODE_ADDITIVE:
  1253. VectorScale( vDirection, flDistance, vPaintPos );
  1254. VectorAdd( vPaintPos, vVert, vPaintPos );
  1255. break;
  1256. case DENSITY_MODE_ATTENUATED:
  1257. VectorScale( vDirection, flDistance, vPaintPos );
  1258. VectorAdd( vPaintPos, vVert, vPaintPos );
  1259. if ( pOrigDisp )
  1260. {
  1261. Vector vOrigVert, vDiff;
  1262. float Length;
  1263. pOrigDisp->GetVert( iVert, vOrigVert );
  1264. vDiff = ( vPaintPos - vOrigVert );
  1265. Length = vDiff.Length() / flMaxDistance;
  1266. if ( Length > 1.0f )
  1267. {
  1268. Length = 1.0f;
  1269. }
  1270. vPaintPos = vOrigVert + ( Length * vDirection * flMaxDistance );
  1271. }
  1272. break;
  1273. }
  1274. AddToUndo( &pDisp );
  1275. pDisp->Paint_SetValue( iVert, vPaintPos );
  1276. }
  1277. }
  1278. }
  1279. #if 0
  1280. typedef enum
  1281. {
  1282. DISP_DIR_LEFT_TO_RIGHT = 0, // adjoining displacement is to the left
  1283. DISP_DIR_TOP_TO_BOTTOM = 1, // adjoining displacement is to the top
  1284. DISP_DIR_RIGHT_TO_LEFT = 2, // adjoining displacement is to the right
  1285. DISP_DIR_BOTTOM_TO_TOP = 3, // adjoining displacement is to the bottom
  1286. } DispDirections;
  1287. typedef enum
  1288. {
  1289. MOVE_DIR_RIGHT = 0,
  1290. MOVE_DIR_UP,
  1291. MOVE_DIR_LEFT,
  1292. MOVE_DIR_DOWN,
  1293. MOVE_DIR_MAX
  1294. } MoveDirections;
  1295. class CDispGrid
  1296. {
  1297. public:
  1298. CDispGrid( CMapDisp *pDisp, bool DoPopulate = false, int GridExpand = 2 );
  1299. ~CDispGrid( );
  1300. void Populate( CMapDisp *pDisp );
  1301. bool GetPosition( int x, int y, int OffsetX, int OffsetY, Vector &Position );
  1302. bool GetFlatPosition( int x, int y, int OffsetX, int OffsetY, Vector &FlatPosition );
  1303. void SetPosition( int x, int y, Vector &NewPosition );
  1304. void UpdatePositions( void );
  1305. void CalcSpringForce( int x, int y, int OffsetX, int OffsetY, float Ks, Vector &SpringForce );
  1306. private:
  1307. typedef struct SDispPoint
  1308. {
  1309. bool m_IsSet;
  1310. int m_DispPos;
  1311. Vector m_Position, m_UpdatePosition;
  1312. Vector m_FlatPosition;
  1313. } TDispPoint;
  1314. int m_Width, m_Height;
  1315. int m_GridWidth, m_GridHeight;
  1316. int m_GridExpand;
  1317. TDispPoint *m_Grid;
  1318. void PopulateUp( CMapDisp *pDisp );
  1319. void PopulateDown( CMapDisp *pDisp );
  1320. void PopulateRight( CMapDisp *pDisp );
  1321. void PopulateLeft( CMapDisp *pDisp );
  1322. };
  1323. CDispGrid::CDispGrid( CMapDisp *pDisp, bool DoPopulate, int GridExpand )
  1324. {
  1325. m_GridExpand = GridExpand;
  1326. m_Width = pDisp->GetWidth();
  1327. m_Height = pDisp->GetHeight();
  1328. m_GridWidth = m_Width + ( GridExpand * 2 );
  1329. m_GridHeight = m_Height + ( GridExpand * 2 );
  1330. m_Grid = new TDispPoint[ m_GridWidth * m_GridHeight ];
  1331. for( int i = 0; i < m_GridWidth * m_GridHeight; i++ )
  1332. {
  1333. m_Grid[ i ].m_IsSet = false;
  1334. }
  1335. if ( DoPopulate )
  1336. {
  1337. Populate( pDisp );
  1338. }
  1339. }
  1340. CDispGrid::~CDispGrid( )
  1341. {
  1342. delete [] m_Grid;
  1343. }
  1344. void CDispGrid::PopulateUp( CMapDisp *pDisp )
  1345. {
  1346. EditDispHandle_t handle;
  1347. int orient;
  1348. pDisp->GetEdgeNeighbor( DISP_DIR_TOP_TO_BOTTOM, handle, orient );
  1349. if ( handle == EDITDISPHANDLE_INVALID )
  1350. {
  1351. return;
  1352. }
  1353. pDisp = EditDispMgr()->GetDisp( handle );
  1354. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1355. { // don't support ones which aren't of the same subdivision
  1356. return;
  1357. }
  1358. if ( orient != MOVE_DIR_DOWN )
  1359. { // don't support rotation for now
  1360. return;
  1361. }
  1362. for( int x = 0; x < m_Width; x++ )
  1363. {
  1364. for( int y = 0; y < m_GridExpand; y++ )
  1365. {
  1366. int GridPos = ( ( m_GridHeight - y - 1 ) * m_GridWidth ) + ( x + m_GridExpand );
  1367. m_Grid[ GridPos ].m_DispPos = ( ( m_GridExpand - y ) * m_Width ) + x; // don't do inner row, as that is sewed
  1368. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1369. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1370. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1371. m_Grid[ GridPos ].m_IsSet = true;
  1372. }
  1373. }
  1374. }
  1375. void CDispGrid::PopulateDown( CMapDisp *pDisp )
  1376. {
  1377. EditDispHandle_t handle;
  1378. int orient;
  1379. pDisp->GetEdgeNeighbor( DISP_DIR_BOTTOM_TO_TOP, handle, orient );
  1380. if ( handle == EDITDISPHANDLE_INVALID )
  1381. {
  1382. return;
  1383. }
  1384. pDisp = EditDispMgr()->GetDisp( handle );
  1385. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1386. { // don't support ones which aren't of the same subdivision
  1387. return;
  1388. }
  1389. if ( orient != MOVE_DIR_UP )
  1390. { // don't support rotation for now
  1391. return;
  1392. }
  1393. for( int x = 0; x < m_Width; x++ )
  1394. {
  1395. for( int y = 0; y < m_GridExpand; y++ )
  1396. {
  1397. int GridPos = ( ( y ) * m_GridWidth ) + ( x + m_GridExpand );
  1398. m_Grid[ GridPos ].m_DispPos = ( ( m_Height - m_GridExpand + y - 1 ) * m_Width ) + x; // don't do inner row, as that is sewed
  1399. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1400. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1401. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1402. m_Grid[ GridPos ].m_IsSet = true;
  1403. }
  1404. }
  1405. }
  1406. void CDispGrid::PopulateRight( CMapDisp *pDisp )
  1407. {
  1408. EditDispHandle_t handle;
  1409. int orient;
  1410. pDisp->GetEdgeNeighbor( DISP_DIR_RIGHT_TO_LEFT, handle, orient );
  1411. if ( handle == EDITDISPHANDLE_INVALID )
  1412. {
  1413. return;
  1414. }
  1415. pDisp = EditDispMgr()->GetDisp( handle );
  1416. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1417. { // don't support ones which aren't of the same subdivision
  1418. return;
  1419. }
  1420. if ( orient != MOVE_DIR_RIGHT )
  1421. { // don't support rotation for now
  1422. return;
  1423. }
  1424. for( int x = 0; x < m_GridExpand; x++ )
  1425. {
  1426. for( int y = 0; y < m_Height; y++ )
  1427. {
  1428. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand + m_Width );
  1429. m_Grid[ GridPos ].m_DispPos = ( ( y ) * m_Width ) + x + 1; // don't do inner row, as that is sewed
  1430. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1431. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1432. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1433. m_Grid[ GridPos ].m_IsSet = true;
  1434. }
  1435. }
  1436. }
  1437. void CDispGrid::PopulateLeft( CMapDisp *pDisp )
  1438. {
  1439. EditDispHandle_t handle;
  1440. int orient;
  1441. pDisp->GetEdgeNeighbor( DISP_DIR_LEFT_TO_RIGHT, handle, orient );
  1442. if ( handle == EDITDISPHANDLE_INVALID )
  1443. {
  1444. return;
  1445. }
  1446. pDisp = EditDispMgr()->GetDisp( handle );
  1447. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1448. { // don't support ones which aren't of the same subdivision
  1449. return;
  1450. }
  1451. if ( orient != MOVE_DIR_LEFT )
  1452. { // don't support rotation for now
  1453. return;
  1454. }
  1455. for( int x = 0; x < m_GridExpand; x++ )
  1456. {
  1457. for( int y = 0; y < m_Height; y++ )
  1458. {
  1459. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x );
  1460. m_Grid[ GridPos ].m_DispPos = ( ( y ) * m_Width ) + ( m_Width - m_GridExpand + x - 1 ); // don't do inner row, as that is sewed
  1461. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1462. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1463. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1464. m_Grid[ GridPos ].m_IsSet = true;
  1465. }
  1466. }
  1467. }
  1468. void CDispGrid::Populate( CMapDisp *pDisp )
  1469. {
  1470. for( int x = 0; x < m_Width; x++ )
  1471. {
  1472. for( int y = 0; y < m_Height; y++ )
  1473. {
  1474. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1475. m_Grid[ GridPos ].m_DispPos = ( y * m_Width ) + x;
  1476. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1477. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1478. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1479. m_Grid[ GridPos ].m_IsSet = true;
  1480. }
  1481. }
  1482. PopulateUp( pDisp );
  1483. PopulateDown( pDisp );
  1484. PopulateRight( pDisp );
  1485. PopulateLeft( pDisp );
  1486. }
  1487. bool CDispGrid::GetPosition( int x, int y, int OffsetX, int OffsetY, Vector &Position )
  1488. {
  1489. x += OffsetX;
  1490. y += OffsetY;
  1491. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1492. if ( !m_Grid[ GridPos ].m_IsSet )
  1493. {
  1494. return false;
  1495. }
  1496. Position = m_Grid[ GridPos ].m_Position;
  1497. return true;
  1498. }
  1499. bool CDispGrid::GetFlatPosition( int x, int y, int OffsetX, int OffsetY, Vector &FlatPosition )
  1500. {
  1501. x += OffsetX;
  1502. y += OffsetY;
  1503. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1504. if ( !m_Grid[ GridPos ].m_IsSet )
  1505. {
  1506. return false;
  1507. }
  1508. FlatPosition = m_Grid[ GridPos ].m_FlatPosition;
  1509. return true;
  1510. }
  1511. void CDispGrid::SetPosition( int x, int y, Vector &NewPosition )
  1512. {
  1513. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1514. if ( !m_Grid[ GridPos ].m_IsSet )
  1515. {
  1516. return;
  1517. }
  1518. m_Grid[ GridPos ].m_UpdatePosition = NewPosition;
  1519. }
  1520. void CDispGrid::UpdatePositions( void )
  1521. {
  1522. for( int i = 0; i < m_GridWidth * m_GridHeight; i++ )
  1523. {
  1524. m_Grid[ i ].m_Position = m_Grid[ i ].m_UpdatePosition ;
  1525. }
  1526. }
  1527. void CDispGrid::CalcSpringForce( int x, int y, int OffsetX, int OffsetY, float Ks, Vector &SpringForce )
  1528. {
  1529. Vector currentP1, currentP2;
  1530. Vector restP1, restP2;
  1531. Vector currentDelta, restDelta;
  1532. float currentDistance, restDistance;
  1533. SpringForce.Init();
  1534. if ( !GetPosition( x, y, 0, 0, currentP1 ) )
  1535. {
  1536. return;
  1537. }
  1538. if ( !GetPosition( x, y, OffsetX, OffsetY, currentP2 ) )
  1539. {
  1540. return;
  1541. }
  1542. if ( !GetFlatPosition( x, y, 0, 0, restP1 ) )
  1543. {
  1544. return;
  1545. }
  1546. if ( !GetFlatPosition( x, y, OffsetX, OffsetY, restP2 ) )
  1547. {
  1548. return;
  1549. }
  1550. currentDelta = currentP1 - currentP2;
  1551. currentDistance = currentDelta.Length();
  1552. if ( currentDistance == 0.0f )
  1553. {
  1554. return;
  1555. }
  1556. restDelta = restP1 - restP2;
  1557. restDistance = restDelta.Length();
  1558. float Hterm = (currentDistance - restDistance) * Ks;
  1559. // VectorDifference(&p1->v,&p2->v,&deltaV); // Delta Velocity Vector
  1560. // Dterm = (DotProduct(&deltaV,&deltaP) * spring->Kd) / dist; // Damping Term
  1561. float Dterm = 0.0f;
  1562. SpringForce = currentDelta * ( 1.0f / currentDistance );
  1563. SpringForce = SpringForce * -(Hterm + Dterm);
  1564. //VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1
  1565. //VectorDifference(&p2->f,&springForce,&p2->f); // - Force on Particle 2
  1566. }
  1567. void CSculptPushOptions::DoSmoothOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  1568. {
  1569. Vector SpringForce;
  1570. int width = pDisp->GetWidth();
  1571. int height = pDisp->GetHeight();
  1572. Vector *Forces = ( Vector * )_alloca( sizeof( *Forces ) * width * height );
  1573. bool *DoCalc = ( bool * )_alloca( sizeof( *DoCalc ) * width * height );
  1574. const float SPRING_CONSTANT = 0.02f;
  1575. const float SPRING_CONSTANT_TO_NORMAL = 0.4f;
  1576. Vector SurfaceNormal;
  1577. pDisp->GetSurfNormal( SurfaceNormal );
  1578. for( int x = 0; x < width; x++ )
  1579. {
  1580. for( int y = 0; y < height; y++ )
  1581. {
  1582. int pVert = ( x * width ) + y;
  1583. Vector pos, vTestVert;
  1584. pDisp->GetVert( pVert, pos );
  1585. if ( pOrigDisp && 0 )
  1586. {
  1587. pOrigDisp->GetVert( pVert, vTestVert );
  1588. }
  1589. else
  1590. {
  1591. vTestVert = pos;
  1592. }
  1593. Vector2D ViewVert;
  1594. pView->GetCamera()->WorldToView( vTestVert, ViewVert );
  1595. Vector2D Offset = ViewVert - m_MousePoint;
  1596. float Length = Offset.Length();
  1597. if ( Length <= m_BrushSize || 0 )
  1598. {
  1599. DoCalc[ pVert ] = true;
  1600. }
  1601. else
  1602. {
  1603. DoCalc[ pVert ] = false;
  1604. }
  1605. }
  1606. }
  1607. #if 0
  1608. EditDispHandle_t handle;
  1609. int orient;
  1610. for( int i = 0; i < 4; i++ )
  1611. {
  1612. pDisp->GetEdgeNeighbor( i, handle, orient );
  1613. if ( handle != EDITDISPHANDLE_INVALID )
  1614. {
  1615. Msg( "Handle at %d orient %d\n", i, orient );
  1616. }
  1617. }
  1618. int x = 0;
  1619. int y = 0;
  1620. CMapDisp *pNextDisp = pDisp;
  1621. Vector Vert;
  1622. Vector FlatVert;
  1623. while( 1 )
  1624. {
  1625. if ( !GetAdjoiningPoint( x, y, MOVE_DIR_UP, 1, pNextDisp, Vert, FlatVert ) || pDisp != pNextDisp )
  1626. {
  1627. break;
  1628. }
  1629. y++;
  1630. }
  1631. return;
  1632. #endif
  1633. CDispGrid DispGrid( pDisp, true );
  1634. const float StepAmount = 1.0f;
  1635. float CurrentSmooth = m_SmoothAmount;
  1636. while( CurrentSmooth > 0.0f )
  1637. {
  1638. float SpringAmount;
  1639. float SpringToNormalAmount;
  1640. if ( CurrentSmooth > StepAmount )
  1641. {
  1642. SpringAmount = SPRING_CONSTANT * StepAmount;
  1643. SpringToNormalAmount = SPRING_CONSTANT_TO_NORMAL * StepAmount;
  1644. }
  1645. else
  1646. {
  1647. SpringAmount = SPRING_CONSTANT * CurrentSmooth;
  1648. SpringToNormalAmount = SPRING_CONSTANT_TO_NORMAL * CurrentSmooth;
  1649. }
  1650. CurrentSmooth -= StepAmount;
  1651. for( int x = 0; x < width; x++ )
  1652. {
  1653. for( int y = 0; y < height; y++ )
  1654. {
  1655. int pVert = ( y * width ) + x;
  1656. if ( !DoCalc[ pVert ] )
  1657. {
  1658. continue;
  1659. }
  1660. Forces[ pVert ].Init();
  1661. // structural springs
  1662. DispGrid.CalcSpringForce( x, y, 1, 0, SpringAmount, SpringForce );
  1663. Forces[ pVert ] += SpringForce;
  1664. DispGrid.CalcSpringForce( x, y, -1, 0, SpringAmount, SpringForce );
  1665. Forces[ pVert ] += SpringForce;
  1666. DispGrid.CalcSpringForce( x, y, 0, 1, SpringAmount, SpringForce );
  1667. Forces[ pVert ] += SpringForce;
  1668. DispGrid.CalcSpringForce( x, y, 0, -1, SpringAmount, SpringForce );
  1669. Forces[ pVert ] += SpringForce;
  1670. // shear springs
  1671. DispGrid.CalcSpringForce( x, y, 1, 1, SpringAmount, SpringForce );
  1672. Forces[ pVert ] += SpringForce;
  1673. DispGrid.CalcSpringForce( x, y, -1, 1, SpringAmount, SpringForce );
  1674. Forces[ pVert ] += SpringForce;
  1675. DispGrid.CalcSpringForce( x, y, 1, -1, SpringAmount, SpringForce );
  1676. Forces[ pVert ] += SpringForce;
  1677. DispGrid.CalcSpringForce( x, y, -1, -1, SpringAmount, SpringForce );
  1678. Forces[ pVert ] += SpringForce;
  1679. // bend springs
  1680. DispGrid.CalcSpringForce( x, y, 2, 0, SpringAmount, SpringForce );
  1681. Forces[ pVert ] += SpringForce;
  1682. DispGrid.CalcSpringForce( x, y, -2, 0, SpringAmount, SpringForce );
  1683. Forces[ pVert ] += SpringForce;
  1684. DispGrid.CalcSpringForce( x, y, 0, 2, SpringAmount, SpringForce );
  1685. Forces[ pVert ] += SpringForce;
  1686. DispGrid.CalcSpringForce( x, y, 0, -2, SpringAmount, SpringForce );
  1687. Forces[ pVert ] += SpringForce;
  1688. Vector Vert, FlatVert, FlatVertExtended, ClosestPoint;
  1689. DispGrid.GetPosition( x, y, 0, 0, Vert );
  1690. DispGrid.GetFlatPosition( x, y, 0, 0, FlatVert );
  1691. FlatVertExtended = FlatVert + ( SurfaceNormal * 10.0f );
  1692. CalcClosestPointOnLine( Vert, FlatVert, FlatVertExtended, ClosestPoint );
  1693. Vector Difference = ( Vert - ClosestPoint );
  1694. float Distance = Difference.Length();
  1695. if ( Distance > 0.0f )
  1696. {
  1697. float Hterm = Distance * SpringToNormalAmount;
  1698. float Dterm = 0.0f;
  1699. SpringForce = ( Difference ) * ( 1.0f / Distance );
  1700. SpringForce = SpringForce * -(Hterm + Dterm);
  1701. Forces[ pVert ] += SpringForce;
  1702. }
  1703. Vector pos;
  1704. DispGrid.GetPosition( x, y, 0, 0, pos );
  1705. pos += Forces[ pVert ];
  1706. AddToUndo( &pDisp );
  1707. pDisp->Paint_SetValue( pVert, pos );
  1708. DispGrid.SetPosition( x, y, pos );
  1709. }
  1710. }
  1711. DispGrid.UpdatePositions();
  1712. }
  1713. }
  1714. #endif
  1715. //-----------------------------------------------------------------------------
  1716. // Purpose: sets the offset distance
  1717. //-----------------------------------------------------------------------------
  1718. void CSculptPushOptions::OnEnChangeSculptPushOptionOffsetDistance()
  1719. {
  1720. char temp[ 1024 ];
  1721. m_OffsetDistanceControl.GetWindowText( temp, sizeof( temp ) );
  1722. m_OffsetDistance = atof( temp );
  1723. }
  1724. //-----------------------------------------------------------------------------
  1725. // Purpose: sets the density mode
  1726. //-----------------------------------------------------------------------------
  1727. void CSculptPushOptions::OnCbnSelchangeSculptPushOptionDensityMode()
  1728. {
  1729. m_DensityMode = ( DensityMode )m_DensityModeControl.GetCurSel();
  1730. }
  1731. //-----------------------------------------------------------------------------
  1732. // Purpose: sets the smooth amount
  1733. //-----------------------------------------------------------------------------
  1734. void CSculptPushOptions::OnEnKillfocusSculptPushOptionSmoothAmount()
  1735. {
  1736. char temp[ 1024 ], t2[ 1024 ];
  1737. m_SmoothAmountControl.GetWindowText( temp, sizeof( temp ) );
  1738. sscanf( temp, "%f%%", &m_SmoothAmount );
  1739. m_SmoothAmount /= 100.0f;
  1740. if ( m_SmoothAmount <= 0.0f )
  1741. {
  1742. m_SmoothAmount = 0.2f;
  1743. }
  1744. sprintf( t2, "%g%%", m_SmoothAmount * 100.0f );
  1745. if ( strcmpi( temp, t2 ) != 0 )
  1746. {
  1747. m_SmoothAmountControl.SetWindowText( t2 );
  1748. }
  1749. }
  1750. //-----------------------------------------------------------------------------
  1751. // Purpose: sets the offset amount
  1752. //-----------------------------------------------------------------------------
  1753. void CSculptPushOptions::OnEnKillfocusSculptPushOptionOffsetAmount()
  1754. {
  1755. char temp[ 1024 ], t2[ 1024 ];
  1756. m_OffsetAmountControl.GetWindowText( temp, sizeof( temp ) );
  1757. sscanf( temp, "%f%%", &m_OffsetAmount );
  1758. m_OffsetAmount /= 100.0f;
  1759. if ( m_OffsetAmount <= 0.0f )
  1760. {
  1761. m_OffsetAmount = 1.0f;
  1762. }
  1763. sprintf( t2, "%g%%", m_OffsetAmount * 100.0f );
  1764. if ( strcmpi( temp, t2 ) != 0 )
  1765. {
  1766. m_OffsetAmountControl.SetWindowText( t2 );
  1767. }
  1768. }
  1769. void CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffPosition()
  1770. {
  1771. char temp[ 1024 ], t2[ 1024 ];
  1772. m_FalloffPositionControl.GetWindowText( temp, sizeof( temp ) );
  1773. sscanf( temp, "%f%%", &m_flFalloffSpot );
  1774. m_flFalloffSpot /= 100.0f;
  1775. if ( m_flFalloffSpot <= 0.0f )
  1776. {
  1777. m_flFalloffSpot = 0.0f;
  1778. }
  1779. if ( m_flFalloffSpot > 1.0f )
  1780. {
  1781. m_flFalloffSpot = 1.0f;
  1782. }
  1783. sprintf( t2, "%g%%", m_flFalloffSpot * 100.0f );
  1784. if ( strcmpi( temp, t2 ) != 0 )
  1785. {
  1786. m_FalloffPositionControl.SetWindowText( t2 );
  1787. }
  1788. }
  1789. void CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffFinal()
  1790. {
  1791. char temp[ 1024 ], t2[ 1024 ];
  1792. m_FalloffFinalControl.GetWindowText( temp, sizeof( temp ) );
  1793. sscanf( temp, "%f%%", &m_flFalloffEndingValue);
  1794. m_flFalloffEndingValue /= 100.0f;
  1795. if ( m_flFalloffEndingValue <= 0.0f )
  1796. {
  1797. m_flFalloffEndingValue = 0.0f;
  1798. }
  1799. if ( m_flFalloffEndingValue > 1.0f )
  1800. {
  1801. m_flFalloffEndingValue = 1.0f;
  1802. }
  1803. sprintf( t2, "%g%%", m_flFalloffEndingValue * 100.0f );
  1804. if ( strcmpi( temp, t2 ) != 0 )
  1805. {
  1806. m_FalloffFinalControl.SetWindowText( t2 );
  1807. }
  1808. }
  1809. // CSculptCarveOptions dialog
  1810. IMPLEMENT_DYNAMIC(CSculptCarveOptions, CDialog)
  1811. //-----------------------------------------------------------------------------
  1812. // Purpose: constructor
  1813. //-----------------------------------------------------------------------------
  1814. CSculptCarveOptions::CSculptCarveOptions(CWnd* pParent /*=NULL*/) :
  1815. CDialog(CSculptCarveOptions::IDD, pParent),
  1816. CSculptPainter()
  1817. {
  1818. m_OffsetMode = OFFSET_MODE_ABSOLUTE;
  1819. m_NormalMode = NORMAL_MODE_Z;
  1820. m_DensityMode = DENSITY_MODE_ADDITIVE;
  1821. m_OffsetDistance = 10.0f;
  1822. m_OffsetAmount = 1.0f;
  1823. m_SmoothAmount = 0.2f;
  1824. m_Direction = 1.0f;
  1825. m_SelectedNormal.Init( 0.0f, 0.0f, 0.0f );
  1826. m_BrushLocation = -1;
  1827. m_StartLine.Init( -1.0f, -1.0f );
  1828. m_EndLine.Init( -1.0f, -1.0f );
  1829. for( int i = 0; i < MAX_SCULPT_SIZE; i++ )
  1830. {
  1831. m_BrushPoints[ i ] = ( i / ( float )MAX_SCULPT_SIZE ); // 0.0f;
  1832. }
  1833. }
  1834. //-----------------------------------------------------------------------------
  1835. // Purpose: destructor
  1836. //-----------------------------------------------------------------------------
  1837. CSculptCarveOptions::~CSculptCarveOptions()
  1838. {
  1839. }
  1840. //-----------------------------------------------------------------------------
  1841. // Purpose: initializes the dialog
  1842. // Output : returns true if successful
  1843. //-----------------------------------------------------------------------------
  1844. BOOL CSculptCarveOptions::OnInitDialog( )
  1845. {
  1846. char temp[ 1024 ];
  1847. CDialog::OnInitDialog();
  1848. m_OffsetModeControl.InsertString( -1, "Adaptive" );
  1849. m_OffsetModeControl.InsertString( -1, "Absolute" );
  1850. m_OffsetModeControl.SetCurSel( m_OffsetMode );
  1851. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  1852. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  1853. sprintf( temp, "%g", m_OffsetDistance );
  1854. m_OffsetDistanceControl.SetWindowText( temp );
  1855. sprintf( temp, "%g%%", m_OffsetAmount * 100.0f );
  1856. m_OffsetAmountControl.SetWindowText( temp );
  1857. sprintf( temp, "%g%%", m_SmoothAmount * 100.0f );
  1858. m_SmoothAmountControl.SetWindowText( temp );
  1859. m_NormalModeControl.InsertString( -1, "Brush Center" );
  1860. m_NormalModeControl.InsertString( -1, "Screen" );
  1861. m_NormalModeControl.InsertString( -1, "Screen XY" );
  1862. m_NormalModeControl.InsertString( -1, "X" );
  1863. m_NormalModeControl.InsertString( -1, "Y" );
  1864. m_NormalModeControl.InsertString( -1, "Z" );
  1865. m_NormalModeControl.InsertString( -1, "Selected" );
  1866. m_NormalModeControl.SetCurSel( m_NormalMode );
  1867. m_DensityModeControl.InsertString( -1, "Additive" );
  1868. m_DensityModeControl.InsertString( -1, "Attenuated" );
  1869. m_DensityModeControl.SetCurSel( m_DensityMode );
  1870. return TRUE;
  1871. }
  1872. //-----------------------------------------------------------------------------
  1873. // Purpose: prevent the dialog from closing
  1874. //-----------------------------------------------------------------------------
  1875. void CSculptCarveOptions::OnOK( )
  1876. {
  1877. }
  1878. //-----------------------------------------------------------------------------
  1879. // Purpose: prevent the dialog from closing
  1880. //-----------------------------------------------------------------------------
  1881. void CSculptCarveOptions::OnCancel( )
  1882. {
  1883. }
  1884. //-----------------------------------------------------------------------------
  1885. // Purpose: set up the data exchange for the variables
  1886. // Input : pDX - the data exchange object
  1887. //-----------------------------------------------------------------------------
  1888. void CSculptCarveOptions::DoDataExchange(CDataExchange* pDX)
  1889. {
  1890. CDialog::DoDataExchange(pDX);
  1891. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, m_OffsetModeControl);
  1892. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, m_OffsetDistanceControl);
  1893. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, m_OffsetAmountControl);
  1894. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, m_SmoothAmountControl);
  1895. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, m_DensityModeControl);
  1896. DDX_Control(pDX, IDC_IDC_SCULPT_PUSH_OPTION_NORMAL_MODE, m_NormalModeControl);
  1897. DDX_Control(pDX, IDC_CARVE_BRUSH, m_CarveBrushControl);
  1898. }
  1899. BEGIN_MESSAGE_MAP(CSculptCarveOptions, CDialog)
  1900. ON_CBN_SELCHANGE(IDC_IDC_SCULPT_PUSH_OPTION_NORMAL_MODE, &CSculptCarveOptions::OnCbnSelchangeIdcSculptPushOptionNormalMode)
  1901. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, &CSculptCarveOptions::OnCbnSelchangeSculptPushOptionOffsetMode)
  1902. ON_EN_CHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, &CSculptCarveOptions::OnEnChangeSculptPushOptionOffsetDistance)
  1903. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, &CSculptCarveOptions::OnCbnSelchangeSculptPushOptionDensityMode)
  1904. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, &CSculptCarveOptions::OnEnKillfocusSculptPushOptionSmoothAmount)
  1905. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, &CSculptCarveOptions::OnEnKillfocusSculptPushOptionOffsetAmount)
  1906. ON_WM_PAINT()
  1907. ON_WM_LBUTTONDOWN()
  1908. ON_WM_LBUTTONUP()
  1909. ON_WM_MOUSEMOVE()
  1910. END_MESSAGE_MAP()
  1911. //-----------------------------------------------------------------------------
  1912. // Purpose: sets the normal mode
  1913. //-----------------------------------------------------------------------------
  1914. void CSculptCarveOptions::OnCbnSelchangeIdcSculptPushOptionNormalMode()
  1915. {
  1916. m_NormalMode = ( NormalMode )m_NormalModeControl.GetCurSel();
  1917. }
  1918. //-----------------------------------------------------------------------------
  1919. // Purpose: sets the offset mode
  1920. //-----------------------------------------------------------------------------
  1921. void CSculptCarveOptions::OnCbnSelchangeSculptPushOptionOffsetMode()
  1922. {
  1923. m_OffsetMode = ( OffsetMode )m_OffsetModeControl.GetCurSel();
  1924. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  1925. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  1926. }
  1927. //-----------------------------------------------------------------------------
  1928. // Purpose: setup for starting to paint on the displacement
  1929. // Input : pView - the 3d view
  1930. // vPoint - the initial click point
  1931. // Output : returns true if successful
  1932. //-----------------------------------------------------------------------------
  1933. bool CSculptCarveOptions::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  1934. {
  1935. __super::BeginPaint( pView, vPoint );
  1936. if ( m_bCtrlDown )
  1937. {
  1938. m_Direction = -1.0f;
  1939. }
  1940. else
  1941. {
  1942. m_Direction = 1.0f;
  1943. }
  1944. return true;
  1945. }
  1946. //-----------------------------------------------------------------------------
  1947. // Purpose: calculates the normal / direction of the drawing line
  1948. // Input : nPointIndex - which point to factor from
  1949. // Output : returns true if we found a valid normal
  1950. // vNormal - the normal we found
  1951. //-----------------------------------------------------------------------------
  1952. #if 0
  1953. bool CSculptCarveOptions::CalculatePointNormal( int nPointIndex, Vector2D &vNormal )
  1954. {
  1955. float count = 0.0;
  1956. Vector2D vAverage( 0.0f, 0.0f );
  1957. const int max_backsize = 3;
  1958. // keep going back from the current point until you get a total distance
  1959. for( int j = 0; j < max_backsize; j++ )
  1960. {
  1961. int index = ( nPointIndex - max_backsize + j );
  1962. if ( index < 0 )
  1963. {
  1964. continue;
  1965. }
  1966. int index2 = nPointIndex;
  1967. Vector2D vDiff( m_DrawPoints[ index2 ].x - m_DrawPoints[ index ].x, m_DrawPoints[ index2 ].y - m_DrawPoints[ index ].y );
  1968. float Length = Vector2DNormalize( vDiff );
  1969. if ( Length == 0.0f )
  1970. {
  1971. continue;
  1972. }
  1973. float factor = ( ( j + 1 ) * 100 ); // * Length; // * 8 * Length;
  1974. vAverage += ( vDiff * factor );
  1975. count += factor;
  1976. }
  1977. if ( count > 0.0f )
  1978. {
  1979. vAverage /= count;
  1980. Vector2DNormalize( vAverage );
  1981. vNormal = vAverage;
  1982. return true;
  1983. }
  1984. return false;
  1985. }
  1986. #endif
  1987. //-----------------------------------------------------------------------------
  1988. // Purpose: calculates the normal / direction of the drawing line
  1989. // Input : nPointIndex - which point to factor from
  1990. // Output : returns true if we found a valid normal
  1991. // vNormal - the normal we found
  1992. //-----------------------------------------------------------------------------
  1993. bool CSculptCarveOptions::CalculateQueuePoint( Vector2D &vPoint, Vector2D &vNormal )
  1994. {
  1995. float count = 0.0;
  1996. Vector2D vAverage( 0.0f, 0.0f );
  1997. const float fMaxLength = 40.0f;
  1998. float fTotalLength = 0.0f;
  1999. Vector2D vInitialDir;
  2000. bool bInitialDirSet = false;
  2001. int PointIndex = m_PointQueue.Count() - 1;
  2002. if ( PointIndex <= 1 )
  2003. {
  2004. return false;
  2005. }
  2006. vPoint = m_PointQueue[ PointIndex ];
  2007. // keep going back from the current point until you get a total distance
  2008. for( int j = PointIndex - 1; j >= 0; j-- )
  2009. {
  2010. int index = j;
  2011. int index2 = PointIndex;
  2012. Vector2D vDiff( m_PointQueue[ index2 ].x - m_PointQueue[ index ].x, m_PointQueue[ index2 ].y - m_PointQueue[ index ].y );
  2013. float Length = Vector2DNormalize( vDiff );
  2014. if ( Length == 0.0f )
  2015. {
  2016. continue;
  2017. }
  2018. if ( bInitialDirSet == false )
  2019. {
  2020. vInitialDir = vDiff;
  2021. bInitialDirSet = true;
  2022. }
  2023. if ( DotProduct2D( vInitialDir, vDiff ) <= 0.5f )
  2024. {
  2025. break;
  2026. }
  2027. fTotalLength += Length;
  2028. float factor;
  2029. #if 0
  2030. factor = 1.0f - ( fTotalLength / fMaxLength );
  2031. if ( factor <= 0.0f )
  2032. {
  2033. factor = 0.01;
  2034. }
  2035. factor *= 20.0f;
  2036. #endif
  2037. factor = Length;
  2038. //= Length; // ( ( j + 1 ) * 100 ); // * Length; // * 8 * Length;
  2039. vAverage += ( vDiff * factor );
  2040. count += factor;
  2041. if ( fTotalLength >= fMaxLength )
  2042. {
  2043. break;
  2044. }
  2045. }
  2046. if ( count > 0.0f )
  2047. {
  2048. vAverage /= count;
  2049. Vector2DNormalize( vAverage );
  2050. vNormal = vAverage;
  2051. return true;
  2052. }
  2053. return false;
  2054. }
  2055. //-----------------------------------------------------------------------------
  2056. // Purpose: adds the point and normal to the queue
  2057. // Input : vPoint - the point to be added
  2058. // bDrawIt - if we should add this point to the draw / normal lists
  2059. //-----------------------------------------------------------------------------
  2060. void CSculptCarveOptions::AddQueuePoint( const Vector2D &vPoint, bool bDrawIt )
  2061. {
  2062. m_PointQueue.AddToTail( vPoint );
  2063. if ( m_PointQueue.Count() > MAX_QUEUE_SIZE )
  2064. {
  2065. m_PointQueue.Remove( 0 );
  2066. }
  2067. Vector2D vNewPoint, vNewNormal;
  2068. if ( bDrawIt && CalculateQueuePoint( vNewPoint, vNewNormal ) )
  2069. {
  2070. m_DrawPoints.AddToTail( vNewPoint );
  2071. m_DrawNormal.AddToTail( vNewNormal );
  2072. }
  2073. }
  2074. //-----------------------------------------------------------------------------
  2075. // Purpose: draws the tool in the 3d view
  2076. // Input : pRender - the 3d renderer
  2077. //-----------------------------------------------------------------------------
  2078. void CSculptCarveOptions::RenderTool3D( CRender3D *pRender )
  2079. {
  2080. // pRender->DrawText( "mouse", m_MousePoint.x, m_MousePoint.y, 0 );
  2081. // Msg( "%g %g\n", m_MousePoint.x, m_MousePoint.y );
  2082. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  2083. pRender->BeginClientSpace();
  2084. Vector2D vMousePoint, vMouseNormal;
  2085. if ( CalculateQueuePoint( vMousePoint, vMouseNormal ) )
  2086. {
  2087. Vector2D vRight( -vMouseNormal.y, vMouseNormal.x );
  2088. pRender->SetDrawColor( 255, 255, 0 );
  2089. pRender->DrawLine( Vector( vMousePoint.x, vMousePoint.y, 0.0f ), Vector( vMousePoint.x + vRight.x * m_BrushSize, vMousePoint.y + vRight.y * m_BrushSize, 0.0f ) );
  2090. pRender->DrawLine( Vector( vMousePoint.x, vMousePoint.y, 0.0f ), Vector( vMousePoint.x - ( vRight.x * m_BrushSize ), vMousePoint.y - ( vRight.y * m_BrushSize ), 0.0f ) );
  2091. }
  2092. #if 0
  2093. for( int i = 2; i < m_DrawPoints.Count(); i++ )
  2094. {
  2095. Vector2D vPoint = m_DrawPoints[ i ];
  2096. Vector2D vPreviousPoint = m_DrawPoints[ i - 1];
  2097. Vector2D vNormal = m_DrawNormal[ i ];
  2098. Vector2D vRight( -m_DrawNormal[ i ].y, m_DrawNormal[ i ].x );
  2099. Vector2D vDelta = vPoint - vPreviousPoint;
  2100. float Length = Vector2DLength( vDelta );
  2101. pRender->SetDrawColor( 255, 255, 0 );
  2102. pRender->DrawLine( Vector( vPreviousPoint.x, vPreviousPoint.y, 0.0f ), Vector( vPoint.x, vPoint.y, 0.0f ) );
  2103. pRender->SetDrawColor( 255, 0, 0 );
  2104. pRender->DrawLine( Vector( vPoint.x, vPoint.y, 0.0f ), Vector( vPoint.x + vRight.x * m_BrushSize, vPoint.y + vRight.y * m_BrushSize, 0.0f ) );
  2105. // pRender->DrawLine( Vector( vPoint.x, vPoint.y, 0.0f ), Vector( vPoint.x - ( vRight.x * m_BrushSize ), vPoint.y - ( vRight.y * m_BrushSize ), 0.0f ) );
  2106. vNormal *= Length;
  2107. pRender->SetDrawColor( 0, 255, 0 );
  2108. pRender->DrawLine( Vector( vPoint.x - vNormal.x, vPoint.y - vNormal.y, 0.0f ), Vector( vPoint.x, vPoint.y, 0.0f ) );
  2109. }
  2110. pRender->SetDrawColor( 255, 0, 255 );
  2111. pRender->SetHandleStyle( 6, CRender::HANDLE_SQUARE );
  2112. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2113. if( pDispMgr )
  2114. {
  2115. int nDispCount = pDispMgr->SelectCount();
  2116. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  2117. {
  2118. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  2119. if ( pDisp )
  2120. {
  2121. int nVertCount = pDisp->GetSize();
  2122. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  2123. {
  2124. Vector vVert;
  2125. Vector2D vViewVert;
  2126. pDisp->GetVert( iVert, vVert );
  2127. pRender->GetCamera()->WorldToView( vVert, vViewVert );
  2128. for( int i = 2; i < m_DrawPoints.Count(); i++ )
  2129. {
  2130. float distance;
  2131. float tolerance = DotProduct2D( m_DrawNormal[ i ], m_DrawNormal[ i - 1 ] );
  2132. if ( tolerance <= 0.5f )
  2133. {
  2134. continue;
  2135. }
  2136. distance = DotProduct2D( m_DrawNormal[ i ], m_DrawPoints[ i ] );
  2137. if ( DotProduct2D( m_DrawNormal[ i ], vViewVert ) > distance )
  2138. {
  2139. continue;
  2140. }
  2141. distance = DotProduct2D( m_DrawNormal[ i - 1 ], m_DrawPoints[ i - 1 ] );
  2142. if ( DotProduct2D( m_DrawNormal[ i - 1 ], vViewVert ) < distance )
  2143. {
  2144. continue;
  2145. }
  2146. Vector2D vRight( -m_DrawNormal[ i ].y, m_DrawNormal[ i ].x );
  2147. Vector2D vPoint;
  2148. vPoint = m_DrawPoints[ i ] + ( vRight * m_BrushSize );
  2149. distance = DotProduct2D( vRight, vPoint );
  2150. if ( DotProduct2D( vRight, vViewVert ) > distance )
  2151. {
  2152. continue;
  2153. }
  2154. vPoint = m_DrawPoints[ i ] - ( vRight * m_BrushSize );
  2155. distance = DotProduct2D( vRight, vPoint );
  2156. if ( DotProduct2D( vRight, vViewVert ) < distance )
  2157. {
  2158. continue;
  2159. }
  2160. // pRender->DrawHandle( Vector( vViewVert.x, vViewVert.y, 0.0f ) );
  2161. pRender->DrawHandle( vVert );
  2162. break;
  2163. }
  2164. }
  2165. }
  2166. }
  2167. }
  2168. #endif
  2169. pRender->EndClientSpace();
  2170. #if 0
  2171. if ( m_InSizingMode )
  2172. { // yellow for sizing mode
  2173. pRender->SetDrawColor( 255, 255, 0 );
  2174. pRender->BeginClientSpace();
  2175. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2176. pRender->EndClientSpace();
  2177. }
  2178. else if ( m_bShiftDown )
  2179. { // purple for smoothing
  2180. pRender->SetDrawColor( 255, 0, 255 );
  2181. pRender->BeginClientSpace();
  2182. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2183. pRender->EndClientSpace();
  2184. }
  2185. else if ( m_bCtrlDown )
  2186. { // red for negative sculpting
  2187. pRender->SetDrawColor( 255, 0, 0 );
  2188. pRender->BeginClientSpace();
  2189. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2190. pRender->EndClientSpace();
  2191. Vector vPaintAxis;
  2192. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  2193. DrawDirection( pRender, -vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  2194. }
  2195. else
  2196. { // green for positive sculpting
  2197. pRender->SetDrawColor( 0, 255, 0 );
  2198. pRender->BeginClientSpace();
  2199. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2200. pRender->EndClientSpace();
  2201. Vector vPaintAxis;
  2202. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  2203. DrawDirection( pRender, vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  2204. }
  2205. #endif
  2206. #if 0
  2207. FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept );
  2208. Vector2D RadiusPoint = m_MousePoint;
  2209. Vector vecStart, vecEnd;
  2210. RadiusPoint.x += m_BrushSize;
  2211. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  2212. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  2213. pRender->RenderWireframeSphere( m_CurrentCollisionPoint, m_CurrentProjectedRadius, 12, 12, 0, 255, 255 );
  2214. #endif
  2215. #if 0
  2216. // Get the displacement manager from the active map document.
  2217. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2218. // For each displacement surface is the selection list attempt to paint on it.
  2219. int nDispCount = pDispMgr->SelectCount();
  2220. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  2221. {
  2222. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  2223. if ( pDisp )
  2224. {
  2225. CMapDisp *OrigDisp = NULL;
  2226. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  2227. if ( index != m_OrigMapDisp.InvalidIndex() )
  2228. {
  2229. OrigDisp = m_OrigMapDisp[ index ];
  2230. }
  2231. Vector vPaintPos, vVert;
  2232. int nVertCount = pDisp->GetSize();
  2233. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  2234. {
  2235. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, false ) )
  2236. {
  2237. // Get the current vert.
  2238. pDisp->GetVert( iVert, vVert );
  2239. }
  2240. }
  2241. }
  2242. }
  2243. #endif
  2244. pRender->PopRenderMode();
  2245. #if 0
  2246. if ( !FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept ) )
  2247. {
  2248. return;
  2249. }
  2250. Vector2D RadiusPoint = m_MousePoint;
  2251. Vector vecStart, vecEnd;
  2252. RadiusPoint.x += m_BrushSize;
  2253. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  2254. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  2255. Msg( "Dist = %g at %g,%g,%g\n", m_CurrentProjectedRadius, m_CurrentCollisionPoint.x, m_CurrentCollisionPoint.y, m_CurrentCollisionPoint.z );
  2256. #endif
  2257. }
  2258. //-----------------------------------------------------------------------------
  2259. // Purpose: handles the left mouse button up in the 3d view
  2260. // Input : pView - the 3d view
  2261. // nFlags - the button flags
  2262. // vPoint - the mouse point
  2263. // Output : returns true if successful
  2264. //-----------------------------------------------------------------------------
  2265. bool CSculptCarveOptions::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2266. {
  2267. __super::OnLMouseUp3D( pView, nFlags, vPoint );
  2268. AddQueuePoint( vPoint, true );
  2269. return true;
  2270. }
  2271. //-----------------------------------------------------------------------------
  2272. // Purpose: handles the left mouse button down in the 3d view
  2273. // Input : pView - the 3d view
  2274. // nFlags - the button flags
  2275. // vPoint - the mouse point
  2276. // Output : returns true if successful
  2277. //-----------------------------------------------------------------------------
  2278. bool CSculptCarveOptions::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2279. {
  2280. __super::OnLMouseDown3D( pView, nFlags, vPoint );
  2281. m_DrawPoints.Purge();
  2282. m_DrawNormal.Purge();
  2283. AddQueuePoint( vPoint, true );
  2284. return true;
  2285. }
  2286. //-----------------------------------------------------------------------------
  2287. // Purpose: handles the right mouse button down in the 3d view
  2288. // Input : pView - the 3d view
  2289. // nFlags - the button flags
  2290. // vPoint - the mouse point
  2291. // Output : returns true if successful
  2292. //-----------------------------------------------------------------------------
  2293. bool CSculptCarveOptions::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2294. {
  2295. __super::OnRMouseDown3D( pView, nFlags, vPoint );
  2296. if ( m_bAltDown )
  2297. {
  2298. m_NormalMode = NORMAL_MODE_Z;
  2299. m_NormalModeControl.SetCurSel( m_NormalMode );
  2300. #if 0
  2301. //
  2302. // check for closest solid object
  2303. //
  2304. ULONG ulFace;
  2305. CMapClass *pObject;
  2306. if( ( ( pObject = pView->NearestObjectAt( vPoint, ulFace ) ) != NULL ) )
  2307. {
  2308. if( pObject->IsMapClass( MAPCLASS_TYPE( CMapSolid ) ) )
  2309. {
  2310. // get the solid
  2311. CMapSolid *pSolid = ( CMapSolid* )pObject;
  2312. if( !pSolid )
  2313. {
  2314. return true;
  2315. }
  2316. // trace a line and get the normal -- will get a displacement normal
  2317. // if one exists
  2318. CMapFace *pFace = pSolid->GetFace( ulFace );
  2319. if( !pFace )
  2320. {
  2321. return true;
  2322. }
  2323. Vector vRayStart, vRayEnd;
  2324. pView->GetCamera()->BuildRay( vPoint, vRayStart, vRayEnd );
  2325. Vector vHitPos, vHitNormal;
  2326. if( pFace->TraceLine( vHitPos, vHitNormal, vRayStart, vRayEnd ) )
  2327. {
  2328. // set the paint direction
  2329. m_SelectedNormal = vHitNormal;
  2330. m_NormalMode = NORMAL_MODE_SELECTED;
  2331. m_NormalModeControl.SetCurSel( m_NormalMode );
  2332. }
  2333. }
  2334. }
  2335. #else
  2336. Vector CollisionPoint, CollisionNormal;
  2337. float CollisionIntercept;
  2338. if ( FindCollisionIntercept( pView->GetCamera(), vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept ) )
  2339. {
  2340. // set the paint direction
  2341. m_SelectedNormal = -CollisionNormal;
  2342. m_NormalMode = NORMAL_MODE_SELECTED;
  2343. m_NormalModeControl.SetCurSel( m_NormalMode );
  2344. }
  2345. #endif
  2346. }
  2347. return true;
  2348. }
  2349. //-----------------------------------------------------------------------------
  2350. // Purpose: handles the mouse move in the 3d view
  2351. // Input : pView - the 3d view
  2352. // nFlags - the button flags
  2353. // vPoint - the mouse point
  2354. // Output : returns true if successful
  2355. //-----------------------------------------------------------------------------
  2356. bool CSculptCarveOptions::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2357. {
  2358. __super::OnMouseMove3D( pView, nFlags, vPoint );
  2359. AddQueuePoint( vPoint, m_bLMBDown );
  2360. return true;
  2361. }
  2362. //-----------------------------------------------------------------------------
  2363. // Purpose: returns the painting direction
  2364. // Input : pCamera - the 3d camera
  2365. // vPoint - the 2d mouse point
  2366. // Output : vPaintAxis - the direction the painting should go
  2367. //-----------------------------------------------------------------------------
  2368. void CSculptCarveOptions::GetPaintAxis( CCamera *pCamera, const Vector2D &vPoint, Vector &vPaintAxis )
  2369. {
  2370. switch( m_NormalMode )
  2371. {
  2372. case NORMAL_MODE_SCREEN:
  2373. pCamera->GetViewForward( vPaintAxis );
  2374. vPaintAxis = -vPaintAxis;
  2375. break;
  2376. case NORMAL_MODE_SCREEN_XY:
  2377. pCamera->GetViewForward( vPaintAxis );
  2378. vPaintAxis = -vPaintAxis;
  2379. vPaintAxis.z = 0.f;
  2380. break;
  2381. case NORMAL_MODE_BRUSH_CENTER:
  2382. if ( !m_InPaintingMode )
  2383. {
  2384. Vector CollisionPoint, CollisionNormal;
  2385. float CollisionIntercept;
  2386. FindCollisionIntercept( pCamera, vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept );
  2387. vPaintAxis = -CollisionNormal;
  2388. }
  2389. else
  2390. {
  2391. vPaintAxis = -m_StartingCollisionNormal;
  2392. }
  2393. break;
  2394. case NORMAL_MODE_X:
  2395. vPaintAxis.Init( 1.0f, 0.0f, 0.0f );
  2396. break;
  2397. case NORMAL_MODE_Y:
  2398. vPaintAxis.Init( 0.0f, 1.0f, 0.0f );
  2399. break;
  2400. case NORMAL_MODE_Z:
  2401. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  2402. break;
  2403. case NORMAL_MODE_SELECTED:
  2404. vPaintAxis = m_SelectedNormal;
  2405. break;
  2406. default:
  2407. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  2408. }
  2409. }
  2410. //-----------------------------------------------------------------------------
  2411. // Purpose: determines if a displacement point is affected by the carve
  2412. // Input : pView - the 3d view
  2413. // pDisp - the displacement
  2414. // pOrigDisp - the displacement prior to any updates
  2415. // nVertIndex - the vertex to look at
  2416. // nBrushPoint - which list point to check against
  2417. // bUseOrigDisplacement - should we use the vert from the original displacement
  2418. // bUseCurrentPosition - should we use the current collision test point
  2419. // Output : returns true if the point is affected
  2420. // vViewVert - the 2d view vert location
  2421. //-----------------------------------------------------------------------------
  2422. bool CSculptCarveOptions::IsPointAffected( CMapView3D *pView, CMapDisp *pDisp, CMapDisp *pOrigDisp, int vertIndex, int nBrushPoint, Vector2D &vViewVert, bool bUseOrigDisplacement, bool bUseCurrentPosition )
  2423. {
  2424. Vector vVert, vTestVert;
  2425. pDisp->GetVert( vertIndex, vVert );
  2426. if ( pOrigDisp && bUseOrigDisplacement )
  2427. {
  2428. pOrigDisp->GetVert( vertIndex, vTestVert );
  2429. }
  2430. else
  2431. {
  2432. vTestVert = vVert;
  2433. }
  2434. pView->GetCamera()->WorldToView( vTestVert, vViewVert );
  2435. float distance;
  2436. float tolerance = DotProduct2D( m_DrawNormal[ nBrushPoint ], m_DrawNormal[ nBrushPoint - 1 ] );
  2437. if ( tolerance <= 0.5f )
  2438. {
  2439. return false;
  2440. }
  2441. distance = DotProduct2D( m_DrawNormal[ nBrushPoint ], m_DrawPoints[ nBrushPoint ] );
  2442. if ( DotProduct2D( m_DrawNormal[ nBrushPoint ], vViewVert ) > distance )
  2443. {
  2444. return false;
  2445. }
  2446. distance = DotProduct2D( m_DrawNormal[ nBrushPoint - 1 ], m_DrawPoints[ nBrushPoint - 1 ] );
  2447. if ( DotProduct2D( m_DrawNormal[ nBrushPoint - 1 ], vViewVert ) < distance )
  2448. {
  2449. return false;
  2450. }
  2451. Vector2D vRight( -m_DrawNormal[ nBrushPoint ].y, m_DrawNormal[ nBrushPoint ].x );
  2452. Vector2D vPoint;
  2453. vPoint = m_DrawPoints[ nBrushPoint ] + ( vRight * m_BrushSize );
  2454. distance = DotProduct2D( vRight, vPoint );
  2455. if ( DotProduct2D( vRight, vViewVert ) > distance )
  2456. {
  2457. return false;
  2458. }
  2459. vPoint = m_DrawPoints[ nBrushPoint ] - ( vRight * m_BrushSize );
  2460. distance = DotProduct2D( vRight, vPoint );
  2461. if ( DotProduct2D( vRight, vViewVert ) < distance )
  2462. {
  2463. return false;
  2464. }
  2465. return true;
  2466. }
  2467. //-----------------------------------------------------------------------------
  2468. // Purpose: applies the specific push operation onto the displacement
  2469. // Input : pView - the 3d view
  2470. // vPoint - the mouse point
  2471. // pDisp - the displacement to apply the push to
  2472. // pOrigDisp - the original displacement prior to any adjustments
  2473. //-----------------------------------------------------------------------------
  2474. void CSculptCarveOptions::DoPaintOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  2475. {
  2476. Vector vPaintPos, vVert, vDirection;
  2477. Vector2D vViewVert;
  2478. float flDistance = 0.0f;
  2479. Vector vPaintAxis;
  2480. int nTestPoint = m_DrawPoints.Count() - 1;
  2481. if ( nTestPoint < 2 )
  2482. {
  2483. return;
  2484. }
  2485. if ( m_bShiftDown )
  2486. {
  2487. // DoSmoothOperation( pView, vPoint, pDisp, pOrigDisp );
  2488. // m_SpatialData.m_flRadius = 256.0f;
  2489. // m_SpatialData.m_flScalar = 5.0f / m_SmoothAmount;
  2490. // m_SpatialData.m_flRadius = m_StartingProjectedRadius * 1.5f;
  2491. m_SpatialData.m_flRadius = m_CurrentProjectedRadius * 2.0f;
  2492. m_SpatialData.m_flRadius2 = ( m_SpatialData.m_flRadius * m_SpatialData.m_flRadius );
  2493. m_SpatialData.m_flOORadius2 = 1.0f / m_SpatialData.m_flRadius2;
  2494. m_SpatialData.m_flScalar = 10.0f / m_SmoothAmount;
  2495. m_SpatialData.m_vCenter = m_CurrentCollisionPoint;
  2496. DoPaintSmooth( pView, vPoint, pDisp, pOrigDisp );
  2497. return;
  2498. }
  2499. GetPaintAxis( pView->GetCamera(), vPoint, vPaintAxis );
  2500. vDirection = vPaintAxis * m_Direction;
  2501. switch( m_OffsetMode )
  2502. {
  2503. case OFFSET_MODE_ADAPTIVE:
  2504. flDistance = m_StartingProjectedRadius * m_OffsetAmount;
  2505. break;
  2506. case OFFSET_MODE_ABSOLUTE:
  2507. flDistance = m_OffsetDistance;
  2508. break;
  2509. }
  2510. int nVertCount = pDisp->GetSize();
  2511. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  2512. {
  2513. if ( IsPointAffected( pView, pDisp, pOrigDisp, iVert, nTestPoint, vViewVert ) )
  2514. {
  2515. pDisp->GetVert( iVert, vVert );
  2516. Vector2D vRight( -m_DrawNormal[ nTestPoint ].y, m_DrawNormal[ nTestPoint ].x );
  2517. float fLineDistance = DotProduct2D( vRight, m_DrawPoints[ nTestPoint ] ) - DotProduct2D( vRight, vViewVert );
  2518. fLineDistance = ( fLineDistance + m_BrushSize ) / ( m_BrushSize * 2.0f );
  2519. int index = ( int )( fLineDistance * MAX_SCULPT_SIZE );
  2520. index = clamp( index, 0, MAX_SCULPT_SIZE - 1 );
  2521. index = MAX_SCULPT_SIZE - index - 1;
  2522. float fScaledDistance = m_BrushPoints[ index ] * flDistance;
  2523. if ( fScaledDistance == 0.0f )
  2524. {
  2525. continue;
  2526. }
  2527. switch( m_DensityMode )
  2528. {
  2529. case DENSITY_MODE_ADDITIVE:
  2530. VectorScale( vDirection, fScaledDistance, vPaintPos );
  2531. VectorAdd( vPaintPos, vVert, vPaintPos );
  2532. break;
  2533. case DENSITY_MODE_ATTENUATED:
  2534. VectorScale( vDirection, fScaledDistance, vPaintPos );
  2535. VectorAdd( vPaintPos, vVert, vPaintPos );
  2536. if ( pOrigDisp )
  2537. {
  2538. Vector vOrigVert, vDiff;
  2539. float Length;
  2540. pOrigDisp->GetVert( iVert, vOrigVert );
  2541. vDiff = ( vPaintPos - vOrigVert );
  2542. Length = vDiff.Length() / flDistance;
  2543. if ( Length > 1.0f )
  2544. {
  2545. Length = 1.0f;
  2546. }
  2547. vPaintPos = vOrigVert + ( Length * vDirection * flDistance );
  2548. }
  2549. break;
  2550. }
  2551. AddToUndo( &pDisp );
  2552. pDisp->Paint_SetValue( iVert, vPaintPos );
  2553. }
  2554. }
  2555. }
  2556. //-----------------------------------------------------------------------------
  2557. // Purpose: sets the offset distance
  2558. //-----------------------------------------------------------------------------
  2559. void CSculptCarveOptions::OnEnChangeSculptPushOptionOffsetDistance()
  2560. {
  2561. char temp[ 1024 ];
  2562. m_OffsetDistanceControl.GetWindowText( temp, sizeof( temp ) );
  2563. m_OffsetDistance = atof( temp );
  2564. }
  2565. //-----------------------------------------------------------------------------
  2566. // Purpose: sets the density mode
  2567. //-----------------------------------------------------------------------------
  2568. void CSculptCarveOptions::OnCbnSelchangeSculptPushOptionDensityMode()
  2569. {
  2570. m_DensityMode = ( DensityMode )m_DensityModeControl.GetCurSel();
  2571. }
  2572. //-----------------------------------------------------------------------------
  2573. // Purpose: sets the smooth amount
  2574. //-----------------------------------------------------------------------------
  2575. void CSculptCarveOptions::OnEnKillfocusSculptPushOptionSmoothAmount()
  2576. {
  2577. char temp[ 1024 ], t2[ 1024 ];
  2578. m_SmoothAmountControl.GetWindowText( temp, sizeof( temp ) );
  2579. sscanf( temp, "%f%%", &m_SmoothAmount );
  2580. m_SmoothAmount /= 100.0f;
  2581. if ( m_SmoothAmount <= 0.0f )
  2582. {
  2583. m_SmoothAmount = 0.2f;
  2584. }
  2585. sprintf( t2, "%g%%", m_SmoothAmount * 100.0f );
  2586. if ( strcmpi( temp, t2 ) != 0 )
  2587. {
  2588. m_SmoothAmountControl.SetWindowText( t2 );
  2589. }
  2590. }
  2591. //-----------------------------------------------------------------------------
  2592. // Purpose: sets the offset amount
  2593. //-----------------------------------------------------------------------------
  2594. void CSculptCarveOptions::OnEnKillfocusSculptPushOptionOffsetAmount()
  2595. {
  2596. char temp[ 1024 ], t2[ 1024 ];
  2597. m_OffsetAmountControl.GetWindowText( temp, sizeof( temp ) );
  2598. sscanf( temp, "%f%%", &m_OffsetAmount );
  2599. m_OffsetAmount /= 100.0f;
  2600. if ( m_OffsetAmount <= 0.0f )
  2601. {
  2602. m_OffsetAmount = 1.0f;
  2603. }
  2604. sprintf( t2, "%g%%", m_OffsetAmount * 100.0f );
  2605. if ( strcmpi( temp, t2 ) != 0 )
  2606. {
  2607. m_OffsetAmountControl.SetWindowText( t2 );
  2608. }
  2609. }
  2610. //-----------------------------------------------------------------------------
  2611. // Purpose: paints the carve brush
  2612. //-----------------------------------------------------------------------------
  2613. void CSculptCarveOptions::OnPaint()
  2614. {
  2615. CPaintDC dc(this); // device context for painting
  2616. CBrush black( RGB( 0, 0, 0 ) );
  2617. CBrush red( RGB( 255, 0, 0 ) );
  2618. CBrush green( RGB( 0, 255, 0 ) );
  2619. CBrush blue_red( RGB( 64, 0, 128 ) );
  2620. CBrush blue_green( RGB( 0, 64, 128 ) );
  2621. CBrush blue( RGB( 0, 0, 255 ) );
  2622. CRect WindowRect;
  2623. m_CarveBrushControl.GetWindowRect( &WindowRect );
  2624. ScreenToClient( &WindowRect );
  2625. dc.FillRect( WindowRect, &black );
  2626. float center = ( WindowRect.bottom + WindowRect.top ) / 2;
  2627. float height = ( WindowRect.bottom - WindowRect.top ) - 1;
  2628. if ( m_BrushLocation != -1 )
  2629. {
  2630. CRect rect;
  2631. rect.left = ( m_BrushLocation * 2 ) + WindowRect.left;
  2632. rect.right = rect.left + 2;
  2633. rect.bottom = WindowRect.bottom;
  2634. rect.top = WindowRect.top;
  2635. dc.FillRect( rect, &blue );
  2636. }
  2637. for( int i = 0; i < MAX_SCULPT_SIZE; i++ )
  2638. {
  2639. float size = height / 2.0f * m_BrushPoints[ i ];
  2640. CRect rect;
  2641. CBrush *pBrush;
  2642. rect.left = ( i * 2 ) + WindowRect.left;
  2643. rect.right = rect.left + 2;
  2644. rect.bottom = center - size;
  2645. rect.top = center;
  2646. if ( m_BrushPoints[ i ] >= 0.0f )
  2647. {
  2648. if ( m_BrushLocation == i )
  2649. {
  2650. pBrush = &blue_green;
  2651. }
  2652. else
  2653. {
  2654. pBrush = &green;
  2655. }
  2656. }
  2657. else
  2658. {
  2659. if ( m_BrushLocation == i )
  2660. {
  2661. pBrush = &blue_red;
  2662. }
  2663. else
  2664. {
  2665. pBrush = &red;
  2666. }
  2667. }
  2668. dc.FillRect( rect, pBrush );
  2669. }
  2670. }
  2671. //-----------------------------------------------------------------------------
  2672. // Purpose: adjusts the carve brush
  2673. // Input : x - location to set the height to
  2674. // y - offset into the brush
  2675. //-----------------------------------------------------------------------------
  2676. void CSculptCarveOptions::AdjustBrush( int x, int y )
  2677. {
  2678. CRect WindowRect;
  2679. CPoint MousePoint( x, y );
  2680. m_CarveBrushControl.GetWindowRect( &WindowRect );
  2681. ClientToScreen( &MousePoint );
  2682. if ( MousePoint.x >= WindowRect.left && MousePoint.x < WindowRect.right &&
  2683. MousePoint.y >= WindowRect.top && MousePoint.y < WindowRect.bottom )
  2684. {
  2685. int pos = ( MousePoint.x - WindowRect.left ) / 2;
  2686. float center = ( WindowRect.bottom + WindowRect.top ) / 2;
  2687. float value = ( center - MousePoint.y ) / ( WindowRect.bottom - WindowRect.top ) * 2.0f;
  2688. value = clamp( value, -1.0f, 1.0f );
  2689. if ( pos >= 0 && pos < MAX_SCULPT_SIZE )
  2690. {
  2691. m_BrushPoints[ pos ] = value;
  2692. Invalidate();
  2693. }
  2694. }
  2695. }
  2696. //-----------------------------------------------------------------------------
  2697. // Purpose: sets the brush cursor location
  2698. // Input : x - x location of mouse
  2699. // y - y location of mouse
  2700. //-----------------------------------------------------------------------------
  2701. void CSculptCarveOptions::AdjustBrushCursor( int x, int y )
  2702. {
  2703. CRect WindowRect;
  2704. int OldBrushLocation = m_BrushLocation;
  2705. CPoint MousePoint( x, y );
  2706. m_CarveBrushControl.GetWindowRect( &WindowRect );
  2707. ClientToScreen( &MousePoint );
  2708. if ( MousePoint.x >= WindowRect.left && MousePoint.x < WindowRect.right &&
  2709. MousePoint.y >= WindowRect.top && MousePoint.y < WindowRect.bottom )
  2710. {
  2711. m_BrushLocation = ( MousePoint.x - WindowRect.left ) / 2;
  2712. }
  2713. else
  2714. {
  2715. m_BrushLocation = -1;
  2716. }
  2717. if ( OldBrushLocation != m_BrushLocation )
  2718. {
  2719. Invalidate();
  2720. }
  2721. }
  2722. //-----------------------------------------------------------------------------
  2723. // Purpose: handles adjusting the brush
  2724. // Input : nFlags - mouse buttons
  2725. // point - mouse point
  2726. //-----------------------------------------------------------------------------
  2727. void CSculptCarveOptions::OnLButtonDown(UINT nFlags, CPoint point)
  2728. {
  2729. AdjustBrush( point.x, point.y );
  2730. AdjustBrushCursor( point.x, point.y );
  2731. __super::OnLButtonDown(nFlags, point);
  2732. }
  2733. //-----------------------------------------------------------------------------
  2734. // Purpose: handles adjusting the brush
  2735. // Input : nFlags - mouse buttons
  2736. // point - mouse point
  2737. //-----------------------------------------------------------------------------
  2738. void CSculptCarveOptions::OnLButtonUp(UINT nFlags, CPoint point)
  2739. {
  2740. AdjustBrush( point.x, point.y );
  2741. AdjustBrushCursor( point.x, point.y );
  2742. __super::OnLButtonUp(nFlags, point);
  2743. }
  2744. //-----------------------------------------------------------------------------
  2745. // Purpose: handles adjusting the brush
  2746. // Input : nFlags - mouse buttons
  2747. // point - mouse point
  2748. //-----------------------------------------------------------------------------
  2749. void CSculptCarveOptions::OnMouseMove(UINT nFlags, CPoint point)
  2750. {
  2751. if ( nFlags & MK_LBUTTON )
  2752. {
  2753. AdjustBrush( point.x, point.y );
  2754. }
  2755. AdjustBrushCursor( point.x, point.y );
  2756. __super::OnMouseMove(nFlags, point);
  2757. }
  2758. //-----------------------------------------------------------------------------
  2759. // Purpose: we want to handle the messages for mouse events
  2760. //-----------------------------------------------------------------------------
  2761. BOOL CSculptCarveOptions::PreTranslateMessage( MSG* pMsg )
  2762. {
  2763. if ( pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_MOUSEMOVE )
  2764. {
  2765. return FALSE;
  2766. }
  2767. return __super::PreTranslateMessage( pMsg );
  2768. }
  2769. #if 0
  2770. class CSculptRegenerator : public ITextureRegenerator
  2771. {
  2772. public:
  2773. CSculptRegenerator( unsigned char *ImageData, int Width, int Height, enum ImageFormat Format ) :
  2774. m_ImageData( ImageData ),
  2775. m_Width( Width ),
  2776. m_Height( Height ),
  2777. m_Format( Format )
  2778. {
  2779. }
  2780. virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pSubRect )
  2781. {
  2782. for (int iFrame = 0; iFrame < pVTFTexture->FrameCount(); ++iFrame )
  2783. {
  2784. for (int iFace = 0; iFace < pVTFTexture->FaceCount(); ++iFace )
  2785. {
  2786. int nWidth = pVTFTexture->Width();
  2787. int nHeight = pVTFTexture->Height();
  2788. int nDepth = pVTFTexture->Depth();
  2789. for (int z = 0; z < nDepth; ++z)
  2790. {
  2791. // Fill mip 0 with a checkerboard
  2792. CPixelWriter pixelWriter;
  2793. pixelWriter.SetPixelMemory( pVTFTexture->Format(), pVTFTexture->ImageData( iFrame, iFace, 0, 0, 0, z ), pVTFTexture->RowSizeInBytes( 0 ) );
  2794. switch( m_Format )
  2795. {
  2796. case IMAGE_FORMAT_BGR888:
  2797. {
  2798. unsigned char *data = m_ImageData;
  2799. for (int y = 0; y < nHeight; ++y)
  2800. {
  2801. pixelWriter.Seek( 0, y );
  2802. for (int x = 0; x < nWidth; ++x)
  2803. {
  2804. pixelWriter.WritePixel( *( data + 2 ), *( data + 1 ), *( data ), 255 );
  2805. data += 3;
  2806. }
  2807. }
  2808. }
  2809. break;
  2810. }
  2811. }
  2812. }
  2813. }
  2814. }
  2815. virtual void Release()
  2816. {
  2817. delete this;
  2818. }
  2819. private:
  2820. unsigned char *m_ImageData;
  2821. int m_Width;
  2822. int m_Height;
  2823. enum ImageFormat m_Format;
  2824. };
  2825. // CSculptProjectOptions dialog
  2826. IMPLEMENT_DYNAMIC(CSculptProjectOptions, CDialog)
  2827. CSculptProjectOptions::CSculptProjectOptions(CWnd* pParent /*=NULL*/) :
  2828. CDialog(CSculptProjectOptions::IDD, pParent),
  2829. CSculptTool()
  2830. {
  2831. m_FileDialog = new CFileDialog(TRUE, NULL, NULL, OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST, "Image Files (*.tga)|*.tga||");
  2832. m_FileDialog->m_ofn.lpstrInitialDir = "";
  2833. m_ImagePixels = NULL;
  2834. m_pTexture = NULL;
  2835. m_pMaterial = NULL;
  2836. m_ProjectX = 100;
  2837. m_ProjectY = 100;
  2838. m_ProjectWidth = 100;
  2839. m_ProjectHeight = 100;
  2840. m_TileWidth = m_TileHeight = 1.0;
  2841. m_OriginalTileWidth = m_TileWidth;
  2842. m_OriginalTileHeight = m_TileHeight;
  2843. m_ProjectLocation.Init( 100.0f, 100.0f, 0.0f );
  2844. m_OriginalProjectLocation = m_ProjectLocation;
  2845. m_ProjectSize.Init( 100.0f, 100.0f, 0.0f );
  2846. m_OriginalProjectSize = m_ProjectSize;
  2847. m_ToolMode = PROJECT_MODE_NONE;
  2848. }
  2849. CSculptProjectOptions::~CSculptProjectOptions()
  2850. {
  2851. delete m_FileDialog;
  2852. if ( m_ImagePixels )
  2853. {
  2854. delete [] m_ImagePixels;
  2855. }
  2856. if ( m_pTexture )
  2857. {
  2858. m_pTexture->DecrementReferenceCount();
  2859. m_pTexture = NULL;
  2860. }
  2861. }
  2862. //-----------------------------------------------------------------------------
  2863. // Purpose: set up the data exchange for the variables
  2864. // Input : pDX - the data exchange object
  2865. //-----------------------------------------------------------------------------
  2866. void CSculptProjectOptions::DoDataExchange(CDataExchange* pDX)
  2867. {
  2868. CDialog::DoDataExchange(pDX);
  2869. DDX_Control(pDX, IDC_PROJECT_SIZE, m_ProjectSizeControl);
  2870. DDX_Control(pDX, IDC_PROJECT_SIZE_NUM, m_ProjectSizeNumControl);
  2871. }
  2872. BEGIN_MESSAGE_MAP(CSculptProjectOptions, CDialog)
  2873. ON_BN_CLICKED(IDC_LOAD_IMAGE, &CSculptProjectOptions::OnBnClickedLoadImage)
  2874. ON_NOTIFY(NM_CUSTOMDRAW, IDC_PROJECT_SIZE, &CSculptProjectOptions::OnNMCustomdrawProjectSize)
  2875. END_MESSAGE_MAP()
  2876. bool CSculptProjectOptions::Paint( CMapView3D *pView, const Vector2D &vPoint, SpatialPaintData_t &spatialData )
  2877. {
  2878. CSculptTool::Paint( pView, vPoint, spatialData );
  2879. switch( m_ToolMode )
  2880. {
  2881. case PROJECT_MODE_SIZE:
  2882. DoSizing( vPoint );
  2883. break;
  2884. case PROJECT_MODE_POSITION:
  2885. DoPosition( vPoint );
  2886. break;
  2887. case PROJECT_MODE_TILE:
  2888. DoTiling( vPoint );
  2889. break;
  2890. }
  2891. return true;
  2892. }
  2893. //-----------------------------------------------------------------------------
  2894. // Purpose: draws the tool in the 3d view
  2895. // Input : pRender - the 3d renderer
  2896. //-----------------------------------------------------------------------------
  2897. void CSculptProjectOptions::RenderTool3D(CRender3D *pRender)
  2898. {
  2899. if ( !m_pMaterial )
  2900. {
  2901. return;
  2902. }
  2903. pRender->PushRenderMode( RENDER_MODE_TEXTURED );
  2904. bool bPopMode = pRender->BeginClientSpace();
  2905. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  2906. pRender->BindMaterial( m_pMaterial );
  2907. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  2908. CMeshBuilder meshBuilder;
  2909. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 4 );
  2910. meshBuilder.Position3f( m_ProjectLocation.x, m_ProjectLocation.y, m_ProjectLocation.z );
  2911. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  2912. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2913. meshBuilder.AdvanceVertex();
  2914. meshBuilder.Position3f( m_ProjectLocation.x + m_ProjectSize.x, m_ProjectLocation.y, m_ProjectLocation.z );
  2915. meshBuilder.TexCoord2f( 0, m_TileWidth, 0.0f );
  2916. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2917. meshBuilder.AdvanceVertex();
  2918. meshBuilder.Position3f( m_ProjectLocation.x + m_ProjectSize.x, m_ProjectLocation.y + m_ProjectSize.y, m_ProjectLocation.z );
  2919. meshBuilder.TexCoord2f( 0, m_TileWidth, m_TileHeight );
  2920. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2921. meshBuilder.AdvanceVertex();
  2922. meshBuilder.Position3f( m_ProjectLocation.x, m_ProjectLocation.y + m_ProjectSize.y, m_ProjectLocation.z );
  2923. meshBuilder.TexCoord2f( 0, 0.0f, m_TileHeight );
  2924. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2925. meshBuilder.AdvanceVertex();
  2926. meshBuilder.End();
  2927. pMesh->Draw();
  2928. if ( bPopMode )
  2929. {
  2930. pRender->EndClientSpace();
  2931. }
  2932. pRender->PopRenderMode();
  2933. }
  2934. //-----------------------------------------------------------------------------
  2935. // Purpose: handles the left mouse button up in the 3d view
  2936. // Input : pView - the 3d view
  2937. // nFlags - the button flags
  2938. // vPoint - the mouse point
  2939. // Output : returns true if successful
  2940. //-----------------------------------------------------------------------------
  2941. bool CSculptProjectOptions::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2942. {
  2943. CSculptTool::OnLMouseUp3D( pView, nFlags, vPoint );
  2944. return true;
  2945. }
  2946. //-----------------------------------------------------------------------------
  2947. // Purpose: handles the left mouse button down in the 3d view
  2948. // Input : pView - the 3d view
  2949. // nFlags - the button flags
  2950. // vPoint - the mouse point
  2951. // Output : returns true if successful
  2952. //-----------------------------------------------------------------------------
  2953. bool CSculptProjectOptions::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2954. {
  2955. CSculptTool::OnLMouseDown3D( pView, nFlags, vPoint );
  2956. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2957. if( pDispMgr )
  2958. {
  2959. pDispMgr->PreUndo( "Displacement Modifier" );
  2960. }
  2961. PrepareDispForPainting();
  2962. // Handle painting.
  2963. if ( !DoPaint( pView, vPoint ) )
  2964. {
  2965. return false;
  2966. }
  2967. // Finish painting.
  2968. if ( !PostPaint( m_PaintOwner->GetAutoSew() ) )
  2969. {
  2970. return false;
  2971. }
  2972. if( pDispMgr )
  2973. {
  2974. pDispMgr->PostUndo();
  2975. }
  2976. return true;
  2977. }
  2978. bool CSculptProjectOptions::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2979. {
  2980. CSculptTool::OnRMouseUp3D( pView, nFlags, vPoint );
  2981. m_ToolMode = PROJECT_MODE_NONE;
  2982. return true;
  2983. }
  2984. //-----------------------------------------------------------------------------
  2985. // Purpose: handles the right mouse button down in the 3d view
  2986. // Input : pView - the 3d view
  2987. // nFlags - the button flags
  2988. // vPoint - the mouse point
  2989. // Output : returns true if successful
  2990. //-----------------------------------------------------------------------------
  2991. bool CSculptProjectOptions::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2992. {
  2993. CSculptTool::OnRMouseDown3D( pView, nFlags, vPoint );
  2994. m_OriginalProjectSize = m_ProjectSize;
  2995. m_OriginalProjectLocation = m_ProjectLocation;
  2996. m_StartSizingPoint = vPoint;
  2997. if ( m_bCtrlDown )
  2998. {
  2999. m_ToolMode = PROJECT_MODE_SIZE;
  3000. }
  3001. else if ( m_bShiftDown )
  3002. {
  3003. m_ToolMode = PROJECT_MODE_TILE;
  3004. }
  3005. else
  3006. {
  3007. m_ToolMode = PROJECT_MODE_POSITION;
  3008. }
  3009. m_StartSizingPoint = vPoint;
  3010. return true;
  3011. }
  3012. //-----------------------------------------------------------------------------
  3013. // Purpose: handles the mouse move in the 3d view
  3014. // Input : pView - the 3d view
  3015. // nFlags - the button flags
  3016. // vPoint - the mouse point
  3017. // Output : returns true if successful
  3018. //-----------------------------------------------------------------------------
  3019. bool CSculptProjectOptions::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  3020. {
  3021. CSculptTool::OnMouseMove3D( pView, nFlags, vPoint );
  3022. return true;
  3023. }
  3024. //-----------------------------------------------------------------------------
  3025. // Purpose: applies the specific push operation onto the displacement
  3026. // Input : pView - the 3d view
  3027. // vPoint - the mouse point
  3028. // pDisp - the displacement to apply the push to
  3029. // pOrigDisp - the original displacement prior to any adjustments
  3030. //-----------------------------------------------------------------------------
  3031. void CSculptProjectOptions::DoPaintOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  3032. {
  3033. Vector vPaintPos, vVert;
  3034. Vector vPaintAxis;
  3035. pView->GetCamera()->GetViewForward( vPaintAxis );
  3036. vPaintAxis = -vPaintAxis;
  3037. vPaintAxis *= ( m_ProjectSizeControl.GetPos() * 16.0f );
  3038. int nVertCount = pDisp->GetSize();
  3039. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  3040. {
  3041. Vector2D ViewVert;
  3042. Vector vTestVert;
  3043. pDisp->GetVert( iVert, vTestVert );
  3044. pView->GetCamera()->WorldToView( vTestVert, ViewVert );
  3045. if ( ViewVert.x >= m_ProjectLocation.x &&
  3046. ViewVert.y >= m_ProjectLocation.y &&
  3047. ViewVert.x <= m_ProjectLocation.x + m_ProjectSize.x &&
  3048. ViewVert.y <= m_ProjectLocation.y + m_ProjectSize.y )
  3049. {
  3050. pDisp->GetVert( iVert, vVert );
  3051. float sCoord = ( ViewVert.x - m_ProjectLocation.x ) / m_ProjectSize.x;
  3052. float tCoord = ( ViewVert.y - m_ProjectLocation.y ) / m_ProjectSize.y;
  3053. sCoord *= m_TileWidth;
  3054. tCoord *= m_TileHeight;
  3055. sCoord -= ( int )sCoord;
  3056. tCoord -= ( int )tCoord;
  3057. int x = ( sCoord * m_Width );
  3058. int y = ( tCoord * m_Height );
  3059. unsigned char *pos = &m_ImagePixels[ ( y * m_Width * 3 ) + ( x * 3 ) ];
  3060. float gray = ( 0.3f * pos[ 2 ] ) + ( 0.59f * pos[ 1 ] ) + ( 0.11f * pos[ 0 ] );
  3061. gray /= 255.0f;
  3062. vPaintPos = vVert + ( vPaintAxis * gray );
  3063. AddToUndo( &pDisp );
  3064. pDisp->Paint_SetValue( iVert, vPaintPos );
  3065. }
  3066. }
  3067. }
  3068. void CSculptProjectOptions::OnBnClickedLoadImage()
  3069. {
  3070. if ( m_FileDialog->DoModal() == IDCANCEL )
  3071. {
  3072. return;
  3073. }
  3074. ReadImage( m_FileDialog->GetPathName() );
  3075. }
  3076. bool CSculptProjectOptions::ReadImage( CString &FileName )
  3077. {
  3078. enum ImageFormat imageFormat;
  3079. float sourceGamma;
  3080. CUtlBuffer buf;
  3081. if ( !g_pFullFileSystem->ReadFile( FileName, NULL, buf ) )
  3082. {
  3083. return false;
  3084. }
  3085. if ( !TGALoader::GetInfo( buf, &m_Width, &m_Height, &imageFormat, &sourceGamma ) )
  3086. {
  3087. return false;
  3088. }
  3089. if ( m_ImagePixels )
  3090. {
  3091. delete [] m_ImagePixels;
  3092. }
  3093. int memRequired = ImageLoader::GetMemRequired( m_Width, m_Height, 1, imageFormat, false );
  3094. m_ImagePixels = new unsigned char[ memRequired ];
  3095. buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  3096. TGALoader::Load( m_ImagePixels, buf, m_Width, m_Height, imageFormat, sourceGamma, false );
  3097. m_pTexture = dynamic_cast< ITextureInternal * >( g_pMaterialSystem->CreateProceduralTexture( "SculptProject", TEXTURE_GROUP_OTHER, m_Width, m_Height, imageFormat,
  3098. TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL ) );
  3099. ITextureRegenerator *pRegen = new CSculptRegenerator( m_ImagePixels, m_Width, m_Height, imageFormat );
  3100. m_pTexture->SetTextureRegenerator( pRegen );
  3101. m_pTexture->Download();
  3102. m_pMaterial = MaterialSystemInterface()->FindMaterial( "editor/sculpt", TEXTURE_GROUP_OTHER );
  3103. return true;
  3104. }
  3105. bool CSculptProjectOptions::DoSizing( const Vector2D &vPoint )
  3106. {
  3107. m_ProjectSize.x = m_OriginalProjectSize.x + ( vPoint.x - m_StartSizingPoint.x );
  3108. if ( m_ProjectSize.x < 1.0f )
  3109. {
  3110. m_ProjectSize.x = 1.0f;
  3111. }
  3112. m_ProjectSize.y = m_OriginalProjectSize.y + ( vPoint.y - m_StartSizingPoint.y );
  3113. if ( m_ProjectSize.y < 1.0f )
  3114. {
  3115. m_ProjectSize.y = 1.0f;
  3116. }
  3117. return true;
  3118. }
  3119. bool CSculptProjectOptions::DoPosition( const Vector2D &vPoint )
  3120. {
  3121. m_ProjectLocation.x = m_OriginalProjectLocation.x + ( vPoint.x - m_StartSizingPoint.x );
  3122. m_ProjectLocation.y = m_OriginalProjectLocation.y + ( vPoint.y - m_StartSizingPoint.y );
  3123. return true;
  3124. }
  3125. bool CSculptProjectOptions::DoTiling( const Vector2D &vPoint )
  3126. {
  3127. m_TileWidth += ( vPoint.x - m_StartSizingPoint.x ) / m_ProjectSize.x;
  3128. m_TileHeight += ( vPoint.y - m_StartSizingPoint.y ) / m_ProjectSize.y;
  3129. m_StartSizingPoint = vPoint;
  3130. return true;
  3131. }
  3132. void CSculptProjectOptions::OnNMCustomdrawProjectSize(NMHDR *pNMHDR, LRESULT *pResult)
  3133. {
  3134. // LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
  3135. char temp[ 128 ];
  3136. sprintf( temp, "%d", m_ProjectSizeControl.GetPos() * 16 );
  3137. m_ProjectSizeNumControl.SetWindowText( temp );
  3138. *pResult = 0;
  3139. }
  3140. //-----------------------------------------------------------------------------
  3141. // Purpose: initializes the dialog
  3142. // Output : returns true if successful
  3143. //-----------------------------------------------------------------------------
  3144. BOOL CSculptProjectOptions::OnInitDialog()
  3145. {
  3146. __super::OnInitDialog();
  3147. m_ProjectSizeControl.SetRange( 1, 32 );
  3148. m_ProjectSizeControl.SetTicFreq( 1 );
  3149. m_ProjectSizeControl.SetPageSize( 4 );
  3150. m_ProjectSizeControl.SetLineSize( 4 );
  3151. return TRUE;
  3152. }
  3153. #endif
  3154. // current mouse position updates location of rectangle
  3155. // then rmb = size
  3156. // +control = st adjust
  3157. #include <tier0/memdbgoff.h>