diff --git a/cl_dll/StudioModelRenderer.cpp b/cl_dll/StudioModelRenderer.cpp index b15930ba..5d01a5fb 100644 --- a/cl_dll/StudioModelRenderer.cpp +++ b/cl_dll/StudioModelRenderer.cpp @@ -1,5 +1,16 @@ // studio_model.cpp // routines for setting up to draw 3DStudio models +#ifdef _WIN32 +#include +#include +#include +#endif + +#ifdef __APPLE__ +#include +#else +#include +#endif #include "hud.h" #include "cl_util.h" @@ -54,6 +65,7 @@ void CStudioModelRenderer::Init( void ) m_pCvarHiModels = IEngineStudio.GetCvar( "cl_himodels" ); m_pCvarDeveloper = IEngineStudio.GetCvar( "developer" ); m_pCvarDrawEntities = IEngineStudio.GetCvar( "r_drawentities" ); + m_pCvarViewmodelFov = gEngfuncs.pfnRegisterVariable( "cl_viewmodel_fov","0", FCVAR_ARCHIVE ); m_pChromeSprite = IEngineStudio.GetChromeSprite(); @@ -2063,6 +2075,32 @@ void CStudioModelRenderer::StudioRenderFinal_Software( void ) IEngineStudio.RestoreRenderer(); } +void CStudioModelRenderer::SetViewmodelFovProjection( void ) +{ + if(m_pCvarViewmodelFov->value < 1 || m_pCvarViewmodelFov->value > 179) + { + m_pCvarViewmodelFov->value = 0.0; + gEngfuncs.Con_Printf("Invalid cl_viewmodel_fov value (minimum 1, maximum 179, 0 to disable). Resetting to 0 (disable).\n"); + gEngfuncs.Con_Printf("Usage: cl_viewmodel_fov [1-179] or 0 to disable and use default_fov's FOV.\n"); + return; + } + + glMatrixMode (GL_PROJECTION); + glLoadIdentity(); + GLfloat w, h; + GLfloat _near = 1.0f; + GLfloat _far = 4096.0f; + float fovY = m_pCvarViewmodelFov->value; + float aspect = (float)ScreenWidth / (float)ScreenHeight; + + h = tan (fovY / 360 * M_PI) * _near * ((float)ScreenHeight / (float)ScreenWidth); + w = h * aspect; + glFrustum (-w, w, -h, h, _near, _far); + // shouldn't be needed, as the API's render funcs called after us probably just set it themselves + // but just to be sure + glMatrixMode (GL_MODELVIEW); +} + /* ==================== StudioRenderFinal_Hardware @@ -2098,6 +2136,11 @@ void CStudioModelRenderer::StudioRenderFinal_Hardware( void ) } IEngineStudio.GL_SetRenderMode( rendermode ); + // Warning: Order is IMPORANT here. I repeat, this has to be HERE. + if (m_pCurrentEntity == gEngfuncs.GetViewModel() && m_pCvarViewmodelFov->value != 0.0f) + { + SetViewmodelFovProjection(); + } IEngineStudio.StudioDrawPoints(); IEngineStudio.GL_StudioDrawShadow(); } @@ -2119,7 +2162,7 @@ StudioRenderFinal ==================== */ -void CStudioModelRenderer::StudioRenderFinal(void) +void CStudioModelRenderer::StudioRenderFinal( void ) { if ( IEngineStudio.IsHardware() ) { diff --git a/cl_dll/StudioModelRenderer.h b/cl_dll/StudioModelRenderer.h index 7e9b3330..895c6848 100644 --- a/cl_dll/StudioModelRenderer.h +++ b/cl_dll/StudioModelRenderer.h @@ -85,7 +85,7 @@ class CStudioModelRenderer virtual void StudioRenderModel ( void ); // Finalize rendering - virtual void StudioRenderFinal (void); + virtual void StudioRenderFinal ( void ); // GL&D3D vs. Software renderer finishing functions virtual void StudioRenderFinal_Software ( void ); @@ -101,6 +101,9 @@ class CStudioModelRenderer // Process movement of player virtual void StudioProcessGait ( entity_state_t *pplayer ); + // Calculate the viewmodel fov and set the OpenGL projection matrix + virtual void SetViewmodelFovProjection ( void ); + public: // Client clock @@ -124,7 +127,8 @@ class CStudioModelRenderer cvar_t *m_pCvarDeveloper; // Draw entities bone hit boxes, etc? cvar_t *m_pCvarDrawEntities; - + // Change viewmodel FOV + cvar_t *m_pCvarViewmodelFov; // The entity which we are currently rendering. cl_entity_t *m_pCurrentEntity; diff --git a/cl_dll/view.cpp b/cl_dll/view.cpp index 90af4f27..ace2f99f 100644 --- a/cl_dll/view.cpp +++ b/cl_dll/view.cpp @@ -90,6 +90,9 @@ cvar_t *cl_bob; cvar_t *cl_bobup; cvar_t *cl_waterdist; cvar_t *cl_chasedist; +cvar_t *cl_viewmodel_ofs_right; +cvar_t *cl_viewmodel_ofs_forward; +cvar_t *cl_viewmodel_ofs_up; // These cvars are not registered (so users can't cheat), so set the ->value field directly // Register these cvars in V_Init() if needed for easy tweaking @@ -504,6 +507,10 @@ void V_CalcNormalRefdef ( struct ref_params_s *pparams ) vec3_t camAngles, camForward, camRight, camUp; cl_entity_t *pwater; + float forward_offset = cl_viewmodel_ofs_forward->value; + float right_offset = cl_viewmodel_ofs_right->value; + float up_offset = cl_viewmodel_ofs_up->value; + V_DriftPitch ( pparams ); if ( gEngfuncs.IsSpectateOnly() ) @@ -651,6 +658,21 @@ void V_CalcNormalRefdef ( struct ref_params_s *pparams ) view->origin[2] += ( waterOffset ); VectorAdd( view->origin, pparams->viewheight, view->origin ); + // Change the origin from which the camera is looking at the viewmodel + // This does not change the angles of the viewmodel camera + // This does not the player's angles & origin + extern cvar_t* cl_righthand; + if (cl_righthand->value != 0.0) + { + right_offset *= -1; + } + for ( i = 0; i < 3; i++ ) + { + view->origin[i] += forward_offset * pparams->forward[i] + + right_offset * pparams->right[i] + + up_offset * pparams->up[i]; + } + // Let the viewmodel shake at about 10% of the amplitude gEngfuncs.V_ApplyShake( view->origin, view->angles, 0.9 ); @@ -1751,6 +1773,10 @@ void V_Init (void) cl_bobup = gEngfuncs.pfnRegisterVariable( "cl_bobup","0.5", 0 ); cl_waterdist = gEngfuncs.pfnRegisterVariable( "cl_waterdist","4", 0 ); cl_chasedist = gEngfuncs.pfnRegisterVariable( "cl_chasedist","112", 0 ); + + cl_viewmodel_ofs_right = gEngfuncs.pfnRegisterVariable( "cl_viewmodel_ofs_right","0", FCVAR_ARCHIVE ); // x = right + cl_viewmodel_ofs_forward = gEngfuncs.pfnRegisterVariable( "cl_viewmodel_ofs_forward","0", FCVAR_ARCHIVE ); // y = forward + cl_viewmodel_ofs_up = gEngfuncs.pfnRegisterVariable( "cl_viewmodel_ofs_up","0", FCVAR_ARCHIVE ); // z = up }