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.

404 lines
13 KiB

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