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.

408 lines
13 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "weapon_ifmbasecamera.h"
  9. #ifdef CLIENT_DLL
  10. #include "view_shared.h"
  11. #include "iviewrender.h"
  12. #include "vgui_controls/controls.h"
  13. #include "vgui/isurface.h"
  14. // NOTE: This has to be the last file included!
  15. #include "tier0/memdbgon.h"
  16. bool ToolFramework_SetupEngineView( Vector &origin, QAngle &angles, float &fov );
  17. #endif
  18. #define INSET_VIEW_FACTOR 0.3f
  19. //-----------------------------------------------------------------------------
  20. // CWeaponIFMBaseCamera tables.
  21. //-----------------------------------------------------------------------------
  22. IMPLEMENT_NETWORKCLASS_ALIASED( WeaponIFMBaseCamera, DT_WeaponIFMBaseCamera )
  23. LINK_ENTITY_TO_CLASS( weapon_ifm_base_camera, CWeaponIFMBaseCamera );
  24. BEGIN_NETWORK_TABLE( CWeaponIFMBaseCamera, DT_WeaponIFMBaseCamera )
  25. #if !defined( CLIENT_DLL )
  26. SendPropFloat( SENDINFO( m_flRenderAspectRatio ), 0, SPROP_NOSCALE ),
  27. SendPropFloat( SENDINFO( m_flRenderFOV ), 0, SPROP_NOSCALE ),
  28. SendPropFloat( SENDINFO( m_flRenderArmLength ), 0, SPROP_NOSCALE ),
  29. SendPropVector( SENDINFO( m_vecRenderPosition ), 0, SPROP_NOSCALE ),
  30. SendPropQAngles( SENDINFO( m_angRenderAngles ), 0, SPROP_NOSCALE ),
  31. #else
  32. RecvPropFloat( RECVINFO( m_flRenderAspectRatio ) ),
  33. RecvPropFloat( RECVINFO( m_flRenderFOV ) ),
  34. RecvPropFloat( RECVINFO( m_flRenderArmLength ) ),
  35. RecvPropVector( RECVINFO( m_vecRenderPosition ) ),
  36. RecvPropQAngles( RECVINFO( m_angRenderAngles ) ),
  37. #endif
  38. END_NETWORK_TABLE()
  39. #ifdef CLIENT_DLL
  40. BEGIN_PREDICTION_DATA( CWeaponIFMBaseCamera )
  41. DEFINE_PRED_FIELD( m_flFOV, FIELD_FLOAT, 0 ),
  42. DEFINE_PRED_FIELD( m_flArmLength, FIELD_FLOAT, 0 ),
  43. DEFINE_PRED_FIELD( m_vecRelativePosition, FIELD_VECTOR, 0 ),
  44. DEFINE_PRED_FIELD( m_angRelativeAngles, FIELD_VECTOR, 0 ),
  45. DEFINE_PRED_FIELD( m_bFullScreen, FIELD_BOOLEAN, 0 ),
  46. END_PREDICTION_DATA()
  47. #endif
  48. #ifdef GAME_DLL
  49. BEGIN_DATADESC( CWeaponIFMBaseCamera )
  50. DEFINE_FIELD( m_flRenderAspectRatio, FIELD_FLOAT ),
  51. DEFINE_FIELD( m_flRenderFOV, FIELD_FLOAT ),
  52. DEFINE_FIELD( m_flRenderArmLength, FIELD_FLOAT ),
  53. DEFINE_FIELD( m_vecRenderPosition, FIELD_VECTOR ),
  54. DEFINE_FIELD( m_angRenderAngles, FIELD_VECTOR ),
  55. END_DATADESC()
  56. #endif
  57. //-----------------------------------------------------------------------------
  58. // CWeaponIFMBaseCamera implementation.
  59. //-----------------------------------------------------------------------------
  60. CWeaponIFMBaseCamera::CWeaponIFMBaseCamera()
  61. {
  62. #ifdef CLIENT_DLL
  63. m_flFOV = 75.0f;
  64. m_flArmLength = 4;
  65. m_vecRelativePosition.Init();
  66. m_angRelativeAngles.Init();
  67. m_bFullScreen = false;
  68. m_nScreenWidth = 0;
  69. m_nScreenHeight = 0;
  70. #endif
  71. }
  72. //-----------------------------------------------------------------------------
  73. //
  74. // Specific methods on the server
  75. //
  76. //-----------------------------------------------------------------------------
  77. #ifdef GAME_DLL
  78. void CWeaponIFMBaseCamera::SetRenderInfo( float flAspectRatio, float flFOV, float flArmLength, const Vector &vecPosition, const QAngle &angles )
  79. {
  80. m_flRenderAspectRatio = flAspectRatio;
  81. m_flRenderFOV = flFOV;
  82. m_flRenderArmLength = flArmLength;
  83. m_vecRenderPosition = vecPosition;
  84. m_angRenderAngles = angles;
  85. }
  86. CON_COMMAND( ifm_basecamera_camerastate, "Set camera state" )
  87. {
  88. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  89. if ( !pPlayer )
  90. return;
  91. if ( args.ArgC() != 10 )
  92. return;
  93. Vector vecPosition;
  94. QAngle angAngles;
  95. float flAspectRatio = atof( args[1] );
  96. float flFOV = atof( args[2] );
  97. float flArmLength = atof( args[3] );
  98. vecPosition.x = atof( args[4] );
  99. vecPosition.y = atof( args[5] );
  100. vecPosition.z = atof( args[6] );
  101. angAngles.x = atof( args[7] );
  102. angAngles.y = atof( args[8] );
  103. angAngles.z = atof( args[9] );
  104. int nCount = pPlayer->WeaponCount();
  105. for ( int i = 0; i < nCount; ++i )
  106. {
  107. CWeaponIFMBaseCamera *pCamera = dynamic_cast<CWeaponIFMBaseCamera*>( pPlayer->GetWeapon( i ) );
  108. if ( !pCamera )
  109. continue;
  110. pCamera->SetRenderInfo( flAspectRatio, flFOV, flArmLength, vecPosition, angAngles );
  111. }
  112. }
  113. #endif // GAME_DLL
  114. //-----------------------------------------------------------------------------
  115. //
  116. // Specific methods on the client
  117. //
  118. //-----------------------------------------------------------------------------
  119. #ifdef CLIENT_DLL
  120. //-----------------------------------------------------------------------------
  121. // Sets up the material to draw with
  122. //-----------------------------------------------------------------------------
  123. void CWeaponIFMBaseCamera::OnDataChanged( DataUpdateType_t updateType )
  124. {
  125. BaseClass::OnDataChanged( updateType );
  126. if (updateType == DATA_UPDATE_CREATED)
  127. {
  128. m_FrustumMaterial.Init( "effects/steadycamfrustum", TEXTURE_GROUP_OTHER );
  129. m_FrustumWireframeMaterial.Init( "debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER );
  130. }
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Transmits render information
  134. //-----------------------------------------------------------------------------
  135. void CWeaponIFMBaseCamera::TransmitRenderInfo()
  136. {
  137. float flAspectRatio = (m_nScreenHeight != 0) ? (float)m_nScreenWidth / (float)m_nScreenHeight : 1.0f;
  138. float flFOV = m_flFOV;
  139. Vector position;
  140. QAngle angles;
  141. ComputeAbsCameraTransform( position, angles );
  142. // give the toolsystem a chance to override the view
  143. ToolFramework_SetupEngineView( position, angles, flFOV );
  144. char pBuf[256];
  145. Q_snprintf( pBuf, sizeof(pBuf), "ifm_basecamera_camerastate %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f",
  146. flAspectRatio, flFOV, m_flArmLength, position.x, position.y, position.z,
  147. angles.x, angles.y, angles.z );
  148. engine->ClientCmd( pBuf );
  149. }
  150. //-----------------------------------------------------------------------------
  151. // Purpose: In 3rd person, draws the cone of the steadycam
  152. //-----------------------------------------------------------------------------
  153. #define FRUSTUM_SIZE 1000
  154. int CWeaponIFMBaseCamera::DrawModel( int flags, const RenderableInstance_t &instance )
  155. {
  156. int nRetVal = BaseClass::DrawModel( flags, instance );
  157. CBasePlayer *pPlayer = GetPlayerOwner();
  158. if ( pPlayer && !pPlayer->IsLocalPlayer( this ) )
  159. {
  160. // Compute endpoints
  161. float flMaxD = 1.0f / tan( M_PI * m_flFOV / 360.0f );
  162. float ex = flMaxD * FRUSTUM_SIZE;
  163. float ey = flMaxD * FRUSTUM_SIZE / m_flRenderAspectRatio;
  164. // Compute basis
  165. Vector vecForward, vecUp, vecRight;
  166. AngleVectors( m_angRenderAngles, &vecForward, &vecRight, &vecUp );
  167. Vector vecCenter;
  168. VectorMA( m_vecRenderPosition, FRUSTUM_SIZE, vecForward, vecCenter );
  169. Vector vecEndPoint[4];
  170. VectorMA( vecCenter, ex, vecRight, vecEndPoint[0] );
  171. VectorMA( vecEndPoint[0], ey, vecUp, vecEndPoint[0] );
  172. VectorMA( vecEndPoint[0], -2.0f * ex, vecRight, vecEndPoint[1] );
  173. VectorMA( vecEndPoint[1], -2.0f * ey, vecUp, vecEndPoint[2] );
  174. VectorMA( vecEndPoint[2], 2.0f * ex, vecRight, vecEndPoint[3] );
  175. CMatRenderContextPtr pRenderContext( materials );
  176. pRenderContext->Bind( m_FrustumMaterial );
  177. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  178. CMeshBuilder meshBuilder;
  179. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 4 );
  180. for ( int i = 0; i < 4; ++i )
  181. {
  182. meshBuilder.Position3fv( m_vecRenderPosition.Get().Base() );
  183. meshBuilder.Color4ub( 128, 0, 0, 255 );
  184. meshBuilder.AdvanceVertex();
  185. meshBuilder.Position3fv( vecEndPoint[i].Base() );
  186. meshBuilder.Color4ub( 128, 0, 0, 255 );
  187. meshBuilder.AdvanceVertex();
  188. meshBuilder.Position3fv( vecEndPoint[(i+1)%4].Base() );
  189. meshBuilder.Color4ub( 128, 0, 0, 255 );
  190. meshBuilder.AdvanceVertex();
  191. }
  192. meshBuilder.End();
  193. pMesh->Draw();
  194. pRenderContext->Bind( m_FrustumWireframeMaterial );
  195. pMesh = pRenderContext->GetDynamicMesh( true );
  196. meshBuilder.Begin( pMesh, MATERIAL_LINES, 8 );
  197. for ( int i = 0; i < 4; ++i )
  198. {
  199. meshBuilder.Position3fv( m_vecRenderPosition.Get().Base() );
  200. meshBuilder.Color4ub( 255, 255, 255, 255 );
  201. meshBuilder.AdvanceVertex();
  202. meshBuilder.Position3fv( vecEndPoint[i].Base() );
  203. meshBuilder.Color4ub( 255, 255, 255, 255 );
  204. meshBuilder.AdvanceVertex();
  205. meshBuilder.Position3fv( vecEndPoint[i].Base() );
  206. meshBuilder.Color4ub( 255, 255, 255, 255 );
  207. meshBuilder.AdvanceVertex();
  208. meshBuilder.Position3fv( vecEndPoint[(i+1)%4].Base() );
  209. meshBuilder.Color4ub( 255, 255, 255, 255 );
  210. meshBuilder.AdvanceVertex();
  211. }
  212. meshBuilder.End();
  213. pMesh->Draw();
  214. }
  215. return nRetVal;
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Gets the size of the overlay to draw
  219. //-----------------------------------------------------------------------------
  220. void CWeaponIFMBaseCamera::GetViewportSize( int &w, int &h )
  221. {
  222. if ( !m_bFullScreen )
  223. {
  224. w = m_nScreenWidth * INSET_VIEW_FACTOR;
  225. h = m_nScreenHeight * INSET_VIEW_FACTOR;
  226. }
  227. else
  228. {
  229. w = m_nScreenWidth;
  230. h = m_nScreenHeight;
  231. }
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Gets the abs orientation of the camera
  235. //-----------------------------------------------------------------------------
  236. void CWeaponIFMBaseCamera::ComputeAbsCameraTransform( Vector &vecAbsOrigin, QAngle &angAbsRotation )
  237. {
  238. CBasePlayer *pPlayer = GetPlayerOwner();
  239. if ( !pPlayer )
  240. {
  241. vecAbsOrigin.Init();
  242. angAbsRotation.Init();
  243. return;
  244. }
  245. float flFOV = m_flFOV;
  246. float flZNear = view->GetZNear();
  247. float flZFar = view->GetZFar();
  248. Vector viewOrigin;
  249. QAngle viewAngles;
  250. pPlayer->CalcView( viewOrigin, viewAngles, flZNear, flZFar, flFOV );
  251. // Offset the view along the forward direction vector by the arm length
  252. Vector vecForward;
  253. AngleVectors( viewAngles, &vecForward );
  254. VectorMA( viewOrigin, m_flArmLength, vecForward, viewOrigin );
  255. // Use player roll
  256. QAngle angles = m_angRelativeAngles;
  257. angles.z = viewAngles.z;
  258. // Compute the actual orientation of the view
  259. matrix3x4_t cameraToWorld, overlayToCamera, overlayToWorld;
  260. AngleMatrix( vec3_angle, viewOrigin, cameraToWorld );
  261. AngleMatrix( angles, m_vecRelativePosition, overlayToCamera );
  262. ConcatTransforms( cameraToWorld, overlayToCamera, overlayToWorld );
  263. MatrixAngles( overlayToWorld, angAbsRotation, vecAbsOrigin );
  264. // give the toolsystem a chance to override the view
  265. ToolFramework_SetupEngineView( vecAbsOrigin, angAbsRotation, flFOV );
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Gets the bounds of the overlay to draw
  269. //-----------------------------------------------------------------------------
  270. void CWeaponIFMBaseCamera::GetOverlayBounds( int &x, int &y, int &w, int &h )
  271. {
  272. const CViewSetup *pViewSetup = view->GetViewSetup();
  273. if ( !m_bFullScreen )
  274. {
  275. w = pViewSetup->width * INSET_VIEW_FACTOR;
  276. h = pViewSetup->height * INSET_VIEW_FACTOR;
  277. x = pViewSetup->x + ( pViewSetup->width - w ) / 2;
  278. y = pViewSetup->height - h;
  279. }
  280. else
  281. {
  282. w = pViewSetup->width;
  283. h = pViewSetup->height;
  284. x = pViewSetup->x;
  285. y = pViewSetup->y;
  286. }
  287. }
  288. //-----------------------------------------------------------------------------
  289. // When drawing the model, if drawing the viewmodel, draw an overlay of what's being rendered
  290. //-----------------------------------------------------------------------------
  291. void CWeaponIFMBaseCamera::ViewModelDrawn( int nFlags, CBaseViewModel *pBaseViewModel )
  292. {
  293. // NOTE: This is not recursively called because we do not draw viewmodels in the overlay
  294. CViewSetup overlayView = *view->GetViewSetup();
  295. m_nScreenWidth = overlayView.width;
  296. m_nScreenHeight = overlayView.height;
  297. GetOverlayBounds( overlayView.x, overlayView.y, overlayView.width, overlayView.height );
  298. overlayView.m_bRenderToSubrectOfLargerScreen = true;
  299. overlayView.fov = m_flFOV;
  300. // Compute the location of the camera
  301. ComputeAbsCameraTransform( overlayView.origin, overlayView.angles );
  302. // give the toolsystem a chance to override the view
  303. ToolFramework_SetupEngineView( overlayView.origin, overlayView.angles, overlayView.fov );
  304. view->QueueOverlayRenderView( overlayView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, RENDERVIEW_UNSPECIFIED );
  305. }
  306. //-----------------------------------------------------------------------------
  307. // Purpose: Draw the weapon's crosshair
  308. //-----------------------------------------------------------------------------
  309. void CWeaponIFMBaseCamera::DrawCrosshair( void )
  310. {
  311. BaseClass::DrawCrosshair();
  312. int x, y, w, h;
  313. GetOverlayBounds( x, y, w, h );
  314. // Draw the targeting zone around the crosshair
  315. int r, g, b, a;
  316. GetHud().m_clrYellowish.GetColor( r, g, b, a );
  317. Color light( r, g, b, 160 );
  318. int nBorderSize = 4;
  319. vgui::surface()->DrawSetColor( light );
  320. vgui::surface()->DrawFilledRect( x-nBorderSize, y-nBorderSize, x+w+nBorderSize, y );
  321. vgui::surface()->DrawFilledRect( x-nBorderSize, y+h, x+w+nBorderSize, y+h+nBorderSize );
  322. vgui::surface()->DrawFilledRect( x-nBorderSize, y, x, y+h );
  323. vgui::surface()->DrawFilledRect( x+w, y, x+w+nBorderSize, y+h );
  324. }
  325. #endif // CLIENT_DLL