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

495 lines
15 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "dme_controls/mdlpanel.h"
  7. #include "materialsystem/imaterialsystem.h"
  8. #include <materialsystem/IMaterialSystemHardwareConfig.h>
  9. #include "materialsystem/imesh.h"
  10. #include "vgui/ivgui.h"
  11. #include "tier1/keyvalues.h"
  12. #include "movieobjects/dmemdl.h"
  13. #include "movieobjects/dmetransform.h"
  14. #include "movieobjects/dmedag.h"
  15. #include "movieobjects/dmemdlmakefile.h"
  16. #include "vgui_controls/frame.h"
  17. #include "convar.h"
  18. #include "tier0/dbg.h"
  19. #include "istudiorender.h"
  20. #include "matsys_controls/matsyscontrols.h"
  21. #include "vcollide.h"
  22. #include "vcollide_parse.h"
  23. #include "bone_setup.h"
  24. #include "vphysics_interface.h"
  25. #include "dme_controls/dmecontrols.h"
  26. #include "dme_controls/dmepanel.h"
  27. // memdbgon must be the last include file in a .cpp file!!!
  28. #include "tier0/memdbgon.h"
  29. using namespace vgui;
  30. IMPLEMENT_DMEPANEL_FACTORY( CMDLPanel, DmeMDLMakefile, "DmeMakeFileOutputPreview", "MDL MakeFile Output Preview", false );
  31. //-----------------------------------------------------------------------------
  32. // Constructor, destructor
  33. //-----------------------------------------------------------------------------
  34. CMDLPanel::CMDLPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
  35. {
  36. CDmeMDL *pMDL = CreateElement< CDmeMDL >( "mdl", DMFILEID_INVALID );
  37. m_hMDL = pMDL;
  38. m_hMDL->DrawInEngine( true );
  39. UseEngineCoordinateSystem( true );
  40. m_pDag = CreateElement< CDmeDag >( "dag", DMFILEID_INVALID );
  41. m_pDag->SetShape( pMDL );
  42. SetVisible( true );
  43. // Used to poll input
  44. vgui::ivgui()->AddTickSignal( GetVPanel() );
  45. // Deal with the default cubemap
  46. ITexture *pCubemapTexture = vgui::MaterialSystem()->FindTexture( "editor/cubemap", NULL, true );
  47. m_DefaultEnvCubemap.Init( pCubemapTexture );
  48. pCubemapTexture = vgui::MaterialSystem()->FindTexture( "editor/cubemap.hdr", NULL, true );
  49. m_DefaultHDREnvCubemap.Init( pCubemapTexture );
  50. KeyValues *pMaterialKeys = new KeyValues( "Wireframe", "$model", "1" );
  51. pMaterialKeys->SetString( "$vertexcolor", "1" );
  52. m_Wireframe.Init( "mdlpanelwireframe", pMaterialKeys );
  53. m_bDrawCollisionModel = false;
  54. m_bWireFrame = false;
  55. m_bGroundGrid = false;
  56. m_bLockView = false;
  57. m_bIsExternalMDL = false;
  58. }
  59. CMDLPanel::~CMDLPanel()
  60. {
  61. CDisableUndoScopeGuard guard;
  62. m_pDag->SetShape( NULL );
  63. m_DefaultEnvCubemap.Shutdown( );
  64. m_DefaultHDREnvCubemap.Shutdown();
  65. if ( !m_bIsExternalMDL )
  66. {
  67. DestroyElement( m_hMDL );
  68. m_hMDL = NULL;
  69. }
  70. g_pDataModel->DestroyElement( m_pDag->GetHandle() );
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Scheme settings
  74. //-----------------------------------------------------------------------------
  75. void CMDLPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  76. {
  77. BaseClass::ApplySchemeSettings( pScheme );
  78. SetBorder( pScheme->GetBorder( "MenuBorder") );
  79. }
  80. //-----------------------------------------------------------------------------
  81. // DMEPanel..
  82. //-----------------------------------------------------------------------------
  83. void CMDLPanel::SetDmeElement( CDmeMDLMakefile *pMDLMakefile )
  84. {
  85. CDisableUndoScopeGuard sg;
  86. if ( !m_bIsExternalMDL )
  87. {
  88. DestroyElement( m_hMDL );
  89. m_hMDL = NULL;
  90. }
  91. CDmeMDL *pMDL = NULL;
  92. if ( pMDLMakefile != NULL )
  93. {
  94. pMDL = CastElement< CDmeMDL >( pMDLMakefile->GetOutputElement( true ) );
  95. m_bIsExternalMDL = ( pMDL != NULL );
  96. }
  97. if ( !pMDL )
  98. {
  99. pMDL = CreateElement< CDmeMDL >( "mdl", DMFILEID_INVALID );
  100. }
  101. m_hMDL = pMDL;
  102. m_hMDL->DrawInEngine( true );
  103. m_pDag->SetShape( pMDL );
  104. }
  105. //-----------------------------------------------------------------------------
  106. // Rendering options
  107. //-----------------------------------------------------------------------------
  108. void CMDLPanel::SetCollsionModel( bool bVisible )
  109. {
  110. m_bDrawCollisionModel = bVisible;
  111. }
  112. void CMDLPanel::SetGroundGrid( bool bVisible )
  113. {
  114. m_bGroundGrid = bVisible;
  115. }
  116. void CMDLPanel::SetWireFrame( bool bVisible )
  117. {
  118. m_bWireFrame = bVisible;
  119. }
  120. void CMDLPanel::SetLockView( bool bLocked )
  121. {
  122. m_bLockView = bLocked;
  123. }
  124. void CMDLPanel::SetLookAtCamera( bool bLookAtCamera )
  125. {
  126. m_bLookAtCamera = bLookAtCamera;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Stores the clip
  130. //-----------------------------------------------------------------------------
  131. void CMDLPanel::SetMDL( MDLHandle_t handle )
  132. {
  133. CDisableUndoScopeGuard sg;
  134. m_hMDL->SetMDL( handle );
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Sets the camera to look at the model
  138. //-----------------------------------------------------------------------------
  139. void CMDLPanel::LookAtMDL( )
  140. {
  141. if ( m_bLockView )
  142. return;
  143. float flRadius;
  144. Vector vecCenter;
  145. m_hMDL->GetBoundingSphere( vecCenter, flRadius );
  146. LookAt( vecCenter, flRadius );
  147. }
  148. //-----------------------------------------------------------------------------
  149. // FIXME: This should be moved into studiorender
  150. //-----------------------------------------------------------------------------
  151. static ConVar r_showenvcubemap( "r_showenvcubemap", "0", FCVAR_CHEAT );
  152. static ConVar r_eyegloss ( "r_eyegloss", "1", FCVAR_ARCHIVE ); // wet eyes
  153. static ConVar r_eyemove ( "r_eyemove", "1", FCVAR_ARCHIVE ); // look around
  154. static ConVar r_eyeshift_x ( "r_eyeshift_x", "0", FCVAR_ARCHIVE ); // eye X position
  155. static ConVar r_eyeshift_y ( "r_eyeshift_y", "0", FCVAR_ARCHIVE ); // eye Y position
  156. static ConVar r_eyeshift_z ( "r_eyeshift_z", "0", FCVAR_ARCHIVE ); // eye Z position
  157. static ConVar r_eyesize ( "r_eyesize", "0", FCVAR_ARCHIVE ); // adjustment to iris textures
  158. static ConVar mat_softwareskin( "mat_softwareskin", "0" );
  159. static ConVar r_nohw ( "r_nohw", "0", FCVAR_CHEAT );
  160. static ConVar r_nosw ( "r_nosw", "0", FCVAR_CHEAT );
  161. static ConVar r_teeth ( "r_teeth", "1" );
  162. static ConVar r_drawentities ( "r_drawentities", "1", FCVAR_CHEAT );
  163. static ConVar r_flex ( "r_flex", "1" );
  164. static ConVar r_eyes ( "r_eyes", "1" );
  165. static ConVar r_skin ( "r_skin","0" );
  166. static ConVar r_maxmodeldecal ( "r_maxmodeldecal", "50" );
  167. static ConVar r_modelwireframedecal ( "r_modelwireframedecal", "0", FCVAR_CHEAT );
  168. static ConVar mat_normals ( "mat_normals", "0", FCVAR_CHEAT );
  169. static ConVar r_eyeglintlodpixels ( "r_eyeglintlodpixels", "0", FCVAR_CHEAT );
  170. static ConVar r_rootlod ( "r_rootlod", "0", FCVAR_CHEAT );
  171. static StudioRenderConfig_t s_StudioRenderConfig;
  172. void CMDLPanel::UpdateStudioRenderConfig( void )
  173. {
  174. memset( &s_StudioRenderConfig, 0, sizeof(s_StudioRenderConfig) );
  175. s_StudioRenderConfig.bEyeMove = !!r_eyemove.GetInt();
  176. s_StudioRenderConfig.fEyeShiftX = r_eyeshift_x.GetFloat();
  177. s_StudioRenderConfig.fEyeShiftY = r_eyeshift_y.GetFloat();
  178. s_StudioRenderConfig.fEyeShiftZ = r_eyeshift_z.GetFloat();
  179. s_StudioRenderConfig.fEyeSize = r_eyesize.GetFloat();
  180. if( mat_softwareskin.GetInt() || m_bWireFrame )
  181. {
  182. s_StudioRenderConfig.bSoftwareSkin = true;
  183. }
  184. else
  185. {
  186. s_StudioRenderConfig.bSoftwareSkin = false;
  187. }
  188. s_StudioRenderConfig.bNoHardware = !!r_nohw.GetInt();
  189. s_StudioRenderConfig.bNoSoftware = !!r_nosw.GetInt();
  190. s_StudioRenderConfig.bTeeth = !!r_teeth.GetInt();
  191. s_StudioRenderConfig.drawEntities = r_drawentities.GetInt();
  192. s_StudioRenderConfig.bFlex = !!r_flex.GetInt();
  193. s_StudioRenderConfig.bEyes = !!r_eyes.GetInt();
  194. s_StudioRenderConfig.bWireframe = m_bWireFrame;
  195. s_StudioRenderConfig.bDrawNormals = mat_normals.GetBool();
  196. s_StudioRenderConfig.skin = r_skin.GetInt();
  197. s_StudioRenderConfig.maxDecalsPerModel = r_maxmodeldecal.GetInt();
  198. s_StudioRenderConfig.bWireframeDecals = r_modelwireframedecal.GetInt() != 0;
  199. s_StudioRenderConfig.fullbright = false;
  200. s_StudioRenderConfig.bSoftwareLighting = false;
  201. s_StudioRenderConfig.bShowEnvCubemapOnly = r_showenvcubemap.GetBool();
  202. s_StudioRenderConfig.fEyeGlintPixelWidthLODThreshold = r_eyeglintlodpixels.GetFloat();
  203. StudioRender()->UpdateConfig( s_StudioRenderConfig );
  204. }
  205. void CMDLPanel::DrawCollisionModel()
  206. {
  207. vcollide_t *pCollide = MDLCache()->GetVCollide( m_hMDL->GetMDL() );
  208. if ( !pCollide || pCollide->solidCount <= 0 )
  209. return;
  210. static color32 color = {255,0,0,0};
  211. IVPhysicsKeyParser *pParser = g_pPhysicsCollision->VPhysicsKeyParserCreate( pCollide );
  212. CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_hMDL->GetMDL() ), g_pMDLCache );
  213. matrix3x4_t pBoneToWorld[MAXSTUDIOBONES];
  214. matrix3x4_t shapeToWorld;
  215. m_pDag->GetTransform()->GetTransform( shapeToWorld );
  216. m_hMDL->SetUpBones( shapeToWorld, MAXSTUDIOBONES, pBoneToWorld );
  217. // PERFORMANCE: Just parse the script each frame. It's fast enough for tools. If you need
  218. // this to go faster then cache off the bone index mapping in an array like HLMV does
  219. while ( !pParser->Finished() )
  220. {
  221. const char *pBlock = pParser->GetCurrentBlockName();
  222. if ( !stricmp( pBlock, "solid" ) )
  223. {
  224. solid_t solid;
  225. pParser->ParseSolid( &solid, NULL );
  226. int boneIndex = Studio_BoneIndexByName( &studioHdr, solid.name );
  227. Vector *outVerts;
  228. int vertCount = g_pPhysicsCollision->CreateDebugMesh( pCollide->solids[solid.index], &outVerts );
  229. if ( vertCount )
  230. {
  231. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  232. pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
  233. // NOTE: assumes these have been set up already by the model render code
  234. // So this is a little bit of a back door to a cache of the bones
  235. // this code wouldn't work unless you draw the model this frame before calling
  236. // this routine. CMDLPanel always does this, but it's worth noting.
  237. // A better solution would be to move the ragdoll visulization into the CDmeMdl
  238. // and either draw it there or make it queryable and query/draw here.
  239. matrix3x4_t xform;
  240. SetIdentityMatrix( xform );
  241. if ( boneIndex >= 0 )
  242. {
  243. MatrixCopy( pBoneToWorld[ boneIndex ], xform );
  244. }
  245. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_Wireframe );
  246. CMeshBuilder meshBuilder;
  247. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, vertCount/3 );
  248. for ( int j = 0; j < vertCount; j++ )
  249. {
  250. Vector out;
  251. VectorTransform( outVerts[j].Base(), xform, out.Base() );
  252. meshBuilder.Position3fv( out.Base() );
  253. meshBuilder.Color4ub( color.r, color.g, color.b, color.a );
  254. meshBuilder.TexCoord2f( 0, 0, 0 );
  255. meshBuilder.AdvanceVertex();
  256. }
  257. meshBuilder.End();
  258. pMesh->Draw();
  259. }
  260. g_pPhysicsCollision->DestroyDebugMesh( vertCount, outVerts );
  261. }
  262. else
  263. {
  264. pParser->SkipBlock();
  265. }
  266. }
  267. g_pPhysicsCollision->VPhysicsKeyParserDestroy( pParser );
  268. }
  269. //-----------------------------------------------------------------------------
  270. // paint it!
  271. //-----------------------------------------------------------------------------
  272. void CMDLPanel::OnPaint3D()
  273. {
  274. if ( !m_hMDL.Get() )
  275. return;
  276. // FIXME: Move this call into DrawModel in StudioRender
  277. StudioRenderConfig_t oldStudioRenderConfig;
  278. StudioRender()->GetCurrentConfig( oldStudioRenderConfig );
  279. UpdateStudioRenderConfig();
  280. CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() );
  281. ITexture *pLocalCube = pRenderContext->GetLocalCubemap();
  282. if ( vgui::MaterialSystemHardwareConfig()->GetHDRType() == HDR_TYPE_NONE )
  283. {
  284. ITexture *pMyCube = HasLightProbe() ? GetLightProbeCubemap( false ) : m_DefaultEnvCubemap;
  285. pRenderContext->BindLocalCubemap( pMyCube );
  286. }
  287. else
  288. {
  289. ITexture *pMyCube = HasLightProbe() ? GetLightProbeCubemap( true ) : m_DefaultHDREnvCubemap;
  290. pRenderContext->BindLocalCubemap( pMyCube );
  291. }
  292. if ( m_bGroundGrid )
  293. {
  294. DrawGrid();
  295. }
  296. if ( m_bLookAtCamera )
  297. {
  298. CDisableUndoScopeGuard sg;
  299. matrix3x4_t worldToCamera;
  300. ComputeCameraTransform( &worldToCamera );
  301. Vector vecPosition;
  302. MatrixGetColumn( worldToCamera, 3, vecPosition );
  303. m_hMDL->m_bWorldSpaceViewTarget = true;
  304. m_hMDL->m_vecViewTarget = vecPosition;
  305. }
  306. // Draw the MDL
  307. m_pDag->Draw();
  308. if ( m_bDrawCollisionModel )
  309. {
  310. DrawCollisionModel();
  311. }
  312. pRenderContext->Flush();
  313. StudioRender()->UpdateConfig( oldStudioRenderConfig );
  314. pRenderContext->BindLocalCubemap( pLocalCube );
  315. }
  316. //-----------------------------------------------------------------------------
  317. // Sets the current sequence
  318. //-----------------------------------------------------------------------------
  319. void CMDLPanel::SetSequence( int nSequence )
  320. {
  321. CDisableUndoScopeGuard guard;
  322. m_hMDL->m_nSequence = nSequence;
  323. }
  324. void CMDLPanel::SetSkin( int nSkin )
  325. {
  326. CDisableUndoScopeGuard guard;
  327. m_hMDL->m_nSkin = nSkin;
  328. }
  329. //-----------------------------------------------------------------------------
  330. // Purpose: Keeps a global clock to autoplay sequences to run from
  331. // Also deals with speedScale changes
  332. //-----------------------------------------------------------------------------
  333. float GetAutoPlayTime( void )
  334. {
  335. static int g_prevTicks;
  336. static float g_time;
  337. int ticks = Plat_MSTime();
  338. // limit delta so that float time doesn't overflow
  339. if (g_prevTicks == 0)
  340. {
  341. g_prevTicks = ticks;
  342. }
  343. g_time += ( ticks - g_prevTicks ) / 1000.0f;
  344. g_prevTicks = ticks;
  345. return g_time;
  346. }
  347. //-----------------------------------------------------------------------------
  348. // called when we're ticked...
  349. //-----------------------------------------------------------------------------
  350. void CMDLPanel::OnTick()
  351. {
  352. BaseClass::OnTick();
  353. if ( m_hMDL->GetMDL() != MDLHANDLE_INVALID )
  354. {
  355. CDisableUndoScopeGuard guard;
  356. m_hMDL->m_flTime = GetAutoPlayTime();
  357. }
  358. }
  359. //-----------------------------------------------------------------------------
  360. // input
  361. //-----------------------------------------------------------------------------
  362. void CMDLPanel::OnMouseDoublePressed( vgui::MouseCode code )
  363. {
  364. float flRadius;
  365. Vector vecCenter;
  366. m_hMDL->GetBoundingSphere( vecCenter, flRadius );
  367. LookAt( vecCenter, flRadius );
  368. BaseClass::OnMouseDoublePressed( code );
  369. }
  370. //-----------------------------------------------------------------------------
  371. // Draws the grid under the MDL
  372. //-----------------------------------------------------------------------------
  373. void CMDLPanel::DrawGrid()
  374. {
  375. matrix3x4_t transform;
  376. SetIdentityMatrix( transform );
  377. CMatRenderContextPtr pRenderContext( MaterialSystem() );
  378. pRenderContext->MatrixMode( MATERIAL_MODEL );
  379. pRenderContext->LoadMatrix( transform );
  380. pRenderContext->Bind( m_Wireframe );
  381. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  382. int nGridDim = 10;
  383. CMeshBuilder meshBuilder;
  384. meshBuilder.Begin( pMesh, MATERIAL_LINES, 2 * nGridDim + 2 );
  385. float bounds = 100.0f;
  386. float delta = 2 * bounds / nGridDim;
  387. for ( int i = 0; i < nGridDim + 1; ++i )
  388. {
  389. float xy = -bounds + delta * i;
  390. meshBuilder.Position3f( xy, -bounds, 0 );
  391. meshBuilder.Color4ub( 255, 255, 255, 255 );
  392. meshBuilder.AdvanceVertex();
  393. meshBuilder.Position3f( xy, bounds, 0 );
  394. meshBuilder.Color4ub( 255, 255, 255, 255 );
  395. meshBuilder.AdvanceVertex();
  396. meshBuilder.Position3f( -bounds, xy, 0 );
  397. meshBuilder.Color4ub( 255, 255, 255, 255 );
  398. meshBuilder.AdvanceVertex();
  399. meshBuilder.Position3f( bounds, xy, 0 );
  400. meshBuilder.Color4ub( 255, 255, 255, 255 );
  401. meshBuilder.AdvanceVertex();
  402. }
  403. meshBuilder.End();
  404. pMesh->Draw();
  405. }