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.

1182 lines
32 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. /*
  9. glapp.c - Simple OpenGL shell
  10. There are several options allowed on the command line. They are:
  11. -height : what window/screen height do you want to use?
  12. -width : what window/screen width do you want to use?
  13. -bpp : what color depth do you want to use?
  14. -window : create a rendering window rather than full-screen
  15. -fov : use a field of view other than 90 degrees
  16. */
  17. //
  18. // Half-Life Model Viewer (c) 1999 by Mete Ciragan
  19. //
  20. // file: MatSysWindow.cpp
  21. // last modified: May 04 1999, Mete Ciragan
  22. // copyright: The programs and associated files contained in this
  23. // distribution were developed by Mete Ciragan. The programs
  24. // are not in the public domain, but they are freely
  25. // distributable without licensing fees. These programs are
  26. // provided without guarantee or warrantee expressed or
  27. // implied.
  28. //
  29. // version: 1.2
  30. //
  31. // email: [email protected]
  32. // web: http://www.swissquake.ch/chumbalum-soft/
  33. //
  34. #include <mxtk/mx.h>
  35. #include <mxtk/mxMessageBox.h>
  36. #include <mxtk/mxTga.h>
  37. #include <mxtk/mxPcx.h>
  38. #include <mxtk/mxBmp.h>
  39. #include <mxtk/mxMatSysWindow.h>
  40. // #include "gl.h"
  41. // #include <GL/glu.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <time.h>
  45. #include <string.h>
  46. #include "MatSysWin.h"
  47. #include "MDLViewer.h"
  48. #include "StudioModel.h"
  49. #include "ControlPanel.h"
  50. #include "ViewerSettings.h"
  51. #include "materialsystem/imaterialsystem.h"
  52. #include "materialsystem/imaterialproxyfactory.h"
  53. #include "filesystem.h"
  54. #include <keyvalues.h>
  55. #include "materialsystem/imesh.h"
  56. #include "materialsystem/IMaterialSystemHardwareConfig.h"
  57. #include "materialsystem/itexture.h"
  58. #include "materialsystem/MaterialSystem_Config.h"
  59. #include "tier0/dbg.h"
  60. #include "istudiorender.h"
  61. #include "tier0/icommandline.h"
  62. #include "mathlib/vmatrix.h"
  63. #include "studio_render.h"
  64. #include "vstdlib/cvar.h"
  65. #include "SoundEmitterSystem/isoundemittersystembase.h"
  66. #include "soundsystem/isoundsystem.h"
  67. #include "soundchars.h"
  68. #include <optimize.h>
  69. #include "valve_ipc_win32.h"
  70. extern char g_appTitle[];
  71. extern bool g_bInError;
  72. extern int g_dxlevel;
  73. extern ISoundEmitterSystemBase *g_pSoundEmitterBase;
  74. extern ISoundSystem *g_pSoundSystem;
  75. extern CValveIpcClientUtl g_HlmvIpcClient;
  76. extern bool g_bHlmvMaster;
  77. void UpdateSounds()
  78. {
  79. static double prev = 0;
  80. double curr = (double) mx::getTickCount () / 1000.0;
  81. if ( prev != 0 )
  82. {
  83. double dt = (curr - prev);
  84. g_pSoundSystem->Update( dt * g_viewerSettings.speedScale );
  85. }
  86. prev = curr;
  87. }
  88. // FIXME: move all this to mxMatSysWin
  89. class DummyMaterialProxyFactory : public IMaterialProxyFactory
  90. {
  91. public:
  92. virtual IMaterialProxy *CreateProxy( const char *proxyName ) {return NULL;}
  93. virtual void DeleteProxy( IMaterialProxy *pProxy ) {}
  94. };
  95. DummyMaterialProxyFactory g_DummyMaterialProxyFactory;
  96. static void ReleaseMaterialSystemObjects()
  97. {
  98. StudioModel::ReleaseStudioModel();
  99. }
  100. static void RestoreMaterialSystemObjects( int nChangeFlags )
  101. {
  102. StudioModel::RestoreStudioModel();
  103. g_ControlPanel->OnLoadModel();
  104. }
  105. void InitMaterialSystemConfig(MaterialSystem_Config_t *pConfig)
  106. {
  107. if ( g_viewerSettings.enableNormalMapping )
  108. {
  109. pConfig->m_Flags &= ~MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP;
  110. }
  111. else
  112. {
  113. pConfig->m_Flags |= MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP;
  114. }
  115. if ( g_viewerSettings.enableSpecular)
  116. {
  117. pConfig->m_Flags &= ~MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR;
  118. }
  119. else
  120. {
  121. pConfig->m_Flags |= MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR;
  122. }
  123. if ( g_viewerSettings.enableParallaxMapping )
  124. {
  125. pConfig->m_Flags |= MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING;
  126. }
  127. else
  128. {
  129. pConfig->m_Flags &= ~MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING;
  130. }
  131. // JasonM...did we foul this up?
  132. }
  133. MatSysWindow *g_MatSysWindow = 0;
  134. Vector g_vright( 50, 50, 0 ); // needs to be set to viewer's right in order for chrome to work
  135. IMaterial *g_materialBackground = NULL;
  136. IMaterial *g_materialWireframe = NULL;
  137. IMaterial *g_materialWireframeVertexColor = NULL;
  138. IMaterial *g_materialWireframeVertexColorNoCull = NULL;
  139. IMaterial *g_materialDebugCopyBaseTexture = NULL;
  140. IMaterial *g_materialFlatshaded = NULL;
  141. IMaterial *g_materialSmoothshaded = NULL;
  142. IMaterial *g_materialBones = NULL;
  143. IMaterial *g_materialLines = NULL;
  144. IMaterial *g_materialFloor = NULL;
  145. IMaterial *g_materialVertexColor = NULL;
  146. IMaterial *g_materialShadow = NULL;
  147. MatSysWindow::MatSysWindow (mxWindow *parent, int x, int y, int w, int h, const char *label, int style)
  148. : mxMatSysWindow (parent, x, y, w, h, label, style)
  149. {
  150. g_pMaterialSystem->SetMaterialProxyFactory( &g_DummyMaterialProxyFactory );
  151. m_pCubemapTexture = NULL;
  152. m_hWnd = (HWND)getHandle();
  153. MaterialSystem_Config_t config;
  154. config = g_pMaterialSystem->GetCurrentConfigForVideoCard();
  155. InitMaterialSystemConfig(&config);
  156. if ( g_dxlevel != 0 )
  157. {
  158. config.dxSupportLevel = g_dxlevel;
  159. }
  160. // config.m_VideoMode.m_Width = config.m_VideoMode.m_Height = 0;
  161. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  162. config.SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, true );
  163. if (!g_pMaterialSystem->SetMode( ( void * )m_hWnd, config ) )
  164. {
  165. return;
  166. }
  167. g_pMaterialSystem->OverrideConfig( config, false );
  168. g_pMaterialSystem->AddReleaseFunc( ReleaseMaterialSystemObjects );
  169. g_pMaterialSystem->AddRestoreFunc( RestoreMaterialSystemObjects );
  170. m_pCubemapTexture = g_pMaterialSystem->FindTexture( "hlmv/cubemap", NULL, true );
  171. m_pCubemapTexture->IncrementReferenceCount();
  172. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  173. pRenderContext->BindLocalCubemap( m_pCubemapTexture );
  174. g_materialBackground = g_pMaterialSystem->FindMaterial("hlmv/background", TEXTURE_GROUP_OTHER, true);
  175. if ( g_materialBackground )
  176. {
  177. g_materialBackground->AddRef();
  178. }
  179. g_materialWireframe = g_pMaterialSystem->FindMaterial("debug/debugmrmwireframe", TEXTURE_GROUP_OTHER, true);
  180. if ( g_materialWireframe )
  181. {
  182. g_materialWireframe->AddRef();
  183. }
  184. g_materialWireframeVertexColor = g_pMaterialSystem->FindMaterial("debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER, true);
  185. if ( g_materialWireframeVertexColor )
  186. {
  187. g_materialWireframeVertexColor->AddRef();
  188. }
  189. // test: create this from code - you need a vmt to make $nocull 1 happen, can't do it from the render context
  190. {
  191. KeyValues *pVMTKeyValues = new KeyValues( "Wireframe" );
  192. pVMTKeyValues->SetInt("$ignorez", 1);
  193. pVMTKeyValues->SetInt("$nocull", 1);
  194. pVMTKeyValues->SetInt("$vertexcolor", 1);
  195. pVMTKeyValues->SetInt("$decal", 1);
  196. g_materialWireframeVertexColorNoCull = g_pMaterialSystem->CreateMaterial( "debug/wireframenocull", pVMTKeyValues );
  197. if ( g_materialWireframeVertexColorNoCull )
  198. {
  199. g_materialWireframeVertexColorNoCull->AddRef();
  200. }
  201. }
  202. {
  203. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  204. pVMTKeyValues->SetString("$basetexture", "vgui/white" );
  205. g_materialDebugCopyBaseTexture = g_pMaterialSystem->CreateMaterial( "debug/copybasetexture", pVMTKeyValues );
  206. if ( g_materialDebugCopyBaseTexture )
  207. {
  208. g_materialDebugCopyBaseTexture->AddRef();
  209. }
  210. }
  211. g_materialFlatshaded = g_pMaterialSystem->FindMaterial("debug/debugdrawflatpolygons", TEXTURE_GROUP_OTHER, true);
  212. if ( g_materialFlatshaded )
  213. {
  214. g_materialFlatshaded->AddRef();
  215. }
  216. g_materialSmoothshaded = g_pMaterialSystem->FindMaterial("debug/debugmrmfullbright2", TEXTURE_GROUP_OTHER, true);
  217. if ( g_materialSmoothshaded )
  218. {
  219. g_materialSmoothshaded->AddRef();
  220. }
  221. g_materialBones = g_pMaterialSystem->FindMaterial("debug/debugskeleton", TEXTURE_GROUP_OTHER, true);
  222. if ( g_materialBones )
  223. {
  224. g_materialBones->AddRef();
  225. }
  226. g_materialLines = g_pMaterialSystem->FindMaterial("debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER, true);
  227. if ( g_materialLines )
  228. {
  229. g_materialLines->AddRef();
  230. }
  231. g_materialFloor = g_pMaterialSystem->FindMaterial("hlmv/floor", TEXTURE_GROUP_OTHER, true);
  232. if ( g_materialFloor )
  233. {
  234. g_materialFloor->AddRef();
  235. }
  236. g_materialVertexColor = g_pMaterialSystem->FindMaterial("debug/debugvertexcolor", TEXTURE_GROUP_OTHER, true);
  237. if ( g_materialVertexColor )
  238. {
  239. g_materialVertexColor->AddRef();
  240. }
  241. g_materialShadow = g_pMaterialSystem->FindMaterial("hlmv/shadow", TEXTURE_GROUP_OTHER, true);
  242. if ( g_materialShadow )
  243. {
  244. g_materialShadow->AddRef();
  245. }
  246. if (!parent)
  247. setVisible (true);
  248. else
  249. mx::setIdleWindow (this);
  250. }
  251. MatSysWindow::~MatSysWindow ()
  252. {
  253. if (m_pCubemapTexture)
  254. {
  255. m_pCubemapTexture->DecrementReferenceCount();
  256. }
  257. mx::setIdleWindow (0);
  258. }
  259. int
  260. MatSysWindow::handleEvent (mxEvent *event)
  261. {
  262. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  263. static float oldrx = 0, oldry = 0, oldtz = 50, oldtx = 0, oldty = 0;
  264. static float oldlrx = 0, oldlry = 0;
  265. static int oldx, oldy;
  266. switch (event->event)
  267. {
  268. case mxEvent::Idle:
  269. {
  270. static double prev;
  271. double curr = (double) mx::getTickCount () / 1000.0;
  272. double dt = (curr - prev);
  273. // clamp to 100fps
  274. if (dt >= 0.0 && dt < 0.01)
  275. {
  276. Sleep( 10 - dt * 1000.0 );
  277. return 1;
  278. }
  279. if ( prev != 0.0 )
  280. {
  281. // dt = 0.001;
  282. g_pStudioModel->AdvanceFrame ( dt * g_viewerSettings.speedScale );
  283. if ( g_viewerSettings.animateWeapons )
  284. {
  285. const char *pszMainSequenceName = g_pStudioModel->GetSequenceName( g_pStudioModel->GetSequence() );
  286. if ( pszMainSequenceName )
  287. {
  288. for ( int i = 0; i < HLMV_MAX_MERGED_MODELS; i++ )
  289. {
  290. if ( !g_pStudioExtraModel[ i ] )
  291. continue;
  292. // match weapon sequence and frame to marine
  293. int iSequence = g_pStudioExtraModel[ i ]->LookupSequence( pszMainSequenceName );
  294. if ( iSequence == -1 )
  295. {
  296. g_pStudioExtraModel[ i ]->SetFrame( 0 );
  297. }
  298. else
  299. {
  300. g_pStudioExtraModel[ i ]->SetSequence( iSequence );
  301. g_pStudioExtraModel[ i ]->SetFrame( g_pStudioModel->GetCycle() * g_pStudioExtraModel[ i ]->GetMaxFrame() );
  302. }
  303. }
  304. }
  305. }
  306. g_ControlPanel->updateFrameSlider( );
  307. g_ControlPanel->updateGroundSpeed( );
  308. }
  309. prev = curr;
  310. if (!g_viewerSettings.pause)
  311. redraw ();
  312. g_ControlPanel->updateTransitionAmount();
  313. UpdateSounds();
  314. return 1;
  315. }
  316. break;
  317. case mxEvent::MouseUp:
  318. {
  319. g_viewerSettings.mousedown = false;
  320. }
  321. break;
  322. case mxEvent::MouseDown:
  323. {
  324. g_viewerSettings.mousedown = true;
  325. oldrx = g_pStudioModel->m_angles[0];
  326. oldry = g_pStudioModel->m_angles[1];
  327. oldtx = g_pStudioModel->m_origin[0];
  328. oldty = g_pStudioModel->m_origin[1];
  329. oldtz = g_pStudioModel->m_origin[2];
  330. oldx = event->x;
  331. oldy = event->y;
  332. oldlrx = g_viewerSettings.lightrot[1];
  333. oldlry = g_viewerSettings.lightrot[0];
  334. g_viewerSettings.pause = false;
  335. float r = 1.0/3.0 * min( w(), h() );
  336. float d = sqrt( ( float )( (event->x - w()/2) * (event->x - w()/2) + (event->y - h()/2) * (event->y - h()/2) ) );
  337. if (d < r)
  338. g_viewerSettings.rotating = false;
  339. else
  340. g_viewerSettings.rotating = true;
  341. return 1;
  342. }
  343. break;
  344. case mxEvent::MouseDrag:
  345. {
  346. bool bSendModelTransform = true;
  347. if ( event->buttons & mxEvent::MouseLeftButton )
  348. {
  349. if ( event->modifiers & mxEvent::KeyShift )
  350. {
  351. g_pStudioModel->m_origin[1] = oldty - (float)( event->x - oldx );
  352. g_pStudioModel->m_origin[2] = oldtz + (float)( event->y - oldy );
  353. }
  354. else if ( event->modifiers & mxEvent::KeyCtrl )
  355. {
  356. float ry = (float)( event->y - oldy );
  357. float rx = (float)( event->x - oldx );
  358. oldx = event->x;
  359. oldy = event->y;
  360. QAngle movement = QAngle( ry, rx, 0 );
  361. matrix3x4_t tmp1, tmp2, tmp3;
  362. AngleMatrix( g_viewerSettings.lightrot, tmp1 );
  363. AngleMatrix( movement, tmp2 );
  364. ConcatTransforms( tmp2, tmp1, tmp3 );
  365. MatrixAngles( tmp3, g_viewerSettings.lightrot );
  366. // g_viewerSettings.lightrot[0] = oldlrx + (float) (event->y - oldy);
  367. // g_viewerSettings.lightrot[1] = oldlry + (float) (event->x - oldx);
  368. bSendModelTransform = false;
  369. }
  370. else
  371. {
  372. if ( !g_viewerSettings.rotating )
  373. {
  374. float ry = (float)( event->y - oldy );
  375. float rx = (float)( event->x - oldx );
  376. oldx = event->x;
  377. oldy = event->y;
  378. QAngle movement;
  379. matrix3x4_t tmp1, tmp2, tmp3;
  380. movement = QAngle( 0, rx, 0 );
  381. AngleMatrix( g_pStudioModel->m_angles, tmp1 );
  382. AngleMatrix( movement, tmp2 );
  383. ConcatTransforms( tmp1, tmp2, tmp3 );
  384. MatrixAngles( tmp3, g_pStudioModel->m_angles );
  385. movement = QAngle( ry, 0, 0 );
  386. AngleMatrix( g_pStudioModel->m_angles, tmp1 );
  387. AngleMatrix( movement, tmp2 );
  388. ConcatTransforms( tmp2, tmp1, tmp3 );
  389. MatrixAngles( tmp3, g_pStudioModel->m_angles );
  390. }
  391. else
  392. {
  393. float ang1 = ( 180 / 3.1415 ) * atan2( oldx - w() / 2.0, oldy - h() / 2.0 );
  394. float ang2 = ( 180 / 3.1415 ) * atan2( event->x - w() / 2.0, event->y - h() / 2.0 );
  395. oldx = event->x;
  396. oldy = event->y;
  397. QAngle movement = QAngle( 0, 0, ang2 - ang1 );
  398. matrix3x4_t tmp1, tmp2, tmp3;
  399. AngleMatrix( g_pStudioModel->m_angles, tmp1 );
  400. AngleMatrix( movement, tmp2 );
  401. ConcatTransforms( tmp2, tmp1, tmp3 );
  402. MatrixAngles( tmp3, g_pStudioModel->m_angles );
  403. }
  404. }
  405. }
  406. else if ( event->buttons & mxEvent::MouseRightButton )
  407. {
  408. g_pStudioModel->m_origin[0] = oldtx + (float)( event->y - oldy );
  409. }
  410. if ( g_bHlmvMaster )
  411. {
  412. if ( bSendModelTransform )
  413. {
  414. g_MDLViewer->SendModelTransformToLinkedHlmv();
  415. }
  416. else
  417. {
  418. g_MDLViewer->SendLightRotToLinkedHlmv();
  419. }
  420. }
  421. redraw();
  422. return 1;
  423. }
  424. break;
  425. case mxEvent::KeyDown:
  426. {
  427. switch (event->key)
  428. {
  429. case VK_F5: // F5
  430. {
  431. g_MDLViewer->Refresh();
  432. break;
  433. }
  434. case 32:
  435. {
  436. int iSeq = g_pStudioModel->GetSequence ();
  437. if (iSeq == g_pStudioModel->SetSequence (iSeq + 1))
  438. {
  439. g_pStudioModel->SetSequence (0);
  440. }
  441. }
  442. break;
  443. }
  444. }
  445. break;
  446. } // switch (event->event)
  447. return 1;
  448. }
  449. void DrawBackground()
  450. {
  451. if (!g_viewerSettings.showBackground)
  452. return;
  453. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  454. pRenderContext->Bind(g_materialBackground);
  455. pRenderContext->MatrixMode(MATERIAL_MODEL);
  456. pRenderContext->PushMatrix();
  457. pRenderContext->LoadIdentity();
  458. pRenderContext->MatrixMode(MATERIAL_VIEW);
  459. pRenderContext->PushMatrix();
  460. pRenderContext->LoadIdentity();
  461. {
  462. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  463. CMeshBuilder meshBuilder;
  464. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  465. float dist=-15000.0f;
  466. float tMin=0, tMax=1;
  467. meshBuilder.Position3f(-dist, dist, dist);
  468. meshBuilder.TexCoord2f( 0, tMin,tMax );
  469. meshBuilder.Color4ub( 255, 255, 255, 255 );
  470. meshBuilder.AdvanceVertex();
  471. meshBuilder.Position3f( dist, dist, dist);
  472. meshBuilder.TexCoord2f( 0, tMax,tMax );
  473. meshBuilder.Color4ub( 255, 255, 255, 255 );
  474. meshBuilder.AdvanceVertex();
  475. meshBuilder.Position3f( dist,-dist, dist);
  476. meshBuilder.TexCoord2f( 0, tMax,tMin );
  477. meshBuilder.Color4ub( 255, 255, 255, 255 );
  478. meshBuilder.AdvanceVertex();
  479. meshBuilder.Position3f(-dist,-dist, dist);
  480. meshBuilder.TexCoord2f( 0, tMin,tMin );
  481. meshBuilder.Color4ub( 255, 255, 255, 255 );
  482. meshBuilder.AdvanceVertex();
  483. meshBuilder.End();
  484. pMesh->Draw();
  485. }
  486. }
  487. void DrawHelpers()
  488. {
  489. if (g_viewerSettings.mousedown)
  490. {
  491. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  492. pRenderContext->Bind( g_materialBones );
  493. pRenderContext->MatrixMode(MATERIAL_MODEL);
  494. pRenderContext->LoadIdentity();
  495. pRenderContext->MatrixMode(MATERIAL_VIEW);
  496. pRenderContext->LoadIdentity();
  497. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  498. CMeshBuilder meshBuilder;
  499. meshBuilder.Begin( pMesh, MATERIAL_LINES, 360 / 5 );
  500. if (g_viewerSettings.rotating)
  501. meshBuilder.Color3ub( 255, 255, 0 );
  502. else
  503. meshBuilder.Color3ub( 0, 255, 0 );
  504. for (int i = 0; i < 360; i += 5)
  505. {
  506. float a = i * (3.151492653/180.0f);
  507. if (g_viewerSettings.rotating)
  508. meshBuilder.Color3ub( 255, 255, 0 );
  509. else
  510. meshBuilder.Color3ub( 0, 255, 0 );
  511. meshBuilder.Position3f( sin( a ), cos( a ), -3.0f );
  512. meshBuilder.AdvanceVertex();
  513. }
  514. meshBuilder.End();
  515. pMesh->Draw();
  516. }
  517. }
  518. void DrawGroundPlane()
  519. {
  520. if (!g_viewerSettings.showGround)
  521. return;
  522. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  523. pRenderContext->Bind(g_materialFloor);
  524. pRenderContext->MatrixMode(MATERIAL_MODEL);
  525. pRenderContext->PushMatrix();;
  526. pRenderContext->LoadIdentity();
  527. pRenderContext->MatrixMode(MATERIAL_VIEW);
  528. pRenderContext->PushMatrix();;
  529. pRenderContext->LoadIdentity();
  530. pRenderContext->MatrixMode( MATERIAL_VIEW );
  531. pRenderContext->LoadIdentity( );
  532. pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
  533. pRenderContext->Rotate( -90, 0, 0, 1 );
  534. pRenderContext->Translate( -g_pStudioModel->m_origin[0], -g_pStudioModel->m_origin[1], -g_pStudioModel->m_origin[2] );
  535. pRenderContext->Rotate( g_pStudioModel->m_angles[1], 0, 0, 1 );
  536. pRenderContext->Rotate( g_pStudioModel->m_angles[0], 0, 1, 0 );
  537. pRenderContext->Rotate( g_pStudioModel->m_angles[2], 1, 0, 0 );
  538. static Vector tMap( 0, 0, 0 );
  539. static Vector dxMap( 1, 0, 0 );
  540. static Vector dyMap( 0, 1, 0 );
  541. Vector deltaPos;
  542. QAngle deltaAngles;
  543. g_pStudioModel->GetMovement( g_pStudioModel->m_prevGroundCycles, deltaPos, deltaAngles );
  544. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  545. CMeshBuilder meshBuilder;
  546. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  547. float scale = 10.0;
  548. float dist=-100.0f;
  549. float dpdd = scale / dist;
  550. tMap.x = tMap.x + dxMap.x * deltaPos.x * dpdd + dxMap.y * deltaPos.y * dpdd;
  551. tMap.y = tMap.y + dyMap.x * deltaPos.x * dpdd + dyMap.y * deltaPos.y * dpdd;
  552. while (tMap.x < 0.0) tMap.x += 1.0;
  553. while (tMap.x > 1.0) tMap.x += -1.0;
  554. while (tMap.y < 0.0) tMap.y += 1.0;
  555. while (tMap.y > 1.0) tMap.y += -1.0;
  556. VectorYawRotate( dxMap, -deltaAngles.y, dxMap );
  557. VectorYawRotate( dyMap, -deltaAngles.y, dyMap );
  558. // ARRGHHH, this is right but I don't know what I've done
  559. meshBuilder.Position3f( -dist, dist, 0 );
  560. meshBuilder.TexCoord2f( 0, tMap.x + (-dxMap.x - dyMap.x) * scale, tMap.y + (dxMap.y + dyMap.y) * scale );
  561. meshBuilder.Color4ub( 128, 128, 128, 255 );
  562. meshBuilder.AdvanceVertex();
  563. meshBuilder.Position3f( dist, dist, 0 );
  564. meshBuilder.TexCoord2f( 0, tMap.x + (dxMap.x - dyMap.x) * scale, tMap.y + (-dxMap.y + dyMap.y) * scale );
  565. meshBuilder.Color4ub( 128, 128, 128, 255 );
  566. meshBuilder.AdvanceVertex();
  567. meshBuilder.Position3f( dist, -dist, 0 );
  568. meshBuilder.TexCoord2f( 0, tMap.x + (dxMap.x + dyMap.x) * scale, tMap.y + (-dxMap.y - dyMap.y) * scale );
  569. meshBuilder.Color4ub( 128, 128, 128, 255 );
  570. meshBuilder.AdvanceVertex();
  571. meshBuilder.Position3f( -dist, -dist, 0 );
  572. meshBuilder.TexCoord2f( 0, tMap.x - (dxMap.x - dyMap.x) * scale, tMap.y - (-dxMap.y + dyMap.y) * scale );
  573. meshBuilder.Color4ub( 128, 128, 128, 255 );
  574. meshBuilder.AdvanceVertex();
  575. // draw underside
  576. meshBuilder.Position3f( -dist, dist, 0 );
  577. meshBuilder.TexCoord2f( 0, tMap.x + (-dxMap.x - dyMap.x) * scale, tMap.y + (dxMap.y + dyMap.y) * scale );
  578. meshBuilder.Color4ub( 128, 128, 128, 128 );
  579. meshBuilder.AdvanceVertex();
  580. meshBuilder.Position3f( -dist, -dist, 0 );
  581. meshBuilder.TexCoord2f( 0, tMap.x - (dxMap.x - dyMap.x) * scale, tMap.y - (-dxMap.y + dyMap.y) * scale );
  582. meshBuilder.Color4ub( 128, 128, 128, 128 );
  583. meshBuilder.AdvanceVertex();
  584. meshBuilder.Position3f( dist, -dist, 0 );
  585. meshBuilder.TexCoord2f( 0, tMap.x + (dxMap.x + dyMap.x) * scale, tMap.y + (-dxMap.y - dyMap.y) * scale );
  586. meshBuilder.Color4ub( 128, 128, 128, 128 );
  587. meshBuilder.AdvanceVertex();
  588. meshBuilder.Position3f( dist, dist, 0 );
  589. meshBuilder.TexCoord2f( 0, tMap.x + (dxMap.x - dyMap.x) * scale, tMap.y + (-dxMap.y + dyMap.y) * scale );
  590. meshBuilder.Color4ub( 128, 128, 128, 128 );
  591. meshBuilder.AdvanceVertex();
  592. meshBuilder.End();
  593. pMesh->Draw();
  594. pRenderContext->MatrixMode(MATERIAL_MODEL);
  595. pRenderContext->PopMatrix();
  596. pRenderContext->MatrixMode(MATERIAL_VIEW);
  597. pRenderContext->PopMatrix();
  598. }
  599. void DrawMovementBoxes()
  600. {
  601. if (!g_viewerSettings.showMovement)
  602. return;
  603. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  604. pRenderContext->Bind(g_materialFloor);
  605. pRenderContext->MatrixMode(MATERIAL_MODEL);
  606. pRenderContext->PushMatrix();
  607. pRenderContext->LoadIdentity();
  608. pRenderContext->MatrixMode(MATERIAL_VIEW);
  609. pRenderContext->PushMatrix();
  610. pRenderContext->LoadIdentity();
  611. pRenderContext->MatrixMode( MATERIAL_VIEW );
  612. pRenderContext->LoadIdentity( );
  613. pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
  614. pRenderContext->Rotate( -90, 0, 0, 1 );
  615. pRenderContext->Translate( -g_pStudioModel->m_origin[0], -g_pStudioModel->m_origin[1], -g_pStudioModel->m_origin[2] );
  616. pRenderContext->Rotate( g_pStudioModel->m_angles[1], 0, 0, 1 );
  617. pRenderContext->Rotate( g_pStudioModel->m_angles[0], 0, 1, 0 );
  618. pRenderContext->Rotate( g_pStudioModel->m_angles[2], 1, 0, 0 );
  619. static matrix3x4_t mStart( 1, 0, 0, 0 , 0, 1, 0, 0 , 0, 0, 1, 0 );
  620. matrix3x4_t mTemp;
  621. static float prevframes[5];
  622. Vector deltaPos;
  623. QAngle deltaAngles;
  624. g_pStudioModel->GetMovement( prevframes, deltaPos, deltaAngles );
  625. AngleMatrix( deltaAngles, deltaPos, mTemp );
  626. MatrixInvert( mTemp, mTemp );
  627. ConcatTransforms( mTemp, mStart, mStart );
  628. Vector bboxMin, bboxMax;
  629. g_pStudioModel->ExtractBbox( bboxMin, bboxMax );
  630. static float prevCycle = 0.0;
  631. if (fabs( g_pStudioModel->GetFrame( 0 ) - prevCycle) > 0.5)
  632. {
  633. SetIdentityMatrix( mStart );
  634. }
  635. prevCycle = g_pStudioModel->GetFrame( 0 );
  636. // starting position
  637. {
  638. float color[] = { 0.7, 1, 0, 0.5 };
  639. float wirecolor[] = { 1, 1, 0, 1.0 };
  640. g_pStudioModel->drawTransparentBox( bboxMin, bboxMax, mStart, color, wirecolor );
  641. }
  642. // current position
  643. {
  644. float color[] = { 1, 0.7, 0, 0.5 };
  645. float wirecolor[] = { 1, 0, 0, 1.0 };
  646. SetIdentityMatrix( mTemp );
  647. g_pStudioModel->drawTransparentBox( bboxMin, bboxMax, mTemp, color, wirecolor );
  648. }
  649. pRenderContext->MatrixMode(MATERIAL_MODEL);
  650. pRenderContext->PopMatrix();
  651. pRenderContext->MatrixMode(MATERIAL_VIEW);
  652. pRenderContext->PopMatrix();
  653. }
  654. char const *HLMV_TranslateSoundName( char const *soundname, StudioModel *model )
  655. {
  656. if ( Q_stristr( soundname, ".wav" ) )
  657. return PSkipSoundChars( soundname );
  658. if ( model )
  659. {
  660. return PSkipSoundChars( g_pSoundEmitterBase->GetWavFileForSound( soundname, model->GetFileName() ) );
  661. }
  662. return PSkipSoundChars( g_pSoundEmitterBase->GetWavFileForSound( soundname, NULL ) );
  663. }
  664. void PlaySound( const char *pSoundName, StudioModel *pStudioModel )
  665. {
  666. // Play Sound
  667. if (!g_viewerSettings.playSounds)
  668. return;
  669. if ( pSoundName == NULL || pSoundName[ 0 ] == '\0' )
  670. return;
  671. const char *pSoundFileName = HLMV_TranslateSoundName( pSoundName, pStudioModel );
  672. char filename[ 256 ];
  673. sprintf( filename, "sound/%s", pSoundFileName );
  674. CAudioSource *pAudioSource = g_pSoundSystem->FindOrAddSound( filename );
  675. if ( pAudioSource == NULL )
  676. return;
  677. float volume = VOL_NORM;
  678. gender_t gender = GENDER_NONE;
  679. if ( pStudioModel )
  680. {
  681. gender = g_pSoundEmitterBase->GetActorGender( pStudioModel->GetFileName() );
  682. }
  683. CSoundParameters params;
  684. if ( !Q_stristr( pSoundName, ".wav" ) &&
  685. g_pSoundEmitterBase->GetParametersForSound( pSoundName, params, gender ) )
  686. {
  687. volume = params.volume;
  688. }
  689. g_pSoundSystem->PlaySound( pAudioSource, volume, NULL );
  690. }
  691. // copied from baseentity.cpp
  692. // HACK: This must match the #define in cl_animevent.h in the client .dll code!!!
  693. #define CL_EVENT_SOUND 5004
  694. #define CL_EVENT_FOOTSTEP_LEFT 6004
  695. #define CL_EVENT_FOOTSTEP_RIGHT 6005
  696. #define CL_EVENT_MFOOTSTEP_LEFT 6006
  697. #define CL_EVENT_MFOOTSTEP_RIGHT 6007
  698. // copied from scriptevent.h
  699. #define SCRIPT_EVENT_SOUND 1004 // Play named wave file (on CHAN_BODY)
  700. #define SCRIPT_EVENT_SOUND_VOICE 1008 // Play named wave file (on CHAN_VOICE)
  701. void PlaySounds( StudioModel *pStudioModel )
  702. {
  703. if ( pStudioModel == NULL )
  704. return;
  705. int iLayer = g_ControlPanel->getFrameSelection();
  706. float flFrame = pStudioModel->GetFrame( iLayer );
  707. float flTime = flFrame / 30.0f; // pStudioModel->GetSequenceTime()
  708. float prevtime = flTime - pStudioModel->GetTimeDelta();
  709. float currtime = flTime;
  710. float duration = pStudioModel->GetDuration();
  711. prevtime = fmod( prevtime, duration );
  712. currtime = fmod( currtime, duration );
  713. float prevcycle = prevtime / duration;
  714. float currcycle = currtime / duration;
  715. CStudioHdr *pStudioHdr = pStudioModel->GetStudioHdr();
  716. if ( pStudioHdr == NULL )
  717. return;
  718. int seq = pStudioModel->GetSequence();
  719. mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( seq );
  720. for ( int i = 0; i < (int)seqdesc.numevents; ++i )
  721. {
  722. mstudioevent_t *pEvent = seqdesc.pEvent( i );
  723. #if defined( _DEBUG )
  724. const char *pEventName = pEvent->pszEventName();
  725. NOTE_UNUSED( pEventName );
  726. #endif
  727. if ( pEvent->cycle <= prevcycle || pEvent->cycle > currcycle )
  728. continue;
  729. // largely copied from BuildAnimationEventSoundList in baseentity.cpp
  730. switch ( pEvent->event )
  731. {
  732. case 0:
  733. if ( Q_strcmp( pEvent->pszEventName(), "AE_CL_PLAYSOUND" ) == 0 )
  734. {
  735. PlaySound( pEvent->pszOptions(), pStudioModel );
  736. continue;
  737. }
  738. break;
  739. case CL_EVENT_SOUND: // Old-style client .dll animation event
  740. // fall-through intentional
  741. case SCRIPT_EVENT_SOUND:
  742. // fall-through intentional
  743. case SCRIPT_EVENT_SOUND_VOICE:
  744. PlaySound( pEvent->pszOptions(), pStudioModel );
  745. break;
  746. case CL_EVENT_FOOTSTEP_LEFT:
  747. case CL_EVENT_FOOTSTEP_RIGHT:
  748. {
  749. char soundname[256];
  750. char const *options = pEvent->pszOptions();
  751. if ( !options || !options[0] )
  752. {
  753. options = "NPC_CombineS";
  754. }
  755. Q_snprintf( soundname, 256, "%s.RunFootstepLeft", options );
  756. PlaySound( soundname, pStudioModel );
  757. Q_snprintf( soundname, 256, "%s.RunFootstepRight", options );
  758. PlaySound( soundname, pStudioModel );
  759. Q_snprintf( soundname, 256, "%s.FootstepLeft", options );
  760. PlaySound( soundname, pStudioModel );
  761. Q_snprintf( soundname, 256, "%s.FootstepRight", options );
  762. PlaySound( soundname, pStudioModel );
  763. }
  764. break;
  765. /*
  766. case AE_CL_PLAYSOUND:
  767. if ( !( pEvent->type & AE_TYPE_CLIENT ) )
  768. break;
  769. if ( pEvent->options[0] )
  770. {
  771. PlaySound( pEvent->options, pStudioModel );
  772. }
  773. else
  774. {
  775. Warning( "-- Error --: empty soundname, .qc error on AE_CL_PLAYSOUND in model %s, sequence %s, animevent # %i\n",
  776. pStudioHdr->name(), seqdesc.pszLabel(), i + 1 );
  777. }
  778. break;
  779. */
  780. default:
  781. break;
  782. }
  783. }
  784. }
  785. void
  786. MatSysWindow::draw ()
  787. {
  788. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  789. if ( g_bInError || !g_pStudioModel->GetStudioRender() )
  790. return;
  791. static bool bInDraw = false;
  792. if (bInDraw)
  793. return;
  794. bInDraw = true;
  795. UpdateSounds(); // need to call this multiple times per frame to avoid audio stuttering
  796. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  797. g_pMaterialSystem->BeginFrame( 0 );
  798. g_pStudioModel->GetStudioRender()->BeginFrame();
  799. pRenderContext->ClearColor3ub(g_viewerSettings.bgColor[0] * 255, g_viewerSettings.bgColor[1] * 255, g_viewerSettings.bgColor[2] * 255);
  800. // pRenderContext->ClearColor3ub(0, 0, 0 );
  801. pRenderContext->ClearBuffers(true, true);
  802. pRenderContext->Viewport( 0, 0, w(), h() );
  803. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  804. pRenderContext->LoadIdentity( );
  805. pRenderContext->PerspectiveX(g_viewerSettings.fov, (float)w() / (float)h(), 1.0f, 20000.0f);
  806. DrawBackground();
  807. DrawGroundPlane();
  808. DrawMovementBoxes();
  809. DrawHelpers();
  810. pRenderContext->MatrixMode( MATERIAL_VIEW );
  811. pRenderContext->LoadIdentity( );
  812. // FIXME: why is this needed? Doesn't SetView() override this?
  813. pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
  814. pRenderContext->Rotate( -90, 0, 0, 1 );
  815. g_pStudioModel->ClearLookTargets();
  816. g_pStudioModel->AddLookTarget( Vector( 0, 0, 0 ), g_pStudioModel->GetSolveHeadTurn() ? 1.0f : 0.0f );
  817. int polycount = g_pStudioModel->DrawModel ();
  818. g_pStudioModel->GetStudioRender()->EndFrame();
  819. UpdateSounds(); // need to call this multiple times per frame to avoid audio stuttering
  820. g_ControlPanel->setModelInfo();
  821. int lod;
  822. float metric;
  823. metric = g_pStudioModel->GetLodMetric();
  824. lod = g_pStudioModel->GetLodUsed();
  825. g_ControlPanel->setLOD( lod, true, false );
  826. g_ControlPanel->setLODMetric( metric );
  827. g_ControlPanel->setPolycount( polycount );
  828. int nVertCount = 0;
  829. int nIndexCount = 0;
  830. int nTriCount = 0;
  831. CStudioHdr *pStudioHdr = g_pStudioModel->GetStudioHdr();
  832. if ( pStudioHdr != NULL )
  833. {
  834. studiohwdata_t *pHardwareData = g_pStudioModel->GetHardwareData();
  835. if ( pHardwareData != NULL )
  836. {
  837. studioloddata_t *pLODData = &pHardwareData->m_pLODs[ pHardwareData->m_RootLOD ];
  838. for ( int meshID = 0; meshID < pHardwareData->m_NumStudioMeshes; meshID++ )
  839. {
  840. studiomeshdata_t *pMesh = &pLODData->m_pMeshData[meshID];
  841. for ( int groupID = 0; groupID < pMesh->m_NumGroup; groupID++ )
  842. {
  843. studiomeshgroup_t *pMeshGroup = &pMesh->m_pMeshGroup[ groupID ];
  844. for( int j = 0; j < pMeshGroup->m_NumStrips; j++ )
  845. {
  846. nIndexCount += pMeshGroup->m_pStripData[ j ].numIndices;
  847. nVertCount += pMeshGroup->m_pStripData[ j ].numVerts;
  848. nTriCount += ( pMeshGroup->m_pStripData[ j ].numIndices / 3 );
  849. }
  850. }
  851. }
  852. }
  853. }
  854. g_ControlPanel->setModelInfo( nVertCount, nIndexCount, nTriCount );
  855. g_ControlPanel->setTransparent( g_pStudioModel->m_bIsTransparent );
  856. g_ControlPanel->updatePoseParameters( );
  857. // draw what ever else is loaded
  858. int i;
  859. for (i = 0; i < HLMV_MAX_MERGED_MODELS; i++)
  860. {
  861. if (g_pStudioExtraModel[i] != NULL)
  862. {
  863. g_pStudioModel->GetStudioRender()->BeginFrame();
  864. g_pStudioExtraModel[i]->DrawModel( true );
  865. g_pStudioModel->GetStudioRender()->EndFrame();
  866. }
  867. }
  868. g_pStudioModel->IncrementFramecounter();
  869. PlaySounds( g_pStudioModel );
  870. UpdateSounds(); // need to call this multiple times per frame to avoid audio stuttering
  871. g_pMaterialSystem->SwapBuffers();
  872. g_pMaterialSystem->EndFrame();
  873. bInDraw = false;
  874. }
  875. /*
  876. int
  877. MatSysWindow::loadTexture (const char *filename, int name)
  878. {
  879. if (!filename || !strlen (filename))
  880. {
  881. if (d_textureNames[name])
  882. {
  883. glDeleteTextures (1, (const GLuint *) &d_textureNames[name]);
  884. d_textureNames[name] = 0;
  885. if (name == 0)
  886. strcpy (g_viewerSettings.backgroundTexFile, "");
  887. else
  888. strcpy (g_viewerSettings.groundTexFile, "");
  889. }
  890. return 0;
  891. }
  892. mxImage *image = 0;
  893. char ext[16];
  894. strcpy (ext, mx_getextension (filename));
  895. if (!mx_strcasecmp (ext, ".tga"))
  896. image = mxTgaRead (filename);
  897. else if (!mx_strcasecmp (ext, ".pcx"))
  898. image = mxPcxRead (filename);
  899. else if (!mx_strcasecmp (ext, ".bmp"))
  900. image = mxBmpRead (filename);
  901. if (image)
  902. {
  903. if (name == 0)
  904. strcpy (g_viewerSettings.backgroundTexFile, filename);
  905. else
  906. strcpy (g_viewerSettings.groundTexFile, filename);
  907. d_textureNames[name] = name + 1;
  908. if (image->bpp == 8)
  909. {
  910. mstudiotexture_t texture;
  911. texture.width = image->width;
  912. texture.height = image->height;
  913. g_pStudioModel->UploadTexture (&texture, (byte *) image->data, (byte *) image->palette, name + 1);
  914. }
  915. else
  916. {
  917. glBindTexture (GL_TEXTURE_2D, d_textureNames[name]);
  918. glTexImage2D (GL_TEXTURE_2D, 0, 3, image->width, image->height, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data);
  919. glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  920. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  921. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  922. }
  923. delete image;
  924. return name + 1;
  925. }
  926. return 0;
  927. }
  928. */
  929. void
  930. MatSysWindow::dumpViewport (const char *filename)
  931. {
  932. redraw ();
  933. int w = w2 ();
  934. int h = h2 ();
  935. mxImage *image = new mxImage ();
  936. if (image->create (w, h, 24))
  937. {
  938. #if 0
  939. glReadBuffer (GL_FRONT);
  940. glReadPixels (0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, image->data);
  941. #else
  942. HDC hdc = GetDC ((HWND) getHandle ());
  943. byte *data = (byte *) image->data;
  944. int i = 0;
  945. for (int y = 0; y < h; y++)
  946. {
  947. for (int x = 0; x < w; x++)
  948. {
  949. COLORREF cref = GetPixel (hdc, x, y);
  950. data[i++] = (byte) ((cref >> 0)& 0xff);
  951. data[i++] = (byte) ((cref >> 8) & 0xff);
  952. data[i++] = (byte) ((cref >> 16) & 0xff);
  953. }
  954. }
  955. ReleaseDC ((HWND) getHandle (), hdc);
  956. #endif
  957. if (!mxTgaWrite (filename, image))
  958. mxMessageBox (this, "Error writing screenshot.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
  959. delete image;
  960. }
  961. }