diff --git a/engine/client/cl_cmds.c b/engine/client/cl_cmds.c index ae4498f5..3d502c5d 100644 --- a/engine/client/cl_cmds.c +++ b/engine/client/cl_cmds.c @@ -461,8 +461,8 @@ void SCR_TimeRefresh_f( void ) R_BeginFrame( false ); for( i = 0; i < 128; i++ ) { - cl.refdef.viewangles[1] = i / 128.0 * 360.0f; - R_RenderFrame( &cl.refdef, true ); + RI.viewangles[1] = i / 128.0 * 360.0f; + R_RenderScene(); } R_EndFrame(); } @@ -470,10 +470,10 @@ void SCR_TimeRefresh_f( void ) { for( i = 0; i < 128; i++ ) { - cl.refdef.viewangles[1] = i / 128.0 * 360.0f; + RI.viewangles[1] = i / 128.0 * 360.0f; R_BeginFrame( true ); - R_RenderFrame( &cl.refdef, true ); + R_RenderScene(); R_EndFrame(); } } @@ -492,6 +492,6 @@ viewpos (level-designer helper) */ void SCR_Viewpos_f( void ) { - Msg( "org ( %g %g %g )\n", cl.refdef.vieworg[0], cl.refdef.vieworg[1], cl.refdef.vieworg[2] ); - Msg( "ang ( %g %g %g )\n", cl.refdef.viewangles[0], cl.refdef.viewangles[1], cl.refdef.viewangles[2] ); + Msg( "org ( %g %g %g )\n", RI.vieworg[0], RI.vieworg[1], RI.vieworg[2] ); + Msg( "ang ( %g %g %g )\n", RI.viewangles[0], RI.viewangles[1], RI.viewangles[2] ); } \ No newline at end of file diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index d37ec8e5..f1974482 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -15,6 +15,7 @@ GNU General Public License for more details. #include "common.h" #include "client.h" +#include "gl_local.h" #include "net_encode.h" #define dem_unknown 0 // unknown command @@ -486,7 +487,7 @@ void CL_DrawDemoRecording( void ) Q_memprint( pos ), (int)(cls.demotime / 60.0f ), (int)fmod( cls.demotime, 60.0f )); Con_DrawStringLen( string, &len, NULL ); - Con_DrawString(((int)scr_width->value - len) >> 1, (int)scr_height->value >> 2, string, color ); + Con_DrawString(( glState.width - len ) >> 1, glState.height >> 2, string, color ); } /* @@ -552,9 +553,9 @@ void CL_ReadDemoUserCmd( qboolean discard ) pcmd->sendsize = 1; // always delta'ing from null - cl.refdef.cmd = &pcmd->cmd; + cl.cmd = &pcmd->cmd; - MSG_ReadDeltaUsercmd( &buf, &nullcmd, cl.refdef.cmd ); + MSG_ReadDeltaUsercmd( &buf, &nullcmd, cl.cmd ); // make sure what interp info contain angles from different frames // or lerping will stop working @@ -566,7 +567,7 @@ void CL_ReadDemoUserCmd( qboolean discard ) // record update a->starttime = demo.timestamp; - VectorCopy( cl.refdef.cmd->viewangles, a->viewangles ); + VectorCopy( cl.viewangles, a->viewangles ); demo.lasttime = demo.timestamp; } @@ -731,7 +732,7 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length ) // HACKHACK: changedemo issues if( !cls.netchan.remote_address.type ) cls.netchan.remote_address.type = NA_LOOPBACK; - if(( !cl.background && ( cl.refdef.paused || cls.key_dest != key_game )) || cls.key_dest == key_console ) + if(( !cl.background && ( cl.paused || cls.key_dest != key_game )) || cls.key_dest == key_console ) { demo.starttime += host.frametime; return false; // paused @@ -891,9 +892,9 @@ void CL_DemoInterpolateAngles( void ) AngleQuaternion( next->viewangles, q1, false ); AngleQuaternion( prev->viewangles, q2, false ); QuaternionSlerp( q2, q1, frac, q ); - QuaternionAngle( q, cl.refdef.cl_viewangles ); + QuaternionAngle( q, cl.viewangles ); } - else VectorCopy( cl.refdef.cmd->viewangles, cl.refdef.cl_viewangles ); + else VectorCopy( cl.cmd->viewangles, cl.viewangles ); } /* diff --git a/engine/client/cl_events.c b/engine/client/cl_events.c index 5b4af439..ce7b5151 100644 --- a/engine/client/cl_events.c +++ b/engine/client/cl_events.c @@ -397,7 +397,6 @@ void CL_ParseEvent( sizebuf_t *msg ) int packet_index; event_args_t nullargs, args; entity_state_t *state; - cl_entity_t *pEnt; float delay; memset( &nullargs, 0, sizeof( nullargs )); @@ -461,69 +460,6 @@ void CL_ParseEvent( sizebuf_t *msg ) // Place event on queue CL_QueueEvent( FEV_SERVER, event_index, delay, &args ); } -#if 0 - if( packet_index != -1 ) - state = &cls.packet_entities[(cl.frame.first_entity+packet_index)%cls.num_client_entities]; - else state = NULL; - - // it's a client. Override some params - if( args.entindex >= 1 && args.entindex <= cl.maxclients ) - { - if(( args.entindex - 1 ) == cl.playernum ) - { - if( state && !CL_IsPredicted( )) - { - // restore viewangles from angles - args.angles[PITCH] = -state->angles[PITCH] * 3; - args.angles[YAW] = state->angles[YAW]; - args.angles[ROLL] = 0; // no roll - } - else - { - // get the predicted angles - VectorCopy( cl.refdef.cl_viewangles, args.angles ); - } - - VectorCopy( cl.frame.client.origin, args.origin ); - VectorCopy( cl.frame.client.velocity, args.velocity ); - } - else if( state ) - { - // restore viewangles from angles - args.angles[PITCH] = -state->angles[PITCH] * 3; - args.angles[YAW] = state->angles[YAW]; - args.angles[ROLL] = 0; // no roll - - if( VectorIsNull( args.origin )) - VectorCopy( state->origin, args.origin ); - if( VectorIsNull( args.velocity )) - VectorCopy( state->velocity, args.velocity ); - } - - COM_NormalizeAngles( args.angles ); - } - else if( state ) - { - if( VectorIsNull( args.origin )) - VectorCopy( state->origin, args.origin ); - if( VectorIsNull( args.angles )) - VectorCopy( state->angles, args.angles ); - if( VectorIsNull( args.velocity )) - VectorCopy( state->velocity, args.velocity ); - } - else if(( pEnt = CL_GetEntityByIndex( args.entindex )) != NULL ) - { - if( VectorIsNull( args.origin )) - VectorCopy( pEnt->curstate.origin, args.origin ); - if( VectorIsNull( args.angles )) - VectorCopy( pEnt->curstate.angles, args.angles ); - if( VectorIsNull( args.velocity )) - VectorCopy( pEnt->curstate.velocity, args.velocity ); - } - - // g-cont. should we need find the event with same index? - CL_QueueEvent( FEV_SERVER, event_index, delay, &args ); -#endif } } @@ -537,7 +473,12 @@ void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, floa float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ) { event_args_t args; - int invokerIndex = 0; + + if( flags & FEV_SERVER ) + { + MsgDev( D_WARN, "CL_PlaybackEvent: event with FEV_SERVER flag!\n" ); + return; + } // first check event for out of bounds if( eventindex < 1 || eventindex > MAX_EVENTS ) @@ -546,12 +487,6 @@ void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, floa return; } - if( flags & FEV_SERVER ) - { - MsgDev( D_WARN, "CL_PlaybackEvent: event with FEV_SERVER flag!\n" ); - return; - } - // check event for precached if( !CL_EventIndex( cl.event_precache[eventindex] )) { @@ -561,34 +496,15 @@ void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, floa flags |= FEV_CLIENT; // it's a client event flags &= ~(FEV_NOTHOST|FEV_HOSTONLY|FEV_GLOBAL); - if( delay < 0.0f ) delay = 0.0f; // fixup negative delays - invokerIndex = cl.playernum + 1; // only local client can issue client events - args.flags = 0; - args.entindex = invokerIndex; + memset( &args, 0, sizeof( args )); - if( !angles || VectorIsNull( angles )) - VectorCopy( cl.refdef.cl_viewangles, args.angles ); - else VectorCopy( angles, args.angles ); - - if( !origin || VectorIsNull( origin )) - { - if( CL_IsPredicted( )) VectorCopy( cl.predicted.origin, args.origin ); - else VectorCopy( cl.frame.client.origin, args.origin ); - } - else VectorCopy( origin, args.origin ); - - if( CL_IsPredicted( )) - { - VectorCopy( cl.predicted.velocity, args.velocity ); - args.ducking = (cl.predicted.usehull == 1); - } - else - { - VectorCopy( cl.frame.client.velocity, args.velocity ); - args.ducking = cl.frame.client.bInDuck; - } + VectorCopy( origin, args.origin ); + VectorCopy( angles, args.angles ); + VectorCopy( cl.simvel, args.velocity ); + args.entindex = cl.playernum + 1; + args.ducking = ( cl.local.usehull == 1 ); args.fparam1 = fparam1; args.fparam2 = fparam2; diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index 00477689..4e9560c1 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -25,8 +25,6 @@ GNU General Public License for more details. #include "sound.h" #include "input.h" -#define MAX_FORWARD 6 - qboolean CL_IsPlayerIndex( int idx ) { if( idx > 0 && idx <= cl.maxclients ) @@ -34,17 +32,6 @@ qboolean CL_IsPlayerIndex( int idx ) return false; } -qboolean CL_IsPredicted( void ) -{ - if( cl_nopred->value || !cl.frame.valid || cl.background || cls.spectator ) - return false; - - if( !cl.validsequence || ( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= CL_UPDATE_MASK ) - return false; - - return true; -} - int CL_PushMoveFilter( physent_t *pe ) { if( !pe || pe->solid != SOLID_BSP || pe->movetype != MOVETYPE_PUSH ) @@ -82,36 +69,52 @@ void CL_UpdatePositions( cl_entity_t *ent ) VectorCopy( ent->curstate.origin, ph->origin ); VectorCopy( ent->curstate.angles, ph->angles ); - ph->animtime = cl.mtime[0]; + ph->animtime = ent->curstate.animtime; // !!! +} + +/* +================== +CL_ResetPositions + +Interpolation init or reset after teleporting +================== +*/ +void CL_ResetPositions( cl_entity_t *ent ) +{ + position_history_t store; + + if( !ent ) return; + + store = ent->ph[ent->current_position]; + ent->current_position = 1; + + memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX ); + memcpy( &ent->ph[1], &store, sizeof( position_history_t )); + memcpy( &ent->ph[0], &store, sizeof( position_history_t )); } qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, float targettime, position_history_t **ph0, position_history_t **ph1, int *ph0Index ) { - qboolean extrapolate; + qboolean extrapolate = true; int i, i0, i1, imod; float at; - imod = ent->current_position - 1; - i0 = (imod + 1) & HISTORY_MASK; - i1 = imod & HISTORY_MASK; + imod = ent->current_position; + i0 = (imod - 0) & HISTORY_MASK; // curpos (lerp end) + i1 = (imod - 1) & HISTORY_MASK; // oldpos (lerp start) - extrapolate = true; - - if( ent->ph[i0].animtime >= targettime ) + for( i = 1; i < HISTORY_MAX - 1; i++ ) { - for( i = 0; i < HISTORY_MAX - 2; i++ ) - { - at = ent->ph[imod & HISTORY_MASK].animtime; - if( at == 0.0f ) break; + at = ent->ph[( imod - i ) & HISTORY_MASK].animtime; + if( at == 0.0 ) break; - if( at < targettime ) - { - i0 = (imod + 1) & HISTORY_MASK; - i1 = imod & HISTORY_MASK; - extrapolate = false; - break; - } - imod--; + if( targettime > at ) + { + // found it + i0 = (( imod - i ) + 1 ) & HISTORY_MASK; + i1 = (( imod - i ) + 0 ) & HISTORY_MASK; + extrapolate = false; + break; } } @@ -122,6 +125,49 @@ qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, float targettime, positi return extrapolate; } +void CL_PureOrigin( cl_entity_t *ent, float t, vec3_t outorigin, vec3_t outangles ) +{ + qboolean extrapolate; + float t1, t0, frac; + position_history_t *ph0, *ph1; + vec3_t delta; + + // NOTE: ph0 is next, ph1 is a prev + extrapolate = CL_FindInterpolationUpdates( ent, t, &ph0, &ph1, NULL ); + + if ( !ph0 || !ph1 ) + return; + + t0 = ph0->animtime; + t1 = ph1->animtime; + + if( t0 != 0.0f ) + { + vec4_t q, q1, q2; + + VectorSubtract( ph0->origin, ph1->origin, delta ); + + if( t0 != t1 ) + frac = ( t - t1 ) / ( t0 - t1 ); + else frac = 1.0f; + + frac = bound( 0.0f, frac, 1.2f ); + + VectorMA( ph1->origin, frac, delta, outorigin ); + + AngleQuaternion( ph0->angles, q1, false ); + AngleQuaternion( ph1->angles, q2, false ); + QuaternionSlerp( q2, q1, frac, q ); + QuaternionAngle( q, outangles ); + } + else + { + // no backup found + VectorCopy( ph1->origin, outorigin ); + VectorCopy( ph1->angles, outangles ); + } +} + int CL_InterpolateModel( cl_entity_t *e ) { position_history_t *ph0 = NULL, *ph1 = NULL; @@ -137,7 +183,7 @@ int CL_InterpolateModel( cl_entity_t *e ) if( !e->model || ( e->model->name[0] == '*' && !cl_bmodelinterp->value ) || RP_LOCALCLIENT( e ) || cl.maxclients <= 1 ) return 1; - if( cl.predicted.moving && cl.predicted.onground == e->index ) + if( cl.local.moving && cl.local.onground == e->index ) return 1; if( e->curstate.starttime != 0.0f && e->curstate.impacttime != 0.0f ) @@ -256,7 +302,7 @@ void CL_UpdateEntityFields( cl_entity_t *ent ) ent->angles[PITCH] = -ent->angles[PITCH] / 3.0f; // make me lerp (multiplayer only. this code visually breaks XashXT parent system) - if( ent->index == cl.predicted.onground && cl.predicted.moving && ( cl.maxclients > 1 )) + if( ent->index == cl.local.onground && cl.local.moving && ( cl.maxclients > 1 )) { CL_InterpolateMovingEntity( ent ); } @@ -389,6 +435,49 @@ void CL_UpdateEntityFields( cl_entity_t *ent ) } } +/* +============= +CL_ComputePlayerOrigin + +interpolate non-local clients +============= +*/ +void CL_ComputePlayerOrigin( cl_entity_t *ent ) +{ + float targettime; + vec3_t origin; + vec3_t angles; + + if( !ent->player || ent->index == ( cl.playernum + 1 )) + return; + + targettime = cl.time - cl_interp->value; + CL_PureOrigin( ent, targettime, origin, angles ); + + VectorCopy( angles, ent->angles ); + VectorCopy( origin, ent->origin ); +} + +/* +============= +CL_InterpolateEntity + +interpolate entity movement +============= +*/ +void CL_InterpolateEntity( cl_entity_t *ent ) +{ + float targettime; + vec3_t origin; + vec3_t angles; + + targettime = cl.time - cl_interp->value; + CL_PureOrigin( ent, targettime, origin, angles ); + + VectorCopy( angles, ent->angles ); + VectorCopy( origin, ent->origin ); +} + qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType ) { if( !ent || !ent->model ) @@ -415,7 +504,7 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType ) return false; // don't add himself on firstperson - if( RP_LOCALCLIENT( ent ) && !cl.thirdperson && cls.key_dest != key_menu && cl.refdef.viewentity == ( cl.playernum + 1 )) + if( RP_LOCALCLIENT( ent ) && !cl.local.thirdperson && cls.key_dest != key_menu && cl.viewentity == ( cl.playernum + 1 )) { if( gl_allow_mirrors->value && world.has_mirrors ) { @@ -555,8 +644,8 @@ void CL_WeaponAnim( int iAnim, int body ) { cl_entity_t *view = &clgame.viewent; - cl.weaponstarttime = 0; - cl.weaponsequence = iAnim; + cl.local.weaponstarttime = 0; + cl.local.weaponsequence = iAnim; // anim is changed. update latchedvars if( iAnim != view->curstate.sequence ) @@ -1064,83 +1153,6 @@ INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS ========================================================================== */ -/* -=============== -CL_SetIdealPitch -=============== -*/ -void CL_SetIdealPitch( void ) -{ - float angleval, sinval, cosval; - float z[MAX_FORWARD], view_z; - vec3_t top, bottom, origin; - int i, j; - int step, dir, steps; - pmtrace_t tr; - - if( !( cl.frame.client.flags & FL_ONGROUND )) - return; - - if( CL_IsPredicted( )) - { - VectorCopy( cl.predicted.origin, origin ); - view_z = cl.predicted.viewofs[2]; - } - else - { - VectorCopy( cl.frame.client.origin, origin ); - view_z = cl.frame.client.view_ofs[2]; - } - - angleval = cl.frame.playerstate[cl.playernum].angles[YAW] * M_PI2 / 360.0f; - SinCos( angleval, &sinval, &cosval ); - - for( i = 0; i < MAX_FORWARD; i++ ) - { - top[0] = origin[0] + cosval * (i + 3.0f) * 12.0f; - top[1] = origin[1] + sinval * (i + 3.0f) * 12.0f; - top[2] = origin[2] + view_z; - - bottom[0] = top[0]; - bottom[1] = top[1]; - bottom[2] = top[2] - 160.0f; - - // skip any monsters (only world and brush models) - tr = CL_TraceLine( top, bottom, PM_STUDIO_IGNORE ); - if( tr.allsolid ) return; // looking at a wall, leave ideal the way is was - - if( tr.fraction == 1.0f ) - return; // near a dropoff - - z[i] = top[2] + tr.fraction * (bottom[2] - top[2]); - } - - dir = 0; - steps = 0; - - for( j = 1; j < i; j++ ) - { - step = z[j] - z[j-1]; - if( step > -ON_EPSILON && step < ON_EPSILON ) - continue; - - if( dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON )) - return; // mixed changes - - steps++; - dir = step; - } - - if( !dir ) - { - cl.refdef.idealpitch = 0.0f; - return; - } - - if( steps < 2 ) return; - cl.refdef.idealpitch = -dir * cl_idealpitchscale->value; -} - /* =============== CL_AddPacketEntities diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index c34a898f..db5cd840 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -67,7 +67,7 @@ static dllfunc_t cdll_exports[] = { "Demo_ReadBuffer", (void **)&clgame.dllFuncs.pfnDemo_ReadBuffer }, { "CAM_Think", (void **)&clgame.dllFuncs.CAM_Think }, { "CL_IsThirdPerson", (void **)&clgame.dllFuncs.CL_IsThirdPerson }, -{ "CL_CameraOffset", (void **)&clgame.dllFuncs.CL_CameraOffset }, +{ "CL_CameraOffset", (void **)&clgame.dllFuncs.CL_CameraOffset }, // unused callback. Now camera code is completely moved to the user area { "CL_CreateMove", (void **)&clgame.dllFuncs.CL_CreateMove }, { "IN_ActivateMouse", (void **)&clgame.dllFuncs.IN_ActivateMouse }, { "IN_DeactivateMouse", (void **)&clgame.dllFuncs.IN_DeactivateMouse }, @@ -139,7 +139,7 @@ returns true if thirdperson is enabled */ qboolean CL_IsThirdPerson( void ) { - return cl.thirdperson; + return cl.local.thirdperson; } /* @@ -284,18 +284,18 @@ static int CL_AdjustXPos( float x, int width, int totalWidth ) if( x == -1 ) { - xPos = ( clgame.scrInfo.iWidth - width ) * 0.5f; + xPos = ( glState.width - width ) * 0.5f; } else { if ( x < 0 ) - xPos = (1.0f + x) * clgame.scrInfo.iWidth - totalWidth; // Alight right + xPos = (1.0f + x) * glState.width - totalWidth; // Alight right else // align left - xPos = x * clgame.scrInfo.iWidth; + xPos = x * glState.width; } - if( xPos + width > clgame.scrInfo.iWidth ) - xPos = clgame.scrInfo.iWidth - width; + if( xPos + width > glState.width ) + xPos = glState.width - width; else if( xPos < 0 ) xPos = 0; @@ -315,19 +315,19 @@ static int CL_AdjustYPos( float y, int height ) if( y == -1 ) // centered? { - yPos = ( clgame.scrInfo.iHeight - height ) * 0.5f; + yPos = ( glState.height - height ) * 0.5f; } else { // Alight bottom? if( y < 0 ) - yPos = (1.0f + y) * clgame.scrInfo.iHeight - height; // Alight bottom + yPos = (1.0f + y) * glState.height - height; // Alight bottom else // align top - yPos = y * clgame.scrInfo.iHeight; + yPos = y * glState.height; } - if( yPos + height > clgame.scrInfo.iHeight ) - yPos = clgame.scrInfo.iHeight - height; + if( yPos + height > glState.height ) + yPos = glState.height - height; else if( yPos < 0 ) yPos = 0; @@ -386,8 +386,8 @@ static void SPR_AdjustSize( float *x, float *y, float *w, float *h ) if( !x && !y && !w && !h ) return; // scale for screen sizes - xscale = scr_width->value / (float)clgame.scrInfo.iWidth; - yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + xscale = glState.width / (float)clgame.scrInfo.iWidth; + yscale = glState.height / (float)clgame.scrInfo.iHeight; if( x ) *x *= xscale; if( y ) *y *= yscale; @@ -410,8 +410,8 @@ void PicAdjustSize( float *x, float *y, float *w, float *h ) if( !x && !y && !w && !h ) return; // scale for screen sizes - xscale = scr_width->value / (float)clgame.scrInfo.iWidth; - yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + xscale = glState.width / (float)clgame.scrInfo.iWidth; + yscale = glState.height / (float)clgame.scrInfo.iHeight; if( x ) *x *= xscale; if( y ) *y *= yscale; @@ -583,7 +583,7 @@ void CL_DrawCenterPrint( void ) for( j = 0; j < lineLength; j++ ) { - if( x >= 0 && y >= 0 && x <= clgame.scrInfo.iWidth ) + if( x >= 0 && y >= 0 && x <= glState.width ) x += Con_DrawCharacter( x, y, line[j], colorDefault ); } y += charHeight; @@ -636,7 +636,7 @@ void CL_DrawScreenFade( void ) if( sf->fadeFlags & FFADE_MODULATE ) GL_SetRenderMode( kRenderTransAdd ); else GL_SetRenderMode( kRenderTransTexture ); - R_DrawStretchPic( 0, 0, scr_width->value, scr_height->value, 0, 0, 1, 1, cls.fillImage ); + R_DrawStretchPic( 0, 0, glState.width, glState.height, 0, 0, 1, 1, cls.fillImage ); pglColor4ub( 255, 255, 255, 255 ); } @@ -837,7 +837,7 @@ void CL_DrawCrosshair( void ) int x, y, width, height; cl_entity_t *pPlayer; - if( !clgame.ds.pCrosshair || cl.refdef.crosshairangle[2] || !cl_crosshair->value ) + if( !clgame.ds.pCrosshair || cl.crosshairangle[2] || !cl_crosshair->value ) return; pPlayer = CL_GetLocalPlayer(); @@ -846,31 +846,31 @@ void CL_DrawCrosshair( void ) return; // any camera on - if( cl.refdef.viewentity != pPlayer->index ) + if( cl.viewentity != pPlayer->index ) return; // get crosshair dimension width = clgame.ds.rcCrosshair.right - clgame.ds.rcCrosshair.left; height = clgame.ds.rcCrosshair.bottom - clgame.ds.rcCrosshair.top; - x = clgame.scrInfo.iWidth / 2; - y = clgame.scrInfo.iHeight / 2; + x = clgame.viewport[0] + ( clgame.viewport[2] >> 1 ); + y = clgame.viewport[1] + ( clgame.viewport[3] >> 1 ); - // g-cont - cl.refdef.crosshairangle is the autoaim angle. + // g-cont - cl.crosshairangle is the autoaim angle. // if we're not using autoaim, just draw in the middle of the screen - if( !VectorIsNull( cl.refdef.crosshairangle )) + if( !VectorIsNull( cl.crosshairangle )) { vec3_t angles; vec3_t forward; vec3_t point, screen; - VectorAdd( cl.refdef.viewangles, cl.refdef.crosshairangle, angles ); + VectorAdd( cl.viewangles, cl.crosshairangle, angles ); AngleVectors( angles, forward, NULL, NULL ); - VectorAdd( cl.refdef.vieworg, forward, point ); + VectorAdd( RI.vieworg, forward, point ); R_WorldToScreen( point, screen ); - x += 0.5f * screen[0] * scr_width->value + 0.5f; - y += 0.5f * screen[1] * scr_height->value + 0.5f; + x += ( clgame.viewport[2] >> 1 ) * screen[0] + 0.5f; + y += ( clgame.viewport[3] >> 1 ) * screen[1] + 0.5f; } clgame.ds.pSprite = clgame.ds.pCrosshair; @@ -899,8 +899,8 @@ static void CL_DrawLoading( float percent ) x = ( clgame.scrInfo.iWidth - width ) >> 1; y = ( clgame.scrInfo.iHeight - height) >> 1; - xscale = scr_width->value / (float)clgame.scrInfo.iWidth; - yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + xscale = glState.width / (float)clgame.scrInfo.iWidth; + yscale = glState.height / (float)clgame.scrInfo.iHeight; x *= xscale; y *= yscale; @@ -947,8 +947,8 @@ static void CL_DrawPause( void ) x = ( clgame.scrInfo.iWidth - width ) >> 1; y = ( clgame.scrInfo.iHeight - height) >> 1; - xscale = scr_width->value / (float)clgame.scrInfo.iWidth; - yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + xscale = glState.width / (float)clgame.scrInfo.iWidth; + yscale = glState.height / (float)clgame.scrInfo.iHeight; x *= xscale; y *= yscale; @@ -965,7 +965,7 @@ void CL_DrawHUD( int state ) if( state == CL_ACTIVE && !cl.video_prepped ) state = CL_LOADING; - if( state == CL_ACTIVE && cl.refdef.paused ) + if( state == CL_ACTIVE && cl.paused ) state = CL_PAUSED; switch( state ) @@ -974,13 +974,13 @@ void CL_DrawHUD( int state ) CL_DrawScreenFade (); CL_DrawCrosshair (); CL_DrawCenterPrint (); - clgame.dllFuncs.pfnRedraw( cl.time, cl.refdef.intermission ); + clgame.dllFuncs.pfnRedraw( cl.time, cl.intermission ); break; case CL_PAUSED: CL_DrawScreenFade (); CL_DrawCrosshair (); CL_DrawCenterPrint (); - clgame.dllFuncs.pfnRedraw( cl.time, cl.refdef.intermission ); + clgame.dllFuncs.pfnRedraw( cl.time, cl.intermission ); CL_DrawPause(); break; case CL_LOADING: @@ -1429,10 +1429,11 @@ static int pfnGetScreenInfo( SCREENINFO *pscrinfo ) { // setup screen info clgame.scrInfo.iSize = sizeof( clgame.scrInfo ); + clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH; if( Cvar_VariableInteger( "hud_scale" )) { - if( scr_width->value < 640 ) + if( glState.width < 640 ) { // virtual screen space 320x200 clgame.scrInfo.iWidth = 320; @@ -1448,8 +1449,8 @@ static int pfnGetScreenInfo( SCREENINFO *pscrinfo ) } else { - clgame.scrInfo.iWidth = scr_width->value; - clgame.scrInfo.iHeight = scr_height->value; + clgame.scrInfo.iWidth = glState.width; + clgame.scrInfo.iHeight = glState.height; clgame.scrInfo.iFlags &= ~SCRINFO_STRETCHED; } @@ -1590,7 +1591,7 @@ pfnPlaySoundByName static void pfnPlaySoundByName( const char *szSound, float volume ) { int hSound = S_RegisterSound( szSound ); - S_StartSound( NULL, cl.refdef.viewentity, CHAN_ITEM, hSound, volume, ATTN_NORM, PITCH_NORM, SND_STOP_LOOPING ); + S_StartSound( NULL, cl.viewentity, CHAN_ITEM, hSound, volume, ATTN_NORM, PITCH_NORM, SND_STOP_LOOPING ); } /* @@ -1612,7 +1613,7 @@ static void pfnPlaySoundByIndex( int iSound, float volume ) MsgDev( D_ERROR, "CL_PlaySoundByIndex: invalid sound handle %i\n", iSound ); return; } - S_StartSound( NULL, cl.refdef.viewentity, CHAN_ITEM, hSound, volume, ATTN_NORM, PITCH_NORM, SND_STOP_LOOPING ); + S_StartSound( NULL, cl.viewentity, CHAN_ITEM, hSound, volume, ATTN_NORM, PITCH_NORM, SND_STOP_LOOPING ); } /* @@ -1680,11 +1681,9 @@ int pfnDrawConsoleString( int x, int y, char *string ) int drawLen; if( !string || !*string ) return 0; // silent ignore - clgame.ds.adjust_size = true; Con_SetFont( con_fontsize->value ); drawLen = Con_DrawString( x, y, string, clgame.ds.textColor ); MakeRGBA( clgame.ds.textColor, 255, 255, 255, 255 ); - clgame.ds.adjust_size = false; Con_RestoreFont(); return (x + drawLen); // exclude color prexfixes @@ -1779,7 +1778,7 @@ return interpolated angles from previous frame */ static void pfnGetViewAngles( float *angles ) { - if( angles ) VectorCopy( cl.refdef.cl_viewangles, angles ); + if( angles ) VectorCopy( cl.viewangles, angles ); } /* @@ -1791,7 +1790,7 @@ return interpolated angles from previous frame */ static void pfnSetViewAngles( float *angles ) { - if( angles ) VectorCopy( angles, cl.refdef.cl_viewangles ); + if( angles ) VectorCopy( angles, cl.viewangles ); } /* @@ -2178,9 +2177,7 @@ pfnLocalPlayerDucking */ int pfnLocalPlayerDucking( void ) { - if( CL_IsPredicted( )) - return (cl.predicted.usehull == 1); - return cl.frame.client.bInDuck; + return (cl.local.usehull == 1) ? true : false; } /* @@ -2191,12 +2188,7 @@ pfnLocalPlayerViewheight */ void pfnLocalPlayerViewheight( float *view_ofs ) { - // predicted or smoothed - if( !view_ofs ) return; - - if( CL_IsPredicted( )) - VectorCopy( cl.predicted.viewofs, view_ofs ); - else VectorCopy( cl.frame.client.view_ofs, view_ofs ); + if( view_ofs ) VectorCopy( cl.viewheight, view_ofs ); } /* @@ -2792,7 +2784,7 @@ pfnPlaySoundVoiceByName void pfnPlaySoundVoiceByName( char *filename, float volume, int pitch ) { int hSound = S_RegisterSound( filename ); - S_StartSound( NULL, cl.refdef.viewentity, CHAN_AUTO, hSound, volume, ATTN_NORM, pitch, SND_STOP_LOOPING ); + S_StartSound( NULL, cl.viewentity, CHAN_AUTO, hSound, volume, ATTN_NORM, pitch, SND_STOP_LOOPING ); } /* @@ -2828,7 +2820,7 @@ pfnPlaySoundByNameAtPitch void pfnPlaySoundByNameAtPitch( char *filename, float volume, int pitch ) { int hSound = S_RegisterSound( filename ); - S_StartSound( NULL, cl.refdef.viewentity, CHAN_STATIC, hSound, volume, ATTN_NORM, pitch, SND_STOP_LOOPING ); + S_StartSound( NULL, cl.viewentity, CHAN_STATIC, hSound, volume, ATTN_NORM, pitch, SND_STOP_LOOPING ); } /* @@ -3119,10 +3111,10 @@ int TriWorldToScreen( float *world, float *screen ) retval = R_WorldToScreen( world, screen ); - screen[0] = 0.5f * screen[0] * (float)cl.refdef.viewport[2]; - screen[1] = -0.5f * screen[1] * (float)cl.refdef.viewport[3]; - screen[0] += 0.5f * (float)cl.refdef.viewport[2]; - screen[1] += 0.5f * (float)cl.refdef.viewport[3]; + screen[0] = 0.5f * screen[0] * (float)clgame.viewport[2]; + screen[1] = -0.5f * screen[1] * (float)clgame.viewport[3]; + screen[0] += 0.5f * (float)clgame.viewport[2]; + screen[1] += 0.5f * (float)clgame.viewport[3]; return retval; } @@ -3938,9 +3930,6 @@ qboolean CL_LoadProgs( const char *name ) if( clgame.hInstance ) CL_UnloadProgs(); - // setup globals - cl.refdef.movevars = &clgame.movevars; - // initialize PlayerMove clgame.pmove = &gpMove; diff --git a/engine/client/cl_gameui.c b/engine/client/cl_gameui.c index 7cbae45f..51daf720 100644 --- a/engine/client/cl_gameui.c +++ b/engine/client/cl_gameui.c @@ -666,7 +666,10 @@ static void pfnRenderScene( const ref_params_t *fd ) // to avoid division by zero if( !fd || fd->fov_x <= 0.0f || fd->fov_y <= 0.0f ) return; - R_RenderFrame( fd, false ); + + R_Set2DMode( false ); + R_RenderFrame( fd, false, fd->fov_x ); + R_Set2DMode( true ); } /* diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 2cbdd13c..f7dd3be3 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -92,7 +92,7 @@ qboolean CL_IsInConsole( void ) qboolean CL_IsIntermission( void ) { - return cl.refdef.intermission; + return cl.intermission; } qboolean CL_IsPlaybackDemo( void ) @@ -125,6 +125,17 @@ char *CL_Userinfo( void ) return cls.userinfo; } +int CL_IsDevOverviewMode( void ) +{ + if( gl_overview->value ) + { + if( host.developer > 0 || cls.spectator ) + return 1; + } + + return 0; +} + /* =============== CL_ChangeGame @@ -258,6 +269,86 @@ static float CL_LerpPoint( void ) return frac; } +/* +=============== +CL_DriftInterpolationAmount + +Drift interpolation value (this is used for server unlag system) +=============== +*/ +int CL_DriftInterpolationAmount( int goal ) +{ + float fgoal, maxmove, diff; + int msec; + + fgoal = (float)goal / 1000.0f; + + if( fgoal != cl.local.interp_amount ) + { + maxmove = host.frametime * 0.05; + diff = fgoal - cl.local.interp_amount; + diff = bound( -maxmove, diff, maxmove ); + cl.local.interp_amount += diff; + } + + msec = cl.local.interp_amount * 1000.0f; + msec = bound( 0, msec, 100 ); + + return msec; +} + +/* +=============== +CL_ComputeClientInterpolationAmount + +Validate interpolation cvars, calc interpolation window +=============== +*/ +void CL_ComputeClientInterpolationAmount( usercmd_t *cmd ) +{ + int min_interp = MIN_EX_INTERP; + int max_interp = MAX_EX_INTERP; + int interpolation_msec; + qboolean forced = false; + + if( cl_updaterate->value < MIN_UPDATERATE ) + { + Con_Printf( "cl_updaterate minimum is %f, resetting to default (20)\n", MIN_UPDATERATE ); + Cvar_Reset( "cl_updaterate" ); + } + + if( cl_updaterate->value > MAX_UPDATERATE ) + { + Con_Printf( "cl_updaterate clamped at maximum (%f)\n", MAX_UPDATERATE ); + Cvar_SetValue( "cl_updaterate", MAX_UPDATERATE ); + } + + if( cls.spectator ) + max_interp = 200; + + min_interp = 1000.0f / cl_updaterate->value; + min_interp = Q_max( 1, min_interp ); + interpolation_msec = cl_interp->value * 1000.0f; + + if(( interpolation_msec + 1 ) < min_interp ) + { + MsgDev( D_INFO, "ex_interp forced up to %i msec\n", interpolation_msec ); + interpolation_msec = min_interp; + forced = true; + } + else if(( interpolation_msec - 1 ) > max_interp ) + { + MsgDev( D_INFO, "ex_interp forced down to %i msec\n", interpolation_msec ); + interpolation_msec = max_interp; + forced = true; + } + + if( forced ) Cvar_SetValue( "ex_interp", (float)interpolation_msec * 0.001f ); + interpolation_msec = bound( min_interp, interpolation_msec, max_interp ); + + cmd->lerp_msec = CL_DriftInterpolationAmount( interpolation_msec ); +} + /* ================= CL_ComputePacketLoss @@ -399,6 +490,35 @@ qboolean CL_ProcessOverviewCmds( usercmd_t *cmd ) return true; } +/* +================= +CL_UpdateClientData + +tell the client.dll about player origin, angles, fov, etc +================= +*/ +void CL_UpdateClientData( void ) +{ + client_data_t cdat; + + if( cls.state != ca_active ) + return; + + memset( &cdat, 0, sizeof( cdat ) ); + + VectorCopy( cl.viewangles, cdat.viewangles ); + VectorCopy( clgame.entities[cl.viewentity].origin, cdat.origin ); + cdat.iWeaponBits = cl.local.weapons; + cdat.fov = cl.local.scr_fov; + + if( clgame.dllFuncs.pfnUpdateClientData( &cdat, cl.time )) + { + // grab changes if successful + VectorCopy( cdat.viewangles, cl.viewangles ); + cl.local.scr_fov = cdat.fov; + } +} + /* ================= CL_CreateCmd @@ -408,35 +528,27 @@ void CL_CreateCmd( void ) { usercmd_t cmd; runcmd_t *pcmd; - color24 color; vec3_t angles; qboolean active; int input_override; int i, ms; - ms = host.frametime * 1000; - if( ms > 250 ) ms = 100; // time was unreasonable - else if( ms <= 0 ) ms = 1; // keep time an actual + // store viewangles in case it's frozen + VectorCopy( cl.viewangles, angles ); + CL_UpdateClientData(); + + if( cls.state < ca_connected || cls.state == ca_cinematic ) + return; + + ms = bound( 1, host.frametime * 1000, 255 ); memset( &cmd, 0, sizeof( cmd )); input_override = 0; + CL_SetSolidEntities(); CL_PushPMStates(); CL_SetSolidPlayers( cl.playernum ); - VectorCopy( cl.refdef.cl_viewangles, angles ); - VectorCopy( cl.frame.client.origin, cl.data.origin ); - VectorCopy( cl.refdef.cl_viewangles, cl.data.viewangles ); - cl.data.iWeaponBits = cl.frame.client.weapons; - cl.data.fov = cl.scr_fov; - - if( clgame.dllFuncs.pfnUpdateClientData( &cl.data, cl.time )) - { - // grab changes if successful - VectorCopy( cl.data.viewangles, cl.refdef.cl_viewangles ); - cl.scr_fov = cl.data.fov; - } - // message we are constructing. i = cls.netchan.outgoing_sequence & CL_UPDATE_MASK; pcmd = &cl.commands[i]; @@ -451,20 +563,16 @@ void CL_CreateCmd( void ) pcmd->sendsize = 0; } - active = ( cls.state == ca_active && !cl.refdef.paused && !cls.demoplayback ); - clgame.dllFuncs.CL_CreateMove( cl.time - cl.oldtime, &pcmd->cmd, active ); + active = ( cls.state == ca_active && !cl.paused && !cls.demoplayback ); + clgame.dllFuncs.CL_CreateMove( host.frametime, &pcmd->cmd, active ); + CL_PopPMStates(); if( !cls.demoplayback ) { - R_LightForPoint( cl.frame.client.origin, &color, false, false, 128.0f ); - pcmd->cmd.lightlevel = (color.r + color.g + color.b) / 3; - - // never let client.dll calc frametime for player - // because is potential backdoor for cheating + CL_ComputeClientInterpolationAmount( &pcmd->cmd ); + pcmd->cmd.lightlevel = cl.local.light_level; pcmd->cmd.msec = ms; - pcmd->cmd.lerp_msec = cl_interp->value * 1000; - pcmd->cmd.lerp_msec = bound( 0, cmd.lerp_msec, 250 ); } input_override |= CL_ProcessOverviewCmds( &pcmd->cmd ); @@ -472,13 +580,13 @@ void CL_CreateCmd( void ) if(( cl.background && !cls.demoplayback ) || input_override || cls.changelevel ) { - VectorCopy( angles, cl.refdef.cl_viewangles ); VectorCopy( angles, pcmd->cmd.viewangles ); + VectorCopy( angles, cl.viewangles ); pcmd->cmd.msec = 0; } // demo always have commands so don't overwrite them - if( !cls.demoplayback ) cl.refdef.cmd = &pcmd->cmd; + if( !cls.demoplayback ) cl.cmd = &pcmd->cmd; } void CL_WriteUsercmd( sizebuf_t *msg, int from, int to ) @@ -525,10 +633,7 @@ void CL_WritePacket( void ) int cmdnumber; // don't send anything if playing back a demo - if( cls.demoplayback || cls.state == ca_cinematic ) - return; - - if( cls.state == ca_disconnected || cls.state == ca_connecting ) + if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic ) return; CL_ComputePacketLoss (); @@ -540,8 +645,8 @@ void CL_WritePacket( void ) if( cls.state == ca_connected ) numbackup = 0; // clamp cmdrate - if( cl_cmdrate->value < 0 ) Cvar_Set( "cl_cmdrate", "0" ); - else if( cl_cmdrate->value > 100 ) Cvar_Set( "cl_cmdrate", "100" ); + if( cl_cmdrate->value < 0.0f ) Cvar_SetValue( "cl_cmdrate", 0.0f ); + else if( cl_cmdrate->value > 100.0f ) Cvar_SetValue( "cl_cmdrate", 100.0f ); // Check to see if we can actually send this command @@ -563,6 +668,9 @@ void CL_WritePacket( void ) send_command = true; } + // spectator is not sending cmds to server + if( cls.spectator ) return; + if(( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= CL_UPDATE_MASK ) { if(( host.realtime - cls.netchan.last_received ) > CONNECTION_PROBLEM_TIME ) @@ -911,11 +1019,12 @@ void CL_ClearState( void ) memset( &clgame.fade, 0, sizeof( clgame.fade )); memset( &clgame.shake, 0, sizeof( clgame.shake )); Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY ); - cl.refdef.movevars = &clgame.movevars; cl.maxclients = 1; // allow to drawing player in menu cl.mtime[0] = cl.mtime[1] = 1.0f; // because level starts from 1.0f second NetAPI_CancelAllRequests(); - cl.scr_fov = 90.0f; + + cl.local.interp_amount = 0.1f; + cl.local.scr_fov = 90.0f; Cvar_SetValue( "scr_download", 0.0f ); Cvar_SetValue( "scr_loading", 0.0f ); @@ -1753,7 +1862,7 @@ void CL_ReadPackets( void ) cl.lerpFrac = CL_LerpPoint(); cl.lerpBack = 1.0f - cl.lerpFrac; - cl.thirdperson = clgame.dllFuncs.CL_IsThirdPerson(); + cl.local.thirdperson = clgame.dllFuncs.CL_IsThirdPerson(); #if 0 // keep cheat cvars are unchanged if( cl.maxclients > 1 && cls.state == ca_active && host.developer <= 1 ) @@ -2160,28 +2269,6 @@ void CL_AdjustClock( void ) } } -/* -================== -CL_PrepareFrame - -setup camera, update visible ents -================== -*/ -void CL_PrepareFrame( void ) -{ - if( cls.state != ca_active ) - return; // not in game - - if( !cl.video_prepped || ( UI_IsVisible() && !cl.background )) - return; // still loading - - if( cl.frame.valid && ( cl.force_refdef || !cl.refdef.paused )) - { - cl.force_refdef = false; - V_SetupRefDef (); - } -} - /* ================== Host_ClientFrame @@ -2297,13 +2384,13 @@ void Host_ClientFrame( void ) SCR_UpdateScreen (); // update audio - S_RenderFrame( &cl.refdef ); + SND_UpdateSound (); // send a new command message to the server CL_SendCommand(); // predict all unacknowledged movements - CL_PredictMovement(); + CL_PredictMovement( false ); // adjust client time CL_AdjustClock(); @@ -2331,7 +2418,6 @@ void CL_Init( void ) if( host.type == HOST_DEDICATED ) return; // nothing running on the client - Con_Init(); CL_InitLocal(); R_Init(); // init renderer diff --git a/engine/client/cl_netgraph.c b/engine/client/cl_netgraph.c index 0bbdc2e4..93396215 100644 --- a/engine/client/cl_netgraph.c +++ b/engine/client/cl_netgraph.c @@ -444,8 +444,8 @@ NetGraph_GetScreenPos void NetGraph_GetScreenPos( wrect_t *rect, int *w, int *x, int *y ) { rect->left = rect->top = 0; - rect->right = clgame.scrInfo.iWidth; - rect->bottom = clgame.scrInfo.iHeight; + rect->right = glState.width; + rect->bottom = glState.height; *w = Q_min( NET_TIMINGS, net_graphwidth->value ); if( rect->right < *w + 10 ) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index c1cb7a75..3c76cab3 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -433,9 +433,10 @@ void CL_ParseMovevars( sizebuf_t *msg ) R_SetupSky( clgame.movevars.skyName ); memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t )); + clgame.entities->curstate.scale = clgame.movevars.waveHeight; + // keep features an actual! clgame.oldmovevars.features = clgame.movevars.features = host.features; - clgame.entities->curstate.scale = cl.refdef.movevars->waveHeight; } /* @@ -684,7 +685,7 @@ void CL_ParseServerData( sizebuf_t *msg ) else if( !cls.demoplayback ) Key_SetKeyDest( key_menu ); - cl.refdef.viewentity = cl.playernum + 1; // always keep viewent an actual + cl.viewentity = cl.playernum + 1; // always keep viewent an actual gameui.globals->maxClients = cl.maxclients; Q_strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle )); @@ -799,9 +800,9 @@ void CL_ParseClientData( sizebuf_t *msg ) { last_predicted = ( cl.last_incoming_sequence + ( command_ack - cl.last_command_ack )) & CL_UPDATE_MASK; - pps = &cl.predict[last_predicted].playerstate; - pwd = cl.predict[last_predicted].weapondata; - ppcd = &cl.predict[last_predicted].client; + pps = &cl.predicted_frames[last_predicted].playerstate; + pwd = cl.predicted_frames[last_predicted].weapondata; + ppcd = &cl.predicted_frames[last_predicted].client; ps = &frame->playerstate[cl.playernum]; wd = frame->weapondata; @@ -853,7 +854,7 @@ void CL_ParseClientData( sizebuf_t *msg ) // clientdata for spectators ends here if( cls.spectator ) { - cl.predicted.health = 1; + cl.local.health = 1; return; } @@ -892,7 +893,10 @@ void CL_ParseClientData( sizebuf_t *msg ) // make a local copy of physinfo Q_strncpy( cls.physinfo, frame->client.physinfo, sizeof( cls.physinfo )); - cl.predicted.health = frame->client.health; + cl.local.maxspeed = frame->client.maxspeed; + cl.local.pushmsec = frame->client.pushmsec; + cl.local.weapons = frame->client.weapons; // g-cont 32-bit predictable weapon limit !!! + cl.local.health = frame->client.health; } /* @@ -951,9 +955,9 @@ set the view angle to this absolute value */ void CL_ParseSetAngle( sizebuf_t *msg ) { - cl.refdef.cl_viewangles[0] = MSG_ReadBitAngle( msg, 16 ); - cl.refdef.cl_viewangles[1] = MSG_ReadBitAngle( msg, 16 ); - cl.refdef.cl_viewangles[2] = MSG_ReadBitAngle( msg, 16 ); + cl.viewangles[0] = MSG_ReadBitAngle( msg, 16 ); + cl.viewangles[1] = MSG_ReadBitAngle( msg, 16 ); + cl.viewangles[2] = MSG_ReadBitAngle( msg, 16 ); } /* @@ -968,7 +972,7 @@ void CL_ParseAddAngle( sizebuf_t *msg ) float add_angle; add_angle = MSG_ReadBitAngle( msg, 16 ); - cl.refdef.cl_viewangles[1] += add_angle; + cl.viewangles[YAW] += add_angle; } /* @@ -980,9 +984,9 @@ offset crosshair angles */ void CL_ParseCrosshairAngle( sizebuf_t *msg ) { - cl.refdef.crosshairangle[0] = MSG_ReadChar( msg ) * 0.2f; - cl.refdef.crosshairangle[1] = MSG_ReadChar( msg ) * 0.2f; - cl.refdef.crosshairangle[2] = 0.0f; // not used for screen space + cl.crosshairangle[0] = MSG_ReadChar( msg ) * 0.2f; + cl.crosshairangle[1] = MSG_ReadChar( msg ) * 0.2f; + cl.crosshairangle[2] = 0.0f; // not used for screen space } /* @@ -1619,7 +1623,7 @@ void CL_ParseServerMessage( sizebuf_t *msg ) cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately break; case svc_setview: - cl.refdef.viewentity = MSG_ReadWord( msg ); + cl.viewentity = MSG_ReadWord( msg ); break; case svc_sound: case svc_ambientsound: @@ -1692,7 +1696,7 @@ void CL_ParseServerMessage( sizebuf_t *msg ) cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart; break; case svc_setpause: - cl.refdef.paused = ( MSG_ReadOneBit( msg ) != 0 ); + cl.paused = ( MSG_ReadOneBit( msg ) != 0 ); break; case svc_signonnum: CL_ParseSignon( msg ); @@ -1718,7 +1722,7 @@ void CL_ParseServerMessage( sizebuf_t *msg ) CL_UpdateUserinfo( msg ); break; case svc_intermission: - cl.refdef.intermission = true; + cl.intermission = true; break; case svc_modelindex: CL_PrecacheModel( msg ); diff --git a/engine/client/cl_pmove.c b/engine/client/cl_pmove.c index ce17983d..4d358f9a 100644 --- a/engine/client/cl_pmove.c +++ b/engine/client/cl_pmove.c @@ -21,6 +21,11 @@ GNU General Public License for more details. #include "particledef.h" #include "studio.h" +#define MAX_FORWARD 6 // forward probes for set idealpitch +#define MIN_CORRECTION_DISTANCE 0.25f // use smoothing if error is > this +#define MIN_PREDICTION_EPSILON 0.5f // complain if error is > this and we have cl_showerror set +#define MAX_PREDICTION_ERROR 64.0f // above this is assumed to be a teleport, don't smooth, etc. + void CL_ClearPhysEnts( void ) { clgame.pmove->numtouch = 0; @@ -39,7 +44,7 @@ void CL_PushPMStates( void ) { if( clgame.pushed ) { - MsgDev( D_ERROR, "PushPMStates called with pushed stack\n"); + MsgDev( D_ERROR, "PushPMStates: stack overflow\n"); } else { @@ -66,19 +71,115 @@ void CL_PopPMStates( void ) } else { - MsgDev( D_ERROR, "PopPMStates called without stack\n"); + MsgDev( D_ERROR, "PopPMStates: stack underflow\n"); } } /* -============= -CL_ComputePlayerOrigin - -FIXME: implement -============= +=============== +CL_SetLastUpdate +=============== */ -void CL_ComputePlayerOrigin( cl_entity_t *clent ) +void CL_SetLastUpdate( void ) { + cls.lastupdate_sequence = cls.netchan.incoming_sequence; +} + +/* +=============== +CL_RedoPrediction +=============== +*/ +void CL_RedoPrediction( void ) +{ + if ( cls.netchan.incoming_sequence != cls.lastupdate_sequence ) + { + CL_PredictMovement( true ); + CL_CheckPredictionError(); + } +} + +/* +=============== +CL_IsPredicted +=============== +*/ +qboolean CL_IsPredicted( void ) +{ + if( cl_nopred->value || !cl.frame.valid || cl.background || cls.spectator ) + return false; + + if( !cl.validsequence || ( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= CL_UPDATE_MASK ) + return false; + + return true; +} + +/* +=============== +CL_SetIdealPitch +=============== +*/ +void CL_SetIdealPitch( void ) +{ + float angleval, sinval, cosval; + int i, j, step, dir, steps; + float z[MAX_FORWARD]; + vec3_t top, bottom; + pmtrace_t tr; + + if( cl.local.onground == -1 ) + return; + + angleval = cl.viewangles[YAW] * M_PI2 / 360.0f; + SinCos( angleval, &sinval, &cosval ); + + // Now move forward by 36, 48, 60, etc. units from the eye position and drop lines straight down + // 160 or so units to see what's below + for( i = 0; i < MAX_FORWARD; i++ ) + { + top[0] = cl.simorg[0] + cosval * (i + 3.0f) * 12.0f; + top[1] = cl.simorg[1] + sinval * (i + 3.0f) * 12.0f; + top[2] = cl.simorg[2] + cl.viewheight[2]; + + bottom[0] = top[0]; + bottom[1] = top[1]; + bottom[2] = top[2] - 160.0f; + + // skip any monsters (only world and brush models) + tr = CL_TraceLine( top, bottom, PM_STUDIO_BOX ); + if( tr.allsolid ) return; // looking at a wall, leave ideal the way is was + + if( tr.fraction == 1.0f ) + return; // near a dropoff + + z[i] = top[2] + tr.fraction * (bottom[2] - top[2]); + } + + dir = 0; + steps = 0; + + for( j = 1; j < i; j++ ) + { + step = z[j] - z[j-1]; + if( step > -ON_EPSILON && step < ON_EPSILON ) + continue; + + if( dir && ( step-dir > ON_EPSILON || step-dir < -ON_EPSILON )) + return; // mixed changes + + steps++; + dir = step; + } + + if( !dir ) + { + cl.local.idealpitch = 0.0f; + return; + } + + if( steps < 2 ) return; + cl.local.idealpitch = -dir * cl_idealpitchscale->value; } /* @@ -91,7 +192,7 @@ void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient ) { entity_state_t *state; predicted_player_t *player; - cl_entity_t *clent; + cl_entity_t *ent; int i; for( i = 0; i < MAX_CLIENTS; i++ ) @@ -107,37 +208,29 @@ void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient ) if( !state->modelindex ) continue; - clent = CL_GetEntityByIndex( i + 1 ); + player->active = true; + player->movetype = state->movetype; + player->solid = state->solid; + player->usehull = state->usehull; - // special for EF_NODRAW and local client? - if( FBitSet( state->effects, EF_NODRAW ) && !bIncludeLocalClient ) + if( FBitSet( state->effects, EF_NODRAW ) && !bIncludeLocalClient && ( cl.playernum == i )) + continue; + + // note that the local player is special, since he moves locally + // we use his last predicted postition + if( cl.playernum == i ) { - // don't include local player? - if( cl.playernum == i ) continue; - - player->active = true; - player->movetype = state->movetype; - player->solid = state->solid; - player->usehull = state->usehull; - - CL_ComputePlayerOrigin( clent ); - - VectorCopy( clent->origin, player->origin ); - VectorCopy( clent->angles, player->angles ); + VectorCopy( state->origin, player->origin ); + VectorCopy( state->angles, player->angles ); } else { - player->active = true; - player->movetype = state->movetype; - player->solid = state->solid; - player->usehull = state->usehull; + ent = CL_GetEntityByIndex( i + 1 ); - // don't rewrite origin and angles of local client - if( cl.playernum == i ) - continue; + CL_ComputePlayerOrigin( ent ); - VectorCopy( state->origin, player->origin ); - VectorCopy( state->angles, player->angles ); + VectorCopy( ent->origin, player->origin ); + VectorCopy( ent->angles, player->angles ); } } } @@ -981,9 +1074,9 @@ void CL_RunUsercmd( local_state_t *from, local_state_t *to, usercmd_t *u, qboole // copy results back to client CL_FinishPMove( clgame.pmove, to ); - cl.predicted.lastground = clgame.pmove->onground; - if( cl.predicted.lastground > 0 && cl.predicted.lastground < clgame.pmove->numphysent ) - cl.predicted.lastground = clgame.pmove->physents[cl.predicted.lastground].info; + if( clgame.pmove->onground > 0 && clgame.pmove->onground < clgame.pmove->numphysent ) + cl.local.lastground = clgame.pmove->physents[clgame.pmove->onground].info; + else cl.local.lastground = clgame.pmove->onground; // world(0) or in air(-1) clgame.dllFuncs.pfnPostRunCmd( from, to, &cmd, runfuncs, *time, random_seed ); *time += (double)cmd.msec / 1000.0; @@ -996,42 +1089,41 @@ CL_CheckPredictionError */ void CL_CheckPredictionError( void ) { - int frame; - vec3_t delta; - float len, maxspd; - - if( !CL_IsPredicted( )) return; + int frame; + vec3_t delta; + float len, maxspd; + static int pos = 0; // calculate the last usercmd_t we sent that the server has processed frame = ( cls.netchan.incoming_acknowledged ) & CL_UPDATE_MASK; // compare what the server returned with what we had predicted it to be - VectorSubtract( cl.frame.playerstate[cl.playernum].origin, cl.predicted.origins[frame], delta ); + VectorSubtract( cl.frame.playerstate[cl.playernum].origin, cl.local.predicted_origins[frame], delta ); maxspd = ( clgame.movevars.maxvelocity * host.frametime ); len = VectorLength( delta ); // save the prediction error for interpolation - if( FBitSet( cl.frame.client.flags, EF_NOINTERP ) || ( len > ( maxspd * 2.0f ))) + if( FBitSet( cl.frame.client.flags, EF_NOINTERP ) || ( len > ( maxspd * 2.0f )) || len > MAX_PREDICTION_ERROR ) { if( cl_showerror->value && ( len > ( maxspd * 2.0f )) && host.developer >= D_ERROR ) - MsgDev( D_INFO, "CL_Predict: player teleported on %i: %g > %g\n", cl.parsecount, len, ( maxspd * 2.0f )); + Con_NPrintf( 10 + ( ++pos & 3 ), "^3player teleported:^7 %.3f units\n", len ); // a teleport or something or gamepaused - VectorClear( cl.predicted.error ); + VectorClear( cl.local.prediction_error ); } else { if( cl_showerror->value && len > 0.25f && host.developer >= D_ERROR ) - MsgDev( D_INFO, "CL_Predict: prediction error on %i: %g\n", cl.parsecount, len ); + Con_NPrintf( 10 + ( ++pos & 3 ), "^1prediction error:^7 %.3f units\n", cl.parsecount, len ); - VectorCopy( cl.frame.playerstate[cl.playernum].origin, cl.predicted.origins[frame] ); + VectorCopy( cl.frame.playerstate[cl.playernum].origin, cl.local.predicted_origins[frame] ); // save for error interpolation - VectorCopy( delta, cl.predicted.error ); + VectorCopy( delta, cl.local.prediction_error ); - if(( len > 0.25f ) && ( cl.maxclients > 1 )) - cl.predicted.correction_time = cl_smoothtime->value; + if(( len > MIN_CORRECTION_DISTANCE ) && ( cl.maxclients > 1 )) + cls.correction_time = cl_smoothtime->value; } } @@ -1073,7 +1165,7 @@ CL_PredictMovement Sets cl.predicted.origin and cl.predicted.angles ================= */ -void CL_PredictMovement( void ) +void CL_PredictMovement( qboolean repredicting ) { double time; usercmd_t *ucmd; @@ -1086,18 +1178,13 @@ void CL_PredictMovement( void ) if( cls.state != ca_active ) return; - if( cls.demoplayback && cl.refdef.cmd != NULL ) + if( cls.demoplayback && cl.cmd != NULL ) CL_DemoInterpolateAngles(); if( !CL_IsInGame( )) return; CL_SetUpPlayerPrediction( false, false ); - // unpredicted pure angled values converted into axis - AngleVectors( cl.refdef.cl_viewangles, cl.refdef.forward, cl.refdef.right, cl.refdef.up ); - - ASSERT( cl.refdef.cmd != NULL ); - if( !CL_IsPredicted( )) { // fake prediction code @@ -1105,14 +1192,14 @@ void CL_PredictMovement( void ) // because cl_lw is enabled by default in Half-Life if( !cl_lw->value ) { - cl.predicted.viewmodel = cl.frame.client.viewmodel; + cl.local.viewmodel = cl.frame.client.viewmodel; return; } ack = cls.netchan.incoming_acknowledged; outgoing_command = cls.netchan.outgoing_sequence; - from = &cl.predict[cl.parsecountmod]; + from = &cl.predicted_frames[cl.parsecountmod]; from->playerstate = cl.frame.playerstate[cl.playernum]; from->client = cl.frame.client; memcpy( from->weapondata, cl.frame.weapondata, sizeof( from->weapondata )); @@ -1133,7 +1220,7 @@ void CL_PredictMovement( void ) if( current_command >= outgoing_command ) break; - to = &cl.predict[( cl.parsecountmod + frame ) & CL_UPDATE_MASK]; + to = &cl.predicted_frames[( cl.parsecountmod + frame ) & CL_UPDATE_MASK]; CL_FakeUsercmd( from, to, &cl.commands[current_command_mod].cmd, !cl.commands[current_command_mod].processedfuncs, @@ -1146,14 +1233,14 @@ void CL_PredictMovement( void ) } if( to ) - cl.predicted.viewmodel = to->client.viewmodel; + cl.local.viewmodel = to->client.viewmodel; return; } ack = cls.netchan.incoming_acknowledged; outgoing_command = cls.netchan.outgoing_sequence; - from = &cl.predict[cl.parsecountmod]; + from = &cl.predicted_frames[cl.parsecountmod]; memcpy( from->weapondata, cl.frame.weapondata, sizeof( from->weapondata )); from->playerstate = cl.frame.playerstate[cl.playernum]; from->client = cl.frame.client; @@ -1176,7 +1263,7 @@ void CL_PredictMovement( void ) if( current_command >= outgoing_command ) break; - to = &cl.predict[( cl.parsecountmod + frame ) & CL_UPDATE_MASK]; + to = &cl.predicted_frames[( cl.parsecountmod + frame ) & CL_UPDATE_MASK]; runfuncs = !cl.commands[current_command_mod].processedfuncs; ucmd = &cl.commands[current_command_mod].cmd; @@ -1184,7 +1271,7 @@ void CL_PredictMovement( void ) cl.commands[current_command_mod].processedfuncs = true; // save for debug checking - VectorCopy( to->playerstate.origin, cl.predicted.origins[current_command_mod] ); + VectorCopy( to->playerstate.origin, cl.local.predicted_origins[current_command_mod] ); from = to; frame++; @@ -1193,7 +1280,7 @@ void CL_PredictMovement( void ) if( to ) { float t0 = cl.commands[( cl.parsecountmod + frame - 1) & CL_UPDATE_MASK].senttime; - float t1 = cl.commands[( cl.parsecountmod + frame ) & CL_UPDATE_MASK].senttime; + float t1 = cl.commands[( cl.parsecountmod + frame - 0) & CL_UPDATE_MASK].senttime; float t; if( t0 == t1 ) @@ -1211,10 +1298,10 @@ void CL_PredictMovement( void ) fabs( to->playerstate.origin[1] - from->playerstate.origin[1] ) > 128.0f || fabs( to->playerstate.origin[2] - from->playerstate.origin[2] ) > 128.0f ) { - VectorCopy( to->playerstate.origin, cl.predicted.origin ); - VectorCopy( to->client.velocity, cl.predicted.velocity ); - VectorCopy( to->client.punchangle, cl.predicted.punchangle ); - VectorCopy( to->client.view_ofs, cl.predicted.viewofs ); + VectorCopy( to->playerstate.origin, cl.simorg ); + VectorCopy( to->client.velocity, cl.simvel ); + VectorCopy( to->client.punchangle, cl.punchangle ); + VectorCopy( to->client.view_ofs, cl.viewheight ); } else { @@ -1224,29 +1311,29 @@ void CL_PredictMovement( void ) VectorSubtract( to->client.velocity, from->client.velocity, delta_vel ); VectorSubtract( to->client.punchangle, from->client.punchangle, delta_punch ); - VectorMA( from->playerstate.origin, t, delta_origin, cl.predicted.origin ); - VectorMA( from->client.velocity, t, delta_vel, cl.predicted.velocity ); - VectorMA( from->client.punchangle, t, delta_punch, cl.predicted.punchangle ); + VectorMA( from->playerstate.origin, t, delta_origin, cl.simorg ); + VectorMA( from->client.velocity, t, delta_vel, cl.simvel ); + VectorMA( from->client.punchangle, t, delta_punch, cl.punchangle ); if( from->playerstate.usehull == to->playerstate.usehull ) { vec3_t delta_viewofs; VectorSubtract( to->client.view_ofs, from->client.view_ofs, delta_viewofs ); - VectorMA( from->client.view_ofs, t, delta_viewofs, cl.predicted.viewofs ); + VectorMA( from->client.view_ofs, t, delta_viewofs, cl.viewheight ); } } - cl.predicted.waterlevel = to->client.waterlevel; - cl.predicted.viewmodel = to->client.viewmodel; - cl.predicted.usehull = to->playerstate.usehull; + cl.local.waterlevel = to->client.waterlevel; + cl.local.viewmodel = to->client.viewmodel; + cl.local.usehull = to->playerstate.usehull; if( FBitSet( to->client.flags, FL_ONGROUND )) { - cl_entity_t *ent = CL_GetEntityByIndex( cl.predicted.lastground ); + cl_entity_t *ent = CL_GetEntityByIndex( cl.local.lastground ); - cl.predicted.onground = cl.predicted.lastground; - cl.predicted.moving = 0; + cl.local.onground = cl.local.lastground; + cl.local.moving = 0; if( ent ) { @@ -1257,42 +1344,42 @@ void CL_PredictMovement( void ) if( VectorLength( delta ) > 0.0f ) { - cl.predicted.correction_time = 0; - cl.predicted.moving = 1; + cls.correction_time = 0; + cl.local.moving = 1; } } } else { - cl.predicted.onground = -1; - cl.predicted.moving = 0; + cl.local.onground = -1; + cl.local.moving = 0; } - if( cl.predicted.correction_time > 0.0 && !cl_nosmooth->value && cl_smoothtime->value ) + if( cls.correction_time > 0.0 && !cl_nosmooth->value && cl_smoothtime->value ) { float d; int i; - cl.predicted.correction_time = cl.predicted.correction_time - host.frametime; + cls.correction_time = cls.correction_time - host.frametime; if( cl_smoothtime->value <= 0 ) Cvar_SetValue( "cl_smoothtime", 0.1 ); - if( cl.predicted.correction_time < 0 ) - cl.predicted.correction_time = 0; + if( cls.correction_time < 0 ) + cls.correction_time = 0; - if( cl_smoothtime->value <= cl.predicted.correction_time ) - cl.predicted.correction_time = cl_smoothtime->value; + if( cl_smoothtime->value <= cls.correction_time ) + cls.correction_time = cl_smoothtime->value; - d = cl.predicted.correction_time / cl_smoothtime->value; + d = cls.correction_time / cl_smoothtime->value; for( i = 0; i < 3; i++ ) { - cl.predicted.origin[i] = cl.predicted.lastorigin[i] + ( cl.predicted.origin[i] - cl.predicted.lastorigin[i] ) * (1.0 - d); + cl.simorg[i] = cl.local.lastorigin[i] + ( cl.simorg[i] - cl.local.lastorigin[i] ) * (1.0 - d); } } - VectorCopy( cl.predicted.origin, cl.predicted.lastorigin ); + VectorCopy( cl.simorg, cl.local.lastorigin ); CL_SetIdealPitch(); } diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index 73745b39..3f53a260 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -22,8 +22,6 @@ GNU General Public License for more details. convar_t *scr_centertime; convar_t *scr_loading; convar_t *scr_download; -convar_t *scr_width; -convar_t *scr_height; convar_t *scr_viewsize; convar_t *cl_testlights; convar_t *cl_allow_levelshots; @@ -100,7 +98,7 @@ void SCR_DrawFPS( int height ) } Con_DrawStringLen( fpsstring, &offset, NULL ); - Con_DrawString( scr_width->value - offset - 4, height, fpsstring, color ); + Con_DrawString( glState.width - offset - 4, height, fpsstring, color ); } /* @@ -144,7 +142,7 @@ void SCR_NetSpeeds( void ) Q_snprintf( msg, sizeof( msg ), "sv fps: ^1%4i min, ^3%4i cur, ^2%4i max\ncl fps: ^1%4i min, ^3%4i cur, ^2%4i max\nGame Time: %02d:%02d\nTotal sended to server: %s\nTotal received from server: %s\n", min_svfps, cur_svfps, max_svfps, min_clfps, cur_clfps, max_clfps, (int)(time / 60.0f ), (int)fmod( time, 60.0f ), Q_memprint( cls.netchan.total_sended ), Q_memprint( cls.netchan.total_received )); - x = scr_width->value - 320; + x = glState.width - 320; y = 384; Con_DrawStringLen( NULL, NULL, &height ); @@ -180,7 +178,7 @@ void SCR_RSpeeds( void ) char *p, *start, *end; rgba_t color; - x = scr_width->value - 340; + x = glState.width - 340; y = 64; Con_DrawStringLen( NULL, NULL, &height ); @@ -288,7 +286,7 @@ void SCR_DrawPlaque( void ) { int levelshot = GL_LoadTexture( cl_levelshot_name->string, NULL, 0, TF_IMAGE, NULL ); GL_SetRenderMode( kRenderNormal ); - R_DrawStretchPic( 0, 0, scr_width->value, scr_height->value, 0, 0, 1, 1, levelshot ); + R_DrawStretchPic( 0, 0, glState.width, glState.height, 0, 0, 1, 1, levelshot ); if( !cl.background ) CL_DrawHUD( CL_LOADING ); } } @@ -346,7 +344,7 @@ SCR_DirtyScreen void SCR_DirtyScreen( void ) { SCR_AddDirtyPoint( 0, 0 ); - SCR_AddDirtyPoint( scr_width->value - 1, scr_height->value - 1 ); + SCR_AddDirtyPoint( glState.width - 1, glState.height - 1 ); } /* @@ -389,10 +387,10 @@ void SCR_TileClear( void ) if( clear.y2 <= clear.y1 ) return; // nothing disturbed - top = cl.refdef.viewport[1]; - bottom = top + cl.refdef.viewport[3] - 1; - left = cl.refdef.viewport[0]; - right = left + cl.refdef.viewport[2] - 1; + top = RI.viewport[1]; + bottom = top + RI.viewport[3] - 1; + left = RI.viewport[0]; + right = left + RI.viewport[2] - 1; if( clear.y1 < top ) { @@ -587,8 +585,8 @@ void SCR_VidInit( void ) memset( &clgame.centerPrint, 0, sizeof( clgame.centerPrint )); // update screen sizes for menu - gameui.globals->scrWidth = scr_width->value; - gameui.globals->scrHeight = scr_height->value; + gameui.globals->scrWidth = glState.width; + gameui.globals->scrHeight = glState.height; SCR_RebuildGammaTable(); VGui_Startup (); diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 2317bcb2..4d294523 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -2517,7 +2517,7 @@ void CL_UpdateFlashlight( cl_entity_t *pEnt ) if(( pEnt->index - 1 ) == cl.playernum ) { // get the predicted angles - AngleVectors( cl.refdef.cl_viewangles, forward, NULL, NULL ); + AngleVectors( cl.viewangles, forward, NULL, NULL ); } else { @@ -2534,7 +2534,7 @@ void CL_UpdateFlashlight( cl_entity_t *pEnt ) VectorClear( view_ofs ); if(( pEnt->index - 1 ) == cl.playernum ) - VectorCopy( cl.refdef.viewheight, view_ofs ); + VectorCopy( cl.viewheight, view_ofs ); VectorAdd( pEnt->origin, view_ofs, vecSrc ); VectorMA( vecSrc, FLASHLIGHT_DISTANCE, forward, vecEnd ); @@ -2584,7 +2584,7 @@ void CL_TestLights( void ) f = 64 * ( i / 4) + 128; for( j = 0; j < 3; j++ ) - dl->origin[j] = cl.refdef.vieworg[j] + cl.refdef.forward[j] * f + cl.refdef.right[j] * r; + dl->origin[j] = RI.vieworg[j] + RI.vforward[j] * f + RI.vright[j] * r; dl->color.r = ((((i % 6) + 1) & 1)>>0) * 255; dl->color.g = ((((i % 6) + 1) & 2)>>1) * 255; diff --git a/engine/client/cl_video.c b/engine/client/cl_video.c index 60953426..81e163b1 100644 --- a/engine/client/cl_video.c +++ b/engine/client/cl_video.c @@ -205,7 +205,7 @@ qboolean SCR_DrawCinematic( void ) redraw = true; } - R_DrawStretchRaw( 0, 0, scr_width->value, scr_height->value, xres, yres, frame, redraw ); + R_DrawStretchRaw( 0, 0, glState.width, glState.height, xres, yres, frame, redraw ); return true; } diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index a9827777..7ca24243 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -20,6 +20,123 @@ GNU General Public License for more details. #include "gl_local.h" #include "vgui_draw.h" +/* +=============== +V_CalcViewRect + +calc frame rectangle (Quake1 style) +=============== +*/ +void V_CalcViewRect( void ) +{ + int size, sb_lines; + + if( scr_viewsize->value >= 120.0f ) + sb_lines = 0; // no status bar at all + else if( scr_viewsize->value >= 110.0f ) + sb_lines = 24; // no inventory + else sb_lines = 48; + + size = Q_min( scr_viewsize->value, 100 ); + + clgame.viewport[2] = glState.width * size / 100; + clgame.viewport[3] = glState.height * size / 100; + + if( clgame.viewport[3] > glState.height - sb_lines ) + clgame.viewport[3] = glState.height - sb_lines; + if( clgame.viewport[3] > glState.height ) + clgame.viewport[3] = glState.height; + + clgame.viewport[0] = ( glState.width - clgame.viewport[2] ) / 2; + clgame.viewport[1] = ( glState.height - sb_lines - clgame.viewport[3] ) / 2; + +} + +/* +=============== +V_SetupViewModel +=============== +*/ +void V_SetupViewModel( void ) +{ + cl_entity_t *view = &clgame.viewent; + + // setup the viewent variables + view->model = Mod_Handle( cl.local.viewmodel ); + view->curstate.modelindex = cl.local.viewmodel; + view->curstate.number = cl.playernum + 1; + view->index = cl.playernum + 1; + view->curstate.colormap = 0; + view->curstate.frame = 0; +} + +/* +=============== +V_SetRefParams +=============== +*/ +void V_SetRefParams( ref_params_t *fd ) +{ + memset( fd, 0, sizeof( ref_params_t )); + + // probably this is not needs + VectorCopy( RI.vieworg, fd->vieworg ); + VectorCopy( RI.viewangles, fd->viewangles ); + + fd->frametime = host.frametime; + fd->time = cl.time; + + fd->intermission = cl.intermission; // Quake Remake compatibility + fd->paused = (cl.paused != 0); + fd->spectator = (cls.spectator != 0); + fd->onground = (cl.local.onground != -1); + fd->waterlevel = cl.local.waterlevel; + + VectorCopy( cl.simvel, fd->simvel ); + VectorCopy( cl.simorg, fd->simorg ); + + VectorCopy( cl.viewheight, fd->viewheight ); + fd->idealpitch = cl.local.idealpitch; + + VectorCopy( cl.viewangles, fd->cl_viewangles ); + fd->health = cl.local.health; + VectorCopy( cl.crosshairangle, fd->crosshairangle ); + fd->viewsize = scr_viewsize->value; + + VectorCopy( cl.punchangle, fd->punchangle ); + fd->maxclients = cl.maxclients; + fd->viewentity = cl.viewentity; + fd->playernum = cl.playernum; + fd->max_entities = clgame.maxEntities; + fd->demoplayback = cls.demoplayback; + fd->hardware = 1; // OpenGL + + if( cl.first_frame ) fd->smoothing = true; // NOTE: currently this used to prevent ugly un-duck effect while level is changed + else fd->smoothing = cl.local.pushmsec; // enable smoothing in multiplayer by server request (AMX uses) + + // get pointers to movement vars and user cmd + fd->movevars = &clgame.movevars; + fd->cmd = cl.cmd; + + // setup viewport + fd->viewport[0] = clgame.viewport[0]; + fd->viewport[1] = clgame.viewport[1]; + fd->viewport[2] = clgame.viewport[2]; + fd->viewport[3] = clgame.viewport[3]; + + fd->onlyClientDraw = 0; // reset clientdraw + fd->nextView = 0; // reset nextview + + // Xash3D extension. FIXME: it's needs to be removed... + + // calc FOV + fd->fov_x = bound( 1.0f, cl.local.scr_fov, 179.0f ); // this is a final fov value + fd->fov_y = V_CalcFov( &fd->fov_x, clgame.viewport[2], clgame.viewport[3] ); + + // adjust FOV for widescreen + if( glState.wideScreen && r_adjust_fov->value ) + V_AdjustFov( &fd->fov_x, &fd->fov_y, clgame.viewport[2], clgame.viewport[3], false ); +} /* =============== @@ -28,14 +145,15 @@ V_MergeOverviewRefdef merge refdef with overview settings =============== */ -void V_MergeOverviewRefdef( void ) +void V_RefParamsApplyOverview( ref_params_t *fd ) { ref_overview_t *ov = &clgame.overView; float aspect; float size_x, size_y; vec2_t mins, maxs; - if( !gl_overview->value ) return; + if( !CL_IsDevOverviewMode( )) + return; // NOTE: Xash3D may use 16:9 or 16:10 aspects aspect = (float)glState.width / (float)glState.height; @@ -55,123 +173,40 @@ void V_MergeOverviewRefdef( void ) ov->flZoom, ov->origin[0], ov->origin[1], ov->origin[2], ov->zNear, ov->zFar, ov->rotated ); } - VectorCopy( ov->origin, cl.refdef.vieworg ); - cl.refdef.vieworg[2] = ov->zFar + ov->zNear; - Vector2Copy( cl.refdef.vieworg, mins ); - Vector2Copy( cl.refdef.vieworg, maxs ); + VectorCopy( ov->origin, fd->vieworg ); + fd->vieworg[2] = ov->zFar + ov->zNear; + Vector2Copy( fd->vieworg, mins ); + Vector2Copy( fd->vieworg, maxs ); mins[!ov->rotated] += ov->xLeft; maxs[!ov->rotated] += ov->xRight; mins[ov->rotated] += ov->xTop; maxs[ov->rotated] += ov->xBottom; - cl.refdef.viewangles[0] = 90.0f; - cl.refdef.viewangles[1] = 90.0f; - cl.refdef.viewangles[2] = (ov->rotated) ? (ov->flZoom < 0.0f) ? 180.0f : 0.0f : (ov->flZoom < 0.0f) ? -90.0f : 90.0f; + fd->viewangles[0] = 90.0f; + fd->viewangles[1] = 90.0f; + fd->viewangles[2] = (ov->rotated) ? (ov->flZoom < 0.0f) ? 180.0f : 0.0f : (ov->flZoom < 0.0f) ? -90.0f : 90.0f; Mod_SetOrthoBounds( mins, maxs ); } /* -=============== -V_CalcViewRect - -calc frame rectangle (Quake1 style) -=============== +============= +V_GetRefParams +============= */ -void V_CalcViewRect( void ) +void V_GetRefParams( ref_params_t *fd ) { - int size, sb_lines; + // part1: deniable updates + VectorCopy( fd->simvel, cl.simvel ); + VectorCopy( fd->simorg, cl.simorg ); + VectorCopy( fd->punchangle, cl.punchangle ); + VectorCopy( fd->viewheight, cl.viewheight ); - if( scr_viewsize->value >= 120 ) - sb_lines = 0; // no status bar at all - else if( scr_viewsize->value >= 110 ) - sb_lines = 24; // no inventory - else sb_lines = 48; - - size = Q_min( scr_viewsize->value, 100 ); - - cl.refdef.viewport[2] = scr_width->value * size / 100; - cl.refdef.viewport[3] = scr_height->value * size / 100; - - if( cl.refdef.viewport[3] > scr_height->value - sb_lines ) - cl.refdef.viewport[3] = scr_height->value - sb_lines; - if( cl.refdef.viewport[3] > scr_height->value ) - cl.refdef.viewport[3] = scr_height->value; - - cl.refdef.viewport[0] = ( scr_width->value - cl.refdef.viewport[2] ) / 2; - cl.refdef.viewport[1] = ( scr_height->value - sb_lines - cl.refdef.viewport[3] ) / 2; - -} - -/* -=============== -V_SetupRefDef - -update refdef values each frame -=============== -*/ -void V_SetupRefDef( void ) -{ - cl_entity_t *clent; - - // compute viewport rectangle - V_CalcViewRect(); - - clent = CL_GetLocalPlayer (); - - clgame.entities->curstate.scale = clgame.movevars.waveHeight; - - cl.refdef.movevars = &clgame.movevars; - cl.refdef.health = cl.frame.client.health; - cl.refdef.playernum = cl.playernum; - cl.refdef.max_entities = clgame.maxEntities; - cl.refdef.maxclients = cl.maxclients; - cl.refdef.time = cl.time; - cl.refdef.frametime = cl.time - cl.oldtime; - cl.refdef.demoplayback = cls.demoplayback; - cl.refdef.viewsize = scr_viewsize->value; - cl.refdef.onlyClientDraw = 0; // reset clientdraw - cl.refdef.hardware = true; // always true - cl.refdef.spectator = (cls.spectator != 0); - cl.refdef.smoothing = cl.first_frame; // NOTE: currently this used to prevent ugly un-duck effect while level is changed - cl.scr_fov = bound( 1.0f, cl.scr_fov, 179.0f ); - cl.refdef.nextView = 0; - - // calc FOV - cl.refdef.fov_x = cl.scr_fov; // this is a final fov value - cl.refdef.fov_y = V_CalcFov( &cl.refdef.fov_x, cl.refdef.viewport[2], cl.refdef.viewport[3] ); - - // adjust FOV for widescreen - if( glState.wideScreen && r_adjust_fov->value ) - V_AdjustFov( &cl.refdef.fov_x, &cl.refdef.fov_y, cl.refdef.viewport[2], cl.refdef.viewport[3], false ); - - if( CL_IsPredicted( ) && !cl.first_frame ) - { - VectorCopy( cl.predicted.origin, cl.refdef.simorg ); - VectorCopy( cl.predicted.velocity, cl.refdef.simvel ); - VectorCopy( cl.predicted.viewofs, cl.refdef.viewheight ); - VectorCopy( cl.predicted.punchangle, cl.refdef.punchangle ); - cl.refdef.onground = ( cl.predicted.onground == -1 ) ? false : true; - cl.refdef.waterlevel = cl.predicted.waterlevel; - } - else - { - VectorCopy( cl.frame.client.origin, cl.refdef.simorg ); - VectorCopy( cl.frame.client.view_ofs, cl.refdef.viewheight ); - VectorCopy( cl.frame.client.velocity, cl.refdef.simvel ); - VectorCopy( cl.frame.client.punchangle, cl.refdef.punchangle ); - cl.refdef.onground = (cl.frame.client.flags & FL_ONGROUND) ? 1 : 0; - cl.refdef.waterlevel = cl.frame.client.waterlevel; - } - - // setup the viewent variables - if( cl_lw->value ) clgame.viewent.curstate.modelindex = cl.predicted.viewmodel; - else clgame.viewent.curstate.modelindex = cl.frame.client.viewmodel; - clgame.viewent.model = Mod_Handle( clgame.viewent.curstate.modelindex ); - clgame.viewent.curstate.number = cl.playernum + 1; - clgame.viewent.curstate.entityType = ET_NORMAL; - clgame.viewent.index = cl.playernum + 1; + // part2: really used updates + VectorCopy( fd->crosshairangle, cl.crosshairangle ); + VectorCopy( fd->cl_viewangles, cl.viewangles ); + cl.intermission = fd->intermission; // Quake Remake compatibility } /* @@ -203,7 +238,7 @@ qboolean V_PreRender( void ) return false; } - R_BeginFrame( !cl.refdef.paused ); + R_BeginFrame( !cl.paused ); return true; } @@ -218,34 +253,50 @@ V_RenderView */ void V_RenderView( void ) { + ref_params_t rp; + int viewnum = 0; + if( !cl.video_prepped || ( UI_IsVisible() && !cl.background )) return; // still loading - if( cl.frame.valid && ( cl.force_refdef || !cl.refdef.paused )) + if( cl.frame.valid && ( cl.force_refdef || !cl.paused )) { cl.force_refdef = false; R_ClearScene (); CL_AddEntities (); - V_SetupRefDef (); } + V_CalcViewRect (); // compute viewport rectangle + V_SetRefParams( &rp ); + V_SetupViewModel (); R_Set2DMode( false ); - SCR_AddDirtyPoint( 0, 0 ); - SCR_AddDirtyPoint( scr_width->value - 1, scr_height->value - 1 ); + SCR_AddDirtyPoint( 0, 0 ); + SCR_AddDirtyPoint( clgame.viewport[2] - 1, clgame.viewport[3] - 1 ); + GL_BackendStartFrame (); tr.framecount++; // g-cont. keep actual frame for all viewpasses do { - clgame.dllFuncs.pfnCalcRefdef( &cl.refdef ); - V_MergeOverviewRefdef(); - R_RenderFrame( &cl.refdef, true ); - cl.refdef.onlyClientDraw = false; - } while( cl.refdef.nextView ); + clgame.dllFuncs.pfnCalcRefdef( &rp ); + V_RefParamsApplyOverview( &rp ); + V_GetRefParams( &rp ); + + if ( viewnum == 0 && rp.onlyClientDraw ) + { + pglClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); + pglClear( GL_COLOR_BUFFER_BIT ); + } + + R_RenderFrame( &rp, true, cl.local.scr_fov ); + viewnum++; + + } while( rp.nextView ); // draw debug triangles on a server SV_DrawDebugTriangles (); + GL_BackendEndFrame (); } /* diff --git a/engine/client/client.h b/engine/client/client.h index 871aa481..e1fcc7cf 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -24,6 +24,7 @@ GNU General Public License for more details. #include "mod_local.h" #include "pm_defs.h" #include "pm_movevars.h" +#include "ref_params.h" #include "render_api.h" #include "cdll_exp.h" #include "screenfade.h" @@ -101,27 +102,45 @@ extern int CL_UPDATE_BACKUP; #define SIGNONS 2 // signon messages to receive before connected #define INVALID_HANDLE 0xFFFF // for XashXT cache system +#define MIN_UPDATERATE 10.0f +#define MAX_UPDATERATE 102.0f + +#define MIN_EX_INTERP 50.0f +#define MAX_EX_INTERP 100.0f + #define cl_serverframetime() (cl.mtime[0] - cl.mtime[1]) #define cl_clientframetime() (cl.time - cl.oldtime) typedef struct { - vec3_t origin; // generated by CL_PredictMovement - vec3_t viewofs; - vec3_t velocity; - vec3_t punchangle; - vec3_t origins[CMD_BACKUP]; - vec3_t error; + // got from prediction system + vec3_t predicted_origins[CMD_BACKUP]; + vec3_t prediction_error; vec3_t lastorigin; - double correction_time; + int lastground; + + // interp info + float interp_amount; + + // misc local info + qboolean thirdperson; + float idealpitch; int viewmodel; int health; // client health int onground; + int light_level; int waterlevel; int usehull; int moving; - int lastground; -} cl_predicted_data_t; // data we got from prediction system + int pushmsec; + int weapons; + float maxspeed; + float scr_fov; + + // weapon predict stuff + int weaponsequence; + float weaponstarttime; +} cl_local_data_t; // the client_t structure is wiped completely at every // server map change @@ -139,6 +158,7 @@ typedef struct qboolean video_prepped; // false if on new level or new ref dll qboolean audio_prepped; // false if on new level or new snd dll qboolean force_refdef; // vid has changed, so we can't use a paused refdef + qboolean paused; int delta_sequence; // acknowledged sequence number @@ -148,20 +168,17 @@ typedef struct int last_incoming_sequence; qboolean send_reply; - qboolean thirdperson; qboolean background; // not real game, just a background qboolean first_frame; // first rendering frame qboolean proxy_redirect; // spectator stuff uint checksum; // for catching cheater maps - client_data_t data; // some clientdata holds - frame_t frame; // received from server - frame_t frames[MULTIPLAYER_BACKUP]; // alloced on svc_serverdata - runcmd_t commands[MULTIPLAYER_BACKUP]; // each mesage will send several old cmds - local_state_t predict[MULTIPLAYER_BACKUP]; // local client state + frame_t frames[MULTIPLAYER_BACKUP]; // alloced on svc_serverdata + runcmd_t commands[MULTIPLAYER_BACKUP]; // each mesage will send several old cmds + local_state_t predicted_frames[MULTIPLAYER_BACKUP]; // local client state double time; // this is the time value that the client // is rendering at. always <= cls.realtime @@ -172,14 +189,27 @@ typedef struct float lerpFrac; // interpolation value float lerpBack; // invert interpolation value float timedelta; // floating delta between two updates - ref_params_t refdef; // shared refdef char serverinfo[MAX_SERVERINFO_STRING]; - player_info_t players[MAX_CLIENTS]; + player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself event_state_t events; - // predicting stuff - cl_predicted_data_t predicted; // generated from CL_PredictMovement + // predicting stuff but not only... + cl_local_data_t local; + + // player final info + usercmd_t *cmd; // cl.commands[outgoing_sequence].cmd + int viewentity; + vec3_t viewangles; + vec3_t viewheight; + vec3_t punchangle; + + int intermission; // don't change view angle, full screen, et + vec3_t crosshairangle; + + // predicted origin and velocity + vec3_t simorg; + vec3_t simvel; // server state information int playernum; @@ -196,11 +226,6 @@ typedef struct cl_entity_t *world; model_t *worldmodel; // pointer to world - - // weapon predict stuff - float scr_fov; - float weaponstarttime; - int weaponsequence; } client_t; /* @@ -298,12 +323,11 @@ typedef struct typedef struct cl_predicted_player_s { - int flags; int movetype; int solid; int usehull; qboolean active; - vec3_t origin; // predicted origin + vec3_t origin; // interpolated origin vec3_t angles; } predicted_player_t; @@ -411,6 +435,8 @@ typedef struct model_t sprites[MAX_IMAGES]; // client spritetextures int load_sequence; // for unloading unneeded sprites + int viewport[4]; // viewport sizes + client_draw_t ds; // draw2d stuff (hud, weaponmenu etc) screenfade_t fade; // screen fade screen_shake_t shake; // screen shake @@ -499,6 +525,7 @@ typedef struct float nextcmdtime; // when can we send the next command packet? int lastoutgoingcommand; // sequence number of last outgoing command + int lastupdate_sequence; // prediction stuff // internal images int fillImage; // used for emulate FillRGBA to avoid wrong draw-sort @@ -517,6 +544,7 @@ typedef struct entity_state_t *packet_entities; // [num_client_entities] predicted_player_t predicted_players[MAX_CLIENTS]; + double correction_time; scrshot_t scrshot_request; // request for screen shot scrshot_t scrshot_action; // in-action @@ -636,6 +664,7 @@ void CL_Disconnect_f( void ); void CL_ProcessFile( qboolean successfully_received, const char *filename ); void CL_WriteUsercmd( sizebuf_t *msg, int from, int to ); void CL_GetChallengePacket( void ); +int CL_IsDevOverviewMode( void ); void CL_PingServers_f( void ); void CL_SignonReply( void ); void CL_ClearState( void ); @@ -755,7 +784,6 @@ void V_Shutdown( void ); qboolean V_PreRender( void ); void V_PostRender( void ); void V_RenderView( void ); -void V_SetupRefDef( void ); // // cl_pmove.c @@ -763,7 +791,7 @@ void V_SetupRefDef( void ); void CL_SetSolidEntities( void ); void CL_SetSolidPlayers( int playernum ); void CL_InitClientMove( void ); -void CL_PredictMovement( void ); +void CL_PredictMovement( qboolean repredicting ); void CL_CheckPredictionError( void ); qboolean CL_IsPredicted( void ); int CL_TruePointContents( const vec3_t p ); @@ -772,6 +800,8 @@ int CL_WaterEntity( const float *rgflPos ); cl_entity_t *CL_GetWaterEntity( const float *rgflPos ); void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, qboolean runfuncs, double time ); pmtrace_t CL_TraceLine( vec3_t start, vec3_t end, int flags ); +void CL_SetLastUpdate( void ); +void CL_RedoPrediction( void ); void CL_ClearPhysEnts( void ); void CL_PushPMStates( void ); void CL_PopPMStates( void ); @@ -790,6 +820,7 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType ); void CL_UpdateStudioVars( cl_entity_t *ent, entity_state_t *newstate, qboolean noInterp ); qboolean CL_GetEntitySpatialization( struct channel_s *ch ); qboolean CL_GetMovieSpatialization( struct rawchan_s *ch ); +void CL_ComputePlayerOrigin( cl_entity_t *clent ); void CL_UpdateEntityFields( cl_entity_t *ent ); qboolean CL_IsPlayerIndex( int idx ); void CL_SetIdealPitch( void ); @@ -841,7 +872,6 @@ void CL_RunLightStyles( void ); // extern convar_t *con_fontsize; qboolean Con_Visible( void ); -void Con_Init( void ); void Con_VidInit( void ); void Con_Shutdown( void ); void Con_ToggleConsole_f( void ); @@ -881,7 +911,7 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa void S_FadeClientVolume( float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds ); void S_FadeMusicVolume( float fadePercent ); void S_StartLocalSound( const char *name, float volume, qboolean reliable ); -void S_RenderFrame( struct ref_params_s *fd ); +void SND_UpdateSound( void ); void S_ExtraUpdate( void ); // diff --git a/engine/client/gl_backend.c b/engine/client/gl_backend.c index ca78dd21..29eba38f 100644 --- a/engine/client/gl_backend.c +++ b/engine/client/gl_backend.c @@ -48,11 +48,9 @@ qboolean R_SpeedsMessage( char *out, size_t size ) GL_BackendStartFrame ============== */ -void GL_BackendStartFrame( const ref_params_t *fd ) +void GL_BackendStartFrame( void ) { - if( !fd->nextView ) r_speeds_msg[0] = '\0'; - - if( !RI.drawWorld ) R_Set2DMode( false ); + r_speeds_msg[0] = '\0'; } /* @@ -60,12 +58,9 @@ void GL_BackendStartFrame( const ref_params_t *fd ) GL_BackendEndFrame ============== */ -void GL_BackendEndFrame( const ref_params_t *fd ) +void GL_BackendEndFrame( void ) { - // go into 2D mode (in case we draw PlayerSetup between two 2d calls) - if( !RI.drawWorld ) R_Set2DMode( true ); - - if( r_speeds->value <= 0 || !RI.drawWorld || fd->nextView ) + if( r_speeds->value <= 0 || !RI.drawWorld ) return; switch( (int)r_speeds->value ) @@ -608,7 +603,7 @@ qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qbo r_side = Mem_Alloc( r_temppool, sizeof( rgbdata_t )); // use client vieworg - if( !vieworg ) vieworg = cl.refdef.vieworg; + if( !vieworg ) vieworg = RI.vieworg; for( i = 0; i < 6; i++ ) { diff --git a/engine/client/gl_beams.c b/engine/client/gl_beams.c index 9cf8ef71..b30c1d87 100644 --- a/engine/client/gl_beams.c +++ b/engine/client/gl_beams.c @@ -109,7 +109,7 @@ static qboolean ComputeBeamEntPosition( int beamEnt, vec3_t pt ) return false; } - if(( pEnt->index - 1 ) == cl.playernum && !cl.thirdperson ) + if(( pEnt->index - 1 ) == cl.playernum && !cl.local.thirdperson ) { // if we view beam at firstperson use viewmodel instead pEnt = &clgame.viewent; @@ -1230,13 +1230,13 @@ void CL_UpdateBeam( BEAM *pbeam, float frametime ) pbeam->freq += frametime; // Generate fractal noise - if( CL_IsInGame() && !cl.refdef.paused ) + if( CL_IsInGame() && !cl.paused ) { rgNoise[0] = 0; rgNoise[NOISE_DIVISIONS] = 0; } - if( pbeam->amplitude != 0 && CL_IsInGame() && !cl.refdef.paused ) + if( pbeam->amplitude != 0 && CL_IsInGame() && !cl.paused ) { if( pbeam->flags & FBEAM_SINENOISE ) { diff --git a/engine/client/gl_cull.c b/engine/client/gl_cull.c index 76f85ded..c19bb9cf 100644 --- a/engine/client/gl_cull.c +++ b/engine/client/gl_cull.c @@ -134,7 +134,7 @@ int R_CullModel( cl_entity_t *e, vec3_t origin, vec3_t mins, vec3_t maxs, float if( e->curstate.effects & EF_REFLECTONLY && !( RI.params & RP_MIRRORVIEW )) return 1; - if( RP_LOCALCLIENT( e ) && !RI.thirdPerson && cl.refdef.viewentity == ( cl.playernum + 1 )) + if( RP_LOCALCLIENT( e ) && !RI.thirdPerson && cl.viewentity == ( cl.playernum + 1 )) { if(!( RI.params & RP_MIRRORVIEW )) return 1; diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index 19aee4e0..cb39f962 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -19,7 +19,6 @@ GNU General Public License for more details. #include "gl_export.h" #include "com_model.h" #include "cl_entity.h" -#include "ref_params.h" #include "render_api.h" #include "protocol.h" #include "dlight.h" @@ -103,9 +102,10 @@ typedef struct qboolean drawWorld; // ignore world for drawing PlayerModel qboolean thirdPerson; // thirdperson camera is enabled qboolean isSkyVisible; // sky is visible + qboolean onlyClientDraw; // disabled by client request qboolean drawOrtho; // draw world as orthogonal projection - ref_params_t refdef; // actual refdef + float fov_x, fov_y; // current view fov cl_entity_t *currententity; model_t *currentmodel; @@ -118,6 +118,7 @@ typedef struct mleaf_t *oldviewleaf; vec3_t pvsorigin; vec3_t vieworg; // locked vieworigin + vec3_t viewangles; vec3_t vforward; vec3_t vright; vec3_t vup; @@ -236,7 +237,6 @@ typedef struct } ref_speeds_t; extern ref_speeds_t r_stats; -extern ref_params_t r_lastRefdef; extern ref_instance_t RI; extern ref_globals_t tr; @@ -255,8 +255,8 @@ extern struct particle_s *cl_free_trails; // // gl_backend.c // -void GL_BackendStartFrame( const ref_params_t *fd ); -void GL_BackendEndFrame( const ref_params_t *fd ); +void GL_BackendStartFrame( void ); +void GL_BackendEndFrame( void ); void GL_CleanUpTextureUnits( int last ); void GL_Bind( GLint tmu, GLenum texnum ); void GL_MultiTexCoord2f( GLenum texture, GLfloat s, GLfloat t ); @@ -327,7 +327,7 @@ void R_ShutdownImages( void ); void R_BeginDrawMirror( msurface_t *fa ); void R_EndDrawMirror( void ); void R_DrawMirrors( void ); -void R_FindMirrors( const ref_params_t *fd ); +void R_FindMirrors( void ); // // gl_refrag.c @@ -351,7 +351,7 @@ int R_CountDlights( void ); // void R_ClearScene( void ); void R_LoadIdentity( void ); -void R_RenderScene( const ref_params_t *fd ); +void R_RenderScene( void ); void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ); void R_TranslateForEntity( cl_entity_t *e ); void R_RotateForEntity( cl_entity_t *e ); @@ -455,7 +455,7 @@ qboolean VID_ScreenShot( const char *filename, int shot_type ); qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot ); void VID_RestoreGamma( void ); void R_BeginFrame( qboolean clearScene ); -void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld ); +void R_RenderFrame( const struct ref_params_s *fd, qboolean drawWorld, float fov ); void R_EndFrame( void ); void R_ClearScene( void ); void R_GetTextureParms( int *w, int *h, int texnum ); diff --git a/engine/client/gl_mirror.c b/engine/client/gl_mirror.c index 43e83f46..f226eaa4 100644 --- a/engine/client/gl_mirror.c +++ b/engine/client/gl_mirror.c @@ -271,10 +271,10 @@ void R_DrawMirrors( void ) RI.frustum[5].signbits = SignbitsForPlane( RI.frustum[5].normal ); RI.frustum[5].type = PLANE_NONAXIAL; - RI.refdef.viewangles[0] = anglemod( angles[0] ); - RI.refdef.viewangles[1] = anglemod( angles[1] ); - RI.refdef.viewangles[2] = anglemod( angles[2] ); - VectorCopy( origin, RI.refdef.vieworg ); + RI.viewangles[0] = anglemod( angles[0] ); + RI.viewangles[1] = anglemod( angles[1] ); + RI.viewangles[2] = anglemod( angles[2] ); + VectorCopy( origin, RI.vieworg ); VectorCopy( origin, RI.cullorigin ); // put pvsorigin before the mirror plane to avoid get full visibility on world mirrors @@ -305,7 +305,7 @@ void R_DrawMirrors( void ) } tr.framecount++; - R_RenderScene( &RI.refdef ); + R_RenderScene(); r_stats.c_mirror_passes++; es->mirrortexturenum = R_AllocateMirrorTexture(); @@ -584,51 +584,16 @@ R_FindMirrors Build mirror chains for this frame ================ */ -void R_FindMirrors( const ref_params_t *fd ) +void R_FindMirrors( void ) { - vec3_t viewOrg, viewAng; - - if( !world.has_mirrors || RI.drawOrtho || !RI.drawWorld || RI.refdef.onlyClientDraw || !cl.worldmodel ) + if( !world.has_mirrors || RI.drawOrtho || !RI.drawWorld || RI.onlyClientDraw || !cl.worldmodel ) return; - RI.refdef = *fd; + // NOTE: we already has initial params at this point like vieworg, viewangles + // all other will be sets into R_SetupFrustum - // build the transformation matrix for the given view angles - if( cl.thirdperson ) - { - vec3_t cam_ofs, vpn; - - clgame.dllFuncs.CL_CameraOffset( cam_ofs ); - - viewAng[PITCH] = cam_ofs[PITCH]; - viewAng[YAW] = cam_ofs[YAW]; - viewAng[ROLL] = 0; - - AngleVectors( viewAng, vpn, NULL, NULL ); - VectorMA( RI.refdef.vieworg, -cam_ofs[ROLL], vpn, viewOrg ); - } - else - { - VectorCopy( RI.refdef.vieworg, viewOrg ); - VectorCopy( RI.refdef.viewangles, viewAng ); - } - - // build the transformation matrix for the given view angles - VectorCopy( viewOrg, RI.vieworg ); - AngleVectors( viewAng, RI.vforward, RI.vright, RI.vup ); - - VectorCopy( RI.vieworg, RI.pvsorigin ); - - if( !r_lockcull->value ) - { - VectorCopy( RI.vieworg, RI.cullorigin ); - VectorCopy( RI.vforward, RI.cull_vforward ); - VectorCopy( RI.vright, RI.cull_vright ); - VectorCopy( RI.vup, RI.cull_vup ); - } - - R_FindViewLeaf(); - R_SetupFrustum(); + R_SetupFrustum (); + R_FindViewLeaf (); R_MarkLeaves (); VectorCopy( RI.cullorigin, tr.modelorg ); diff --git a/engine/client/gl_rlight.c b/engine/client/gl_rlight.c index 7414cd14..286a949e 100644 --- a/engine/client/gl_rlight.c +++ b/engine/client/gl_rlight.c @@ -37,6 +37,7 @@ void CL_RunLightStyles( void ) { int i, k, flight, clight; float l, c, lerpfrac, backlerp; + float frametime = (cl.time - cl.oldtime); float scale; lightstyle_t *ls; @@ -56,8 +57,8 @@ void CL_RunLightStyles( void ) continue; } - if( !RI.refdef.paused && RI.refdef.frametime <= 0.1f ) - ls->time += RI.refdef.frametime; // evaluate local time + if( !cl.paused && frametime <= 0.1f ) + ls->time += frametime; // evaluate local time flight = (int)Q_floor( ls->time * 10 ); clight = (int)Q_ceil( ls->time * 10 ); @@ -337,20 +338,12 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig model_t *pmodel; mnode_t *pnodes; - if( !cl.refdef.movevars ) - { - ambientLight->r = 255; - ambientLight->g = 255; - ambientLight->b = 255; - return; - } - // set to full bright if no light data if( !cl.worldmodel || !cl.worldmodel->lightdata ) { - ambientLight->r = TextureToTexGamma( cl.refdef.movevars->skycolor_r ); - ambientLight->g = TextureToTexGamma( cl.refdef.movevars->skycolor_g ); - ambientLight->b = TextureToTexGamma( cl.refdef.movevars->skycolor_b ); + ambientLight->r = TextureToTexGamma( clgame.movevars.skycolor_r ); + ambientLight->g = TextureToTexGamma( clgame.movevars.skycolor_g ); + ambientLight->b = TextureToTexGamma( clgame.movevars.skycolor_b ); return; } diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index 27da51ad..3022cbc8 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -27,8 +27,7 @@ GNU General Public License for more details. msurface_t *r_debug_surface; const char *r_debug_hitbox; float gldepthmin, gldepthmax; -ref_params_t r_lastRefdef; -ref_instance_t RI, prevRI; +ref_instance_t RI; static int R_RankForRenderMode( cl_entity_t *ent ) { @@ -271,16 +270,16 @@ int R_ComputeFxBlend( cl_entity_t *e ) switch( e->curstate.renderfx ) { case kRenderFxPulseSlowWide: - blend = renderAmt + 0x40 * sin( RI.refdef.time * 2 + offset ); + blend = renderAmt + 0x40 * sin( cl.time * 2 + offset ); break; case kRenderFxPulseFastWide: - blend = renderAmt + 0x40 * sin( RI.refdef.time * 8 + offset ); + blend = renderAmt + 0x40 * sin( cl.time * 8 + offset ); break; case kRenderFxPulseSlow: - blend = renderAmt + 0x10 * sin( RI.refdef.time * 2 + offset ); + blend = renderAmt + 0x10 * sin( cl.time * 2 + offset ); break; case kRenderFxPulseFast: - blend = renderAmt + 0x10 * sin( RI.refdef.time * 8 + offset ); + blend = renderAmt + 0x10 * sin( cl.time * 8 + offset ); break; // JAY: HACK for now -- not time based case kRenderFxFadeSlow: @@ -308,35 +307,35 @@ int R_ComputeFxBlend( cl_entity_t *e ) blend = renderAmt; break; case kRenderFxStrobeSlow: - blend = 20 * sin( RI.refdef.time * 4 + offset ); + blend = 20 * sin( cl.time * 4 + offset ); if( blend < 0 ) blend = 0; else blend = renderAmt; break; case kRenderFxStrobeFast: - blend = 20 * sin( RI.refdef.time * 16 + offset ); + blend = 20 * sin( cl.time * 16 + offset ); if( blend < 0 ) blend = 0; else blend = renderAmt; break; case kRenderFxStrobeFaster: - blend = 20 * sin( RI.refdef.time * 36 + offset ); + blend = 20 * sin( cl.time * 36 + offset ); if( blend < 0 ) blend = 0; else blend = renderAmt; break; case kRenderFxFlickerSlow: - blend = 20 * (sin( RI.refdef.time * 2 ) + sin( RI.refdef.time * 17 + offset )); + blend = 20 * (sin( cl.time * 2 ) + sin( cl.time * 17 + offset )); if( blend < 0 ) blend = 0; else blend = renderAmt; break; case kRenderFxFlickerFast: - blend = 20 * (sin( RI.refdef.time * 16 ) + sin( RI.refdef.time * 23 + offset )); + blend = 20 * (sin( cl.time * 16 ) + sin( cl.time * 23 + offset )); if( blend < 0 ) blend = 0; else blend = renderAmt; break; case kRenderFxHologram: case kRenderFxDistort: VectorCopy( e->origin, tmp ); - VectorSubtract( tmp, RI.refdef.vieworg, tmp ); - dist = DotProduct( tmp, RI.refdef.forward ); + VectorSubtract( tmp, RI.vieworg, tmp ); + dist = DotProduct( tmp, RI.vforward ); // Turn off distance fade if( e->curstate.renderfx == kRenderFxDistort ) @@ -515,7 +514,7 @@ R_GetFarClip static float R_GetFarClip( void ) { if( cl.worldmodel && RI.drawWorld ) - return cl.refdef.movevars->zmax * 1.5f; + return clgame.movevars.zmax * 1.73f; return 2048.0f; } @@ -578,12 +577,23 @@ void R_SetupFrustum( void ) vec3_t farPoint; int i; - // 0 - left - // 1 - right - // 2 - down - // 3 - up - // 4 - farclip - // 5 - nearclip + // first we need to compute FOV and other things that needs for frustum properly work + RI.fov_y = V_CalcFov( &RI.fov_x, RI.viewport[2], RI.viewport[3] ); + + // adjust FOV for widescreen + if( glState.wideScreen && RI.drawWorld && r_adjust_fov->value ) + V_AdjustFov( &RI.fov_x, &RI.fov_y, RI.viewport[2], RI.viewport[3], false ); + + // build the transformation matrix for the given view angles + AngleVectors( RI.viewangles, RI.vforward, RI.vright, RI.vup ); + + if( !r_lockcull->value ) + { + VectorCopy( RI.vieworg, RI.cullorigin ); + VectorCopy( RI.vforward, RI.cull_vforward ); + VectorCopy( RI.vright, RI.cull_vright ); + VectorCopy( RI.vup, RI.cull_vup ); + } if( RI.drawOrtho ) { @@ -591,14 +601,21 @@ void R_SetupFrustum( void ) return; } + // 0 - left + // 1 - right + // 2 - down + // 3 - up + // 4 - farclip + // 5 - nearclip + // rotate RI.vforward right by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[0].normal, RI.cull_vup, RI.cull_vforward, -( 90 - RI.refdef.fov_x / 2 )); + RotatePointAroundVector( RI.frustum[0].normal, RI.cull_vup, RI.cull_vforward, -( 90 - RI.fov_x / 2 )); // rotate RI.vforward left by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[1].normal, RI.cull_vup, RI.cull_vforward, 90 - RI.refdef.fov_x / 2 ); + RotatePointAroundVector( RI.frustum[1].normal, RI.cull_vup, RI.cull_vforward, 90 - RI.fov_x / 2 ); // rotate RI.vforward up by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[2].normal, RI.cull_vright, RI.cull_vforward, 90 - RI.refdef.fov_y / 2 ); + RotatePointAroundVector( RI.frustum[2].normal, RI.cull_vright, RI.cull_vforward, 90 - RI.fov_y / 2 ); // rotate RI.vforward down by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[3].normal, RI.cull_vright, RI.cull_vforward, -( 90 - RI.refdef.fov_y / 2 )); + RotatePointAroundVector( RI.frustum[3].normal, RI.cull_vright, RI.cull_vforward, -( 90 - RI.fov_y / 2 )); // negate forward vector VectorNegate( RI.cull_vforward, RI.frustum[4].normal ); @@ -620,7 +637,7 @@ void R_SetupFrustum( void ) R_SetupProjectionMatrix ============= */ -static void R_SetupProjectionMatrix( const ref_params_t *fd, matrix4x4 m ) +static void R_SetupProjectionMatrix( matrix4x4 m ) { GLdouble xMin, xMax, yMin, yMax, zNear, zFar; @@ -637,10 +654,10 @@ static void R_SetupProjectionMatrix( const ref_params_t *fd, matrix4x4 m ) zNear = 4.0f; zFar = max( 256.0f, RI.farClip ); - yMax = zNear * tan( fd->fov_y * M_PI / 360.0 ); + yMax = zNear * tan( RI.fov_y * M_PI / 360.0 ); yMin = -yMax; - xMax = zNear * tan( fd->fov_x * M_PI / 360.0 ); + xMax = zNear * tan( RI.fov_x * M_PI / 360.0 ); xMin = -xMax; Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar ); @@ -651,7 +668,7 @@ static void R_SetupProjectionMatrix( const ref_params_t *fd, matrix4x4 m ) R_SetupModelviewMatrix ============= */ -static void R_SetupModelviewMatrix( const ref_params_t *fd, matrix4x4 m ) +static void R_SetupModelviewMatrix( matrix4x4 m ) { #if 0 Matrix4x4_LoadIdentity( m ); @@ -660,10 +677,10 @@ static void R_SetupModelviewMatrix( const ref_params_t *fd, matrix4x4 m ) #else Matrix4x4_CreateModelview( m ); #endif - Matrix4x4_ConcatRotate( m, -fd->viewangles[2], 1, 0, 0 ); - Matrix4x4_ConcatRotate( m, -fd->viewangles[0], 0, 1, 0 ); - Matrix4x4_ConcatRotate( m, -fd->viewangles[1], 0, 0, 1 ); - Matrix4x4_ConcatTranslate( m, -fd->vieworg[0], -fd->vieworg[1], -fd->vieworg[2] ); + Matrix4x4_ConcatRotate( m, -RI.viewangles[2], 1, 0, 0 ); + Matrix4x4_ConcatRotate( m, -RI.viewangles[0], 0, 1, 0 ); + Matrix4x4_ConcatRotate( m, -RI.viewangles[1], 0, 0, 1 ); + Matrix4x4_ConcatTranslate( m, -RI.vieworg[0], -RI.vieworg[1], -RI.vieworg[2] ); } /* @@ -753,28 +770,10 @@ R_SetupFrame */ static void R_SetupFrame( void ) { - vec3_t viewOrg, viewAng; - - VectorCopy( RI.refdef.vieworg, viewOrg ); - VectorCopy( RI.refdef.viewangles, viewAng ); - - // build the transformation matrix for the given view angles - VectorCopy( viewOrg, RI.vieworg ); - AngleVectors( viewAng, RI.vforward, RI.vright, RI.vup ); - // setup viewplane dist RI.viewplanedist = DotProduct( RI.vieworg, RI.vforward ); - VectorCopy( RI.vieworg, RI.pvsorigin ); - - if( !r_lockcull->value ) - { - VectorCopy( RI.vieworg, RI.cullorigin ); - VectorCopy( RI.vforward, RI.cull_vforward ); - VectorCopy( RI.vright, RI.cull_vright ); - VectorCopy( RI.vup, RI.cull_vup ); - } - + // prepare events for viewmodel (e.g. muzzleflashes) R_RunViewmodelEvents(); // sort opaque entities by model type to avoid drawing model shadows under alpha-surfaces @@ -801,16 +800,16 @@ R_SetupGL */ static void R_SetupGL( void ) { - if( RI.refdef.waterlevel >= 3 ) + if( RP_NORMALPASS() && ( cl.local.waterlevel >= 3 )) { float f; f = sin( cl.time * 0.4f * ( M_PI * 2.7f )); - RI.refdef.fov_x += f; - RI.refdef.fov_y -= f; + RI.fov_x += f; + RI.fov_y -= f; } - R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix ); - R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix ); + R_SetupModelviewMatrix( RI.worldviewMatrix ); + R_SetupProjectionMatrix( RI.projectionMatrix ); // if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0]; Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); @@ -965,7 +964,7 @@ static void R_CheckFog( void ) RI.fogEnabled = false; - if( RI.refdef.waterlevel < 2 || !RI.drawWorld || !RI.viewleaf ) + if( cl.local.waterlevel < 2 || !RI.drawWorld || !RI.viewleaf ) return; ent = CL_GetWaterEntity( RI.vieworg ); @@ -979,7 +978,7 @@ static void R_CheckFog( void ) return; } - if( RI.refdef.waterlevel < 3 ) return; + if( cl.local.waterlevel < 3 ) return; if( !IsLiquidContents( RI.cached_contents ) && IsLiquidContents( cnt )) { @@ -1034,7 +1033,7 @@ R_DrawFog */ void R_DrawFog( void ) { - if( !RI.fogEnabled || RI.refdef.onlyClientDraw ) + if( !RI.fogEnabled || RI.onlyClientDraw ) return; pglEnable( GL_FOG ); @@ -1059,11 +1058,8 @@ void R_DrawEntitiesOnList( void ) R_DrawFog (); // first draw solid entities - for( i = 0; i < tr.num_solid_entities; i++ ) + for( i = 0; i < tr.num_solid_entities && !RI.onlyClientDraw; i++ ) { - if( RI.refdef.onlyClientDraw ) - break; - RI.currententity = tr.solid_entities[i]; RI.currentmodel = RI.currententity->model; @@ -1086,7 +1082,7 @@ void R_DrawEntitiesOnList( void ) } } - if( !RI.refdef.onlyClientDraw ) + if( !RI.onlyClientDraw ) { CL_DrawBeams( false ); } @@ -1105,11 +1101,8 @@ void R_DrawEntitiesOnList( void ) glState.drawTrans = true; // then draw translucent entities - for( i = 0; i < tr.num_trans_entities; i++ ) + for( i = 0; i < tr.num_trans_entities && !RI.onlyClientDraw; i++ ) { - if( RI.refdef.onlyClientDraw ) - break; - RI.currententity = tr.trans_entities[i]; RI.currentmodel = RI.currententity->model; @@ -1138,7 +1131,7 @@ void R_DrawEntitiesOnList( void ) clgame.dllFuncs.pfnDrawTransparentTriangles (); } - if( !RI.refdef.onlyClientDraw ) + if( !RI.onlyClientDraw ) { CL_DrawBeams( true ); CL_DrawParticles(); @@ -1161,20 +1154,18 @@ void R_DrawEntitiesOnList( void ) ================ R_RenderScene -RI.refdef must be set before the first call +R_SetupRefParams must be called right before ================ */ -void R_RenderScene( const ref_params_t *fd ) +void R_RenderScene( void ) { - RI.refdef = *fd; - if( !cl.worldmodel && RI.drawWorld ) Host_Error( "R_RenderView: NULL worldmodel\n" ); R_PushDlights(); - R_SetupFrame(); R_SetupFrustum(); + R_SetupFrame(); R_SetupGL(); R_Clear( ~0 ); @@ -1238,12 +1229,43 @@ void R_BeginFrame( qboolean clearScene ) CL_ExtraUpdate (); } +/* +=============== +R_SetupRefParams + +set initial params for renderer +=============== +*/ +void R_SetupRefParams( const ref_params_t *fd, qboolean drawWorld, float fov ) +{ + RI.params = RP_NONE; + RI.drawWorld = drawWorld; + RI.thirdPerson = cl.local.thirdperson; + RI.drawOrtho = (drawWorld) ? (int)gl_overview->value : 0; + RI.clipFlags = 15; // top, bottom, left, right + RI.onlyClientDraw = fd->onlyClientDraw; + RI.farClip = 0; + + // setup viewport + RI.viewport[0] = fd->viewport[0]; + RI.viewport[1] = fd->viewport[1]; + RI.viewport[2] = fd->viewport[2]; + RI.viewport[3] = fd->viewport[3]; + + // calc FOV + RI.fov_x = fov; // this is a final fov value + + VectorCopy( fd->vieworg, RI.vieworg ); + VectorCopy( fd->viewangles, RI.viewangles ); + VectorCopy( fd->vieworg, RI.pvsorigin ); +} + /* =============== R_RenderFrame =============== */ -void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld ) +void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld, float fov ) { if( r_norefresh->value ) return; @@ -1264,26 +1286,7 @@ void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld ) } } - if( drawWorld ) r_lastRefdef = *fd; - - RI.params = RP_NONE; - RI.farClip = 0; - RI.clipFlags = 15; - RI.drawWorld = drawWorld; - RI.thirdPerson = cl.thirdperson; - RI.drawOrtho = (RI.drawWorld) ? gl_overview->value : 0; - - GL_BackendStartFrame( fd ); - - if( !r_lockcull->value ) - VectorCopy( fd->vieworg, RI.cullorigin ); - VectorCopy( fd->vieworg, RI.pvsorigin ); - - // setup viewport - RI.viewport[0] = fd->viewport[0]; - RI.viewport[1] = fd->viewport[1]; - RI.viewport[2] = fd->viewport[2]; - RI.viewport[3] = fd->viewport[3]; + R_SetupRefParams( fd, drawWorld, fov ); if( gl_finish->value && drawWorld ) pglFinish(); @@ -1291,13 +1294,11 @@ void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld ) if( gl_allow_mirrors->value ) { // render mirrors - R_FindMirrors( fd ); + R_FindMirrors (); R_DrawMirrors (); } - R_RenderScene( fd ); - - GL_BackendEndFrame( fd ); + R_RenderScene(); } /* @@ -1324,34 +1325,33 @@ R_DrawCubemapView */ void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ) { - ref_params_t *fd; - if( clgame.drawFuncs.R_DrawCubemapView != NULL ) { if( clgame.drawFuncs.R_DrawCubemapView( origin, angles, size )) return; } - fd = &RI.refdef; - *fd = r_lastRefdef; - fd->time = 0; - fd->viewport[0] = 0; - fd->viewport[1] = 0; - fd->viewport[2] = size; - fd->viewport[3] = size; - fd->fov_x = 90; - fd->fov_y = 90; - VectorCopy( origin, fd->vieworg ); - VectorCopy( angles, fd->viewangles ); - VectorCopy( fd->vieworg, RI.pvsorigin ); - - // setup viewport - RI.viewport[0] = fd->viewport[0]; - RI.viewport[1] = fd->viewport[1]; - RI.viewport[2] = fd->viewport[2]; - RI.viewport[3] = fd->viewport[3]; + // basic params + RI.params = RP_NONE; + RI.drawWorld = true; + RI.thirdPerson = RI.drawOrtho = false; + RI.clipFlags = 15; // top, bottom, left, right + RI.onlyClientDraw = false; + RI.farClip = 0; - R_RenderScene( fd ); + // setup viewport + RI.viewport[0] = RI.viewport[1] = 0; + RI.viewport[2] = RI.viewport[3] = size; + + // calc FOV + RI.fov_x = 90.0f; // this is a final fov value + + // setup origin & angles + VectorCopy( origin, RI.vieworg ); + VectorCopy( angles, RI.viewangles ); + VectorCopy( origin, RI.pvsorigin ); + + R_RenderScene (); RI.oldviewleaf = RI.viewleaf = NULL; // force markleafs next frame } diff --git a/engine/client/gl_rmisc.c b/engine/client/gl_rmisc.c index ae98024f..a1ba187f 100644 --- a/engine/client/gl_rmisc.c +++ b/engine/client/gl_rmisc.c @@ -474,7 +474,7 @@ void R_NewMap( void ) tx->texturechain = NULL; } - R_SetupSky( cl.refdef.movevars->skyName ); + R_SetupSky( clgame.movevars.skyName ); GL_BuildLightmaps (); } \ No newline at end of file diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index 2cea4dff..d8c99b5a 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -222,7 +222,7 @@ void GL_SetupFogColorForSurfaces( void ) vec3_t fogColor; float factor, div; - if(( !RI.fogEnabled && !RI.fogCustom ) || RI.refdef.onlyClientDraw || !RI.currententity ) + if(( !RI.fogEnabled && !RI.fogCustom ) || RI.onlyClientDraw || !RI.currententity ) return; if( RI.currententity->curstate.rendermode == kRenderTransTexture ) @@ -242,7 +242,7 @@ void GL_SetupFogColorForSurfaces( void ) void GL_ResetFogColor( void ) { // restore fog here - if(( RI.fogEnabled || RI.fogCustom ) && !RI.refdef.onlyClientDraw ) + if(( RI.fogEnabled || RI.fogCustom ) && !RI.onlyClientDraw ) pglFogfv( GL_FOG_COLOR, RI.fogColor ); } @@ -742,8 +742,8 @@ void DrawGLPoly( glpoly_t *p, float xScale, float yScale ) flAngle = ( flConveyorSpeed >= 0 ) ? 180 : 0; SinCos( flAngle * ( M_PI / 180.0f ), &sy, &cy ); - sOffset = RI.refdef.time * cy * flRate; - tOffset = RI.refdef.time * sy * flRate; + sOffset = cl.time * cy * flRate; + tOffset = cl.time * sy * flRate; // make sure that we are positive if( sOffset < 0.0f ) sOffset += 1.0f + -(int)sOffset; @@ -988,7 +988,7 @@ void R_RenderFullbrights( void ) if( !draw_fullbrights ) return; - if( RI.fogEnabled && !RI.refdef.onlyClientDraw ) + if( RI.fogEnabled && !RI.onlyClientDraw ) pglDisable( GL_FOG ); pglEnable( GL_BLEND ); @@ -1021,7 +1021,7 @@ void R_RenderFullbrights( void ) draw_fullbrights = false; // restore for here - if( RI.fogEnabled && !RI.refdef.onlyClientDraw ) + if( RI.fogEnabled && !RI.onlyClientDraw ) pglEnable( GL_FOG ); } @@ -1283,7 +1283,7 @@ void R_DrawTextureChains( void ) if( !s || ( i == tr.skytexturenum )) continue; - if(( s->flags & SURF_DRAWTURB ) && cl.refdef.movevars->wateralpha < 1.0f ) + if(( s->flags & SURF_DRAWTURB ) && clgame.movevars.wateralpha < 1.0f ) continue; // draw translucent water later for( ; s != NULL; s = s->texturechain ) @@ -1305,11 +1305,11 @@ void R_DrawWaterSurfaces( void ) msurface_t *s; texture_t *t; - if( !RI.drawWorld || RI.refdef.onlyClientDraw ) + if( !RI.drawWorld || RI.onlyClientDraw ) return; // non-transparent water is already drawed - if( cl.refdef.movevars->wateralpha >= 1.0f ) + if( clgame.movevars.wateralpha >= 1.0f ) return; // restore worldmodel @@ -1324,7 +1324,7 @@ void R_DrawWaterSurfaces( void ) pglDisable( GL_ALPHA_TEST ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - pglColor4f( 1.0f, 1.0f, 1.0f, cl.refdef.movevars->wateralpha ); + pglColor4f( 1.0f, 1.0f, 1.0f, clgame.movevars.wateralpha ); for( i = 0; i < cl.worldmodel->numtextures; i++ ) { @@ -1909,7 +1909,7 @@ void R_DrawWorld( void ) RI.currententity = clgame.entities; RI.currentmodel = RI.currententity->model; - if( !RI.drawWorld || RI.refdef.onlyClientDraw ) + if( !RI.drawWorld || RI.onlyClientDraw ) return; VectorCopy( RI.cullorigin, tr.modelorg ); diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index 3ce99b96..85098892 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -499,7 +499,7 @@ mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ) } else if( psprite->frames[frame].type == FRAME_ANGLED ) { - int angleframe = (int)(Q_rint(( RI.refdef.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; + int angleframe = (int)(Q_rint(( RI.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; // e.g. doom-style sprite monsters pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; @@ -554,25 +554,25 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, // this can be happens when rendering switched between single and angled frames // or change model on replace delta-entity ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; - ent->latched.prevanimtime = RI.refdef.time; + ent->latched.prevanimtime = cl.time; lerpFrac = 1.0f; } - if( ent->latched.prevanimtime < RI.refdef.time ) + if( ent->latched.prevanimtime < cl.time ) { if( frame != ent->latched.prevblending[1] ) { ent->latched.prevblending[0] = ent->latched.prevblending[1]; ent->latched.prevblending[1] = frame; - ent->latched.prevanimtime = RI.refdef.time; + ent->latched.prevanimtime = cl.time; lerpFrac = 0.0f; } - else lerpFrac = (RI.refdef.time - ent->latched.prevanimtime) * 10; + else lerpFrac = (cl.time - ent->latched.prevanimtime) * 10; } else { ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; - ent->latched.prevanimtime = RI.refdef.time; + ent->latched.prevanimtime = cl.time; lerpFrac = 0.0f; } } @@ -586,7 +586,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, { // reset interpolation on change model ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; - ent->latched.prevanimtime = RI.refdef.time; + ent->latched.prevanimtime = cl.time; lerpFrac = 0.0f; } @@ -601,7 +601,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, numframes = pspritegroup->numframes; fullinterval = pintervals[numframes-1]; jinterval = pintervals[1] - pintervals[0]; - time = RI.refdef.time; + time = cl.time; jtime = 0.0f; // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values @@ -631,7 +631,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, { // e.g. doom-style sprite monsters float yaw = ent->angles[YAW]; - int angleframe = (int)(Q_rint(( RI.refdef.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; + int angleframe = (int)(Q_rint(( RI.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; if( m_fDoInterp ) { @@ -640,25 +640,25 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, // this can be happens when rendering switched between single and angled frames // or change model on replace delta-entity ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; - ent->latched.prevanimtime = RI.refdef.time; + ent->latched.prevanimtime = cl.time; lerpFrac = 1.0f; } - if( ent->latched.prevanimtime < RI.refdef.time ) + if( ent->latched.prevanimtime < cl.time ) { if( frame != ent->latched.prevblending[1] ) { ent->latched.prevblending[0] = ent->latched.prevblending[1]; ent->latched.prevblending[1] = frame; - ent->latched.prevanimtime = RI.refdef.time; + ent->latched.prevanimtime = cl.time; lerpFrac = 0.0f; } - else lerpFrac = (RI.refdef.time - ent->latched.prevanimtime) * ent->curstate.framerate; + else lerpFrac = (cl.time - ent->latched.prevanimtime) * ent->curstate.framerate; } else { ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; - ent->latched.prevanimtime = RI.refdef.time; + ent->latched.prevanimtime = cl.time; lerpFrac = 0.0f; } } @@ -816,9 +816,9 @@ qboolean R_SpriteOccluded( cl_entity_t *e, vec3_t origin, int *alpha, float *psc TriWorldToScreen( origin, v ); - if( v[0] < RI.refdef.viewport[0] || v[0] > RI.refdef.viewport[0] + RI.refdef.viewport[2] ) + if( v[0] < RI.viewport[0] || v[0] > RI.viewport[0] + RI.viewport[2] ) return true; // do scissor - if( v[1] < RI.refdef.viewport[1] || v[1] > RI.refdef.viewport[1] + RI.refdef.viewport[3] ) + if( v[1] < RI.viewport[1] || v[1] > RI.viewport[1] + RI.viewport[3] ) return true; // do scissor blend *= R_SpriteGlowBlend( origin, e->curstate.rendermode, e->curstate.renderfx, *alpha, pscale ); diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index c27d98ef..7644cb76 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -87,8 +87,6 @@ convar_t *cl_himodels; cvar_t r_shadows = { "r_shadows", "0", 0, 0 }; // dead cvar. especially disabled cvar_t r_shadowalpha = { "r_shadowalpha", "0.5", 0, 0.8f }; static r_studio_interface_t *pStudioDraw; -static float aliasXscale, aliasYscale; // software renderer scale -static matrix3x4 g_aliastransform; // software renderer transform static matrix3x4 g_rotationmatrix; static vec3_t g_chrome_origin; static vec2_t g_chrome[MAXSTUDIOVERTS]; // texture coords for surface normals @@ -138,8 +136,6 @@ R_StudioInit */ void R_StudioInit( void ) { - float pixelAspect, fov_x = 90.0f, fov_y; - r_studio_lambert = Cvar_Get( "r_studio_lambert", "2", FCVAR_ARCHIVE, "bonelighting lambert value" ); r_studio_lerping = Cvar_Get( "r_studio_lerping", "1", FCVAR_ARCHIVE, "enables studio animation lerping" ); r_drawviewmodel = Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" ); @@ -150,17 +146,6 @@ void R_StudioInit( void ) // NOTE: some mods with custom studiomodel renderer may cause error when menu trying draw player model out of the loaded game r_customdraw_playermodel = Cvar_Get( "r_customdraw_playermodel", "0", FCVAR_ARCHIVE, "allow to drawing playermodel in menu with client renderer" ); - // recalc software X and Y alias scale (this stuff is used only by HL software renderer but who knews...) - pixelAspect = ((float)scr_height->value / (float)scr_width->value); - if( scr_width->value < 640 ) - pixelAspect *= (320.0f / 240.0f); - else pixelAspect *= (640.0f / 480.0f); - - fov_y = V_CalcFov( &fov_x, scr_width->value, scr_height->value ); - aliasXscale = (float)scr_width->value / fov_y; // stub - aliasYscale = aliasXscale * pixelAspect; - - Matrix3x4_LoadIdentity( g_aliastransform ); Matrix3x4_LoadIdentity( g_rotationmatrix ); g_nStudioCount = 0; @@ -412,8 +397,8 @@ pfnGetAliasScale */ static void pfnGetAliasScale( float *x, float *y ) { - if( x ) *x = aliasXscale; - if( y ) *y = aliasYscale; + if( x ) *x = 1.0f; + if( y ) *y = 1.0f; } /* @@ -446,7 +431,7 @@ pfnStudioGetAliasTransform */ static float ***pfnStudioGetAliasTransform( void ) { - return (float ***)g_aliastransform; + return NULL; } /* @@ -539,10 +524,10 @@ void R_StudioSetUpTransform( cl_entity_t *e ) // don't do it if the goalstarttime hasn't updated in a while. // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit // was increased to 1.0 s., which is 2x the max lag we are accounting for. - if( m_fDoInterp && ( RI.refdef.time < e->curstate.animtime + 1.0f ) && ( e->curstate.animtime != e->latched.prevanimtime )) + if( m_fDoInterp && ( cl.time < e->curstate.animtime + 1.0f ) && ( e->curstate.animtime != e->latched.prevanimtime )) { - f = ( RI.refdef.time - e->curstate.animtime ) / ( e->curstate.animtime - e->latched.prevanimtime ); - // Msg( "%4.2f %.2f %.2f\n", f, e->curstate.animtime, RI.refdef.time ); + f = ( cl.time - e->curstate.animtime ) / ( e->curstate.animtime - e->latched.prevanimtime ); + // Msg( "%4.2f %.2f %.2f\n", f, e->curstate.animtime, cl.time ); } if( m_fDoInterp ) @@ -601,8 +586,8 @@ float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc ) if( m_fDoInterp ) { - if( RI.refdef.time < e->curstate.animtime ) dfdt = 0.0; - else dfdt = (RI.refdef.time - e->curstate.animtime) * e->curstate.framerate * pseqdesc->fps; + if( cl.time < e->curstate.animtime ) dfdt = 0.0; + else dfdt = (cl.time - e->curstate.animtime) * e->curstate.framerate * pseqdesc->fps; } else dfdt = 0; @@ -638,7 +623,7 @@ float R_StudioEstimateInterpolant( cl_entity_t *e ) if( m_fDoInterp && ( e->curstate.animtime >= e->latched.prevanimtime + 0.01f )) { - dadt = ( RI.refdef.time - e->curstate.animtime ) / 0.1f; + dadt = ( cl.time - e->curstate.animtime ) / 0.1f; if( dadt > 2.0f ) dadt = 2.0f; } return dadt; @@ -729,7 +714,7 @@ void R_StudioFxTransform( cl_entity_t *ent, matrix3x4 transform ) { float scale; - scale = 1.0f + ( RI.refdef.time - ent->curstate.animtime ) * 10.0f; + scale = 1.0f + ( cl.time - ent->curstate.animtime ) * 10.0f; if( scale > 2.0f ) scale = 2.0f; // don't blow up more than 200% transform[0][1] *= scale; @@ -1158,7 +1143,7 @@ void R_StudioSetupBones( cl_entity_t *e ) } } - if( m_fDoInterp && e->latched.sequencetime && ( e->latched.sequencetime + 0.2f > RI.refdef.time) && ( e->latched.prevsequence < m_pStudioHeader->numseq )) + if( m_fDoInterp && e->latched.sequencetime && ( e->latched.sequencetime + 0.2f > cl.time) && ( e->latched.prevsequence < m_pStudioHeader->numseq )) { // blend from last sequence static vec3_t pos1b[MAXSTUDIOBONES]; @@ -1195,7 +1180,7 @@ void R_StudioSetupBones( cl_entity_t *e ) } } - s = 1.0f - ( RI.refdef.time - e->latched.sequencetime ) / 0.2f; + s = 1.0f - ( cl.time - e->latched.sequencetime ) / 0.2f; R_StudioSlerpBones( q, pos, q1b, pos1b, s ); } else @@ -1306,7 +1291,7 @@ void R_StudioSetupChrome( float *pchrome, int bone, vec3_t normal ) float angle, sr, cr; int i; - angle = anglemod( RI.refdef.time * 40 ) * (M_PI2 / 360.0f); + angle = anglemod( cl.time * 40 ) * (M_PI2 / 360.0f); SinCos( angle, &sr, &cr ); for( i = 0; i < 3; i++ ) @@ -1425,10 +1410,8 @@ void R_StudioGetShadowImpactAndDir( void ) float angle; vec3_t skyAngles, origin, end; - if( !cl.refdef.movevars ) return; // e.g. in menu - // convert skyvec into angles then back into vector to avoid 0 0 0 direction - VectorAngles( (float *)&cl.refdef.movevars->skyvec_x, skyAngles ); + VectorAngles( (float *)&clgame.movevars.skyvec_x, skyAngles ); angle = skyAngles[YAW] / 180 * M_PI; Matrix3x4_OriginFromMatrix( g_bonestransform[0], origin ); @@ -1477,14 +1460,9 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *lightinfo ) else Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin ); // setup light dir - if( cl.refdef.movevars ) - { - // pre-defined light vector - plight->lightvec[0] = cl.refdef.movevars->skyvec_x; - plight->lightvec[1] = cl.refdef.movevars->skyvec_y; - plight->lightvec[2] = cl.refdef.movevars->skyvec_z; - } - else VectorSet( plight->lightvec, 0.0f, 0.0f, -1.0f ); + plight->lightvec[0] = clgame.movevars.skyvec_x; + plight->lightvec[1] = clgame.movevars.skyvec_y; + plight->lightvec[2] = clgame.movevars.skyvec_z; if( VectorIsNull( plight->lightvec )) VectorSet( plight->lightvec, 0.0f, 0.0f, -1.0f ); @@ -1510,7 +1488,7 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *lightinfo ) for( lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ ) { - if( dl->die < RI.refdef.time || !dl->radius ) + if( dl->die < cl.time || !dl->radius ) continue; VectorSubtract( dl->origin, origin, direction ); @@ -1596,7 +1574,7 @@ void R_StudioEntityLight( alight_t *lightinfo ) for( lnum = 0, el = cl_elights; lnum < MAX_ELIGHTS; lnum++, el++ ) { - if( el->die < RI.refdef.time || !el->radius ) + if( el->die < cl.time || !el->radius ) continue; VectorSubtract( el->origin, origin, direction ); @@ -2833,7 +2811,7 @@ void R_StudioEstimateGait( entity_state_t *pplayer ) vec3_t est_velocity; float dt; - dt = bound( 0.0f, (RI.refdef.time - cl.oldtime), 1.0f ); + dt = bound( 0.0f, (cl.time - cl.oldtime), 1.0f ); if( dt == 0.0f || m_pPlayerInfo->renderframe == tr.framecount ) { @@ -2902,7 +2880,7 @@ void R_StudioProcessGait( entity_state_t *pplayer ) RI.currententity->latched.prevblending[0] = RI.currententity->curstate.blending[0]; RI.currententity->latched.prevseqblending[0] = RI.currententity->curstate.blending[0]; - dt = bound( 0.0f, (RI.refdef.time - cl.oldtime), 1.0f ); + dt = bound( 0.0f, (cl.time - cl.oldtime), 1.0f ); R_StudioEstimateGait( pplayer ); // calc side to side turning @@ -3309,7 +3287,7 @@ R_RunViewmodelEvents */ void R_RunViewmodelEvents( void ) { - if( cl.refdef.nextView || cl.thirdperson || RI.params & RP_NONVIEWERREF ) + if( cl.local.thirdperson || RI.params & RP_NONVIEWERREF ) return; if( !Mod_Extradata( clgame.viewent.model )) @@ -3319,9 +3297,9 @@ void R_RunViewmodelEvents( void ) RI.currentmodel = RI.currententity->model; if( !RI.currentmodel ) return; - if( !cl.weaponstarttime ) cl.weaponstarttime = cl.time; - RI.currententity->curstate.animtime = cl.weaponstarttime; - RI.currententity->curstate.sequence = cl.weaponsequence; + if( !cl.local.weaponstarttime ) cl.local.weaponstarttime = cl.time; + RI.currententity->curstate.animtime = cl.local.weaponstarttime; + RI.currententity->curstate.sequence = cl.local.weaponsequence; pStudioDraw->StudioDrawModel( STUDIO_EVENTS ); @@ -3336,14 +3314,14 @@ R_DrawViewModel */ void R_DrawViewModel( void ) { - if( RI.refdef.onlyClientDraw || r_drawviewmodel->value == 0 ) + if( RI.onlyClientDraw || r_drawviewmodel->value == 0 ) return; // ignore in thirdperson, camera view or client is died - if( cl.thirdperson || cl.refdef.health <= 0 || cl.refdef.viewentity != ( cl.playernum + 1 )) + if( cl.local.thirdperson || cl.local.health <= 0 || cl.viewentity != ( cl.playernum + 1 )) return; - if( cl.refdef.nextView || RI.params & RP_NONVIEWERREF ) + if( RI.params & RP_NONVIEWERREF ) return; if( !Mod_Extradata( clgame.viewent.model )) @@ -3362,9 +3340,9 @@ void R_DrawViewModel( void ) if( r_lefthand->value == 1 || g_iBackFaceCull ) GL_FrontFace( !glState.frontFace ); - if( !cl.weaponstarttime ) cl.weaponstarttime = cl.time; - RI.currententity->curstate.animtime = cl.weaponstarttime; - RI.currententity->curstate.sequence = cl.weaponsequence; + if( !cl.local.weaponstarttime ) cl.local.weaponstarttime = cl.time; + RI.currententity->curstate.animtime = cl.local.weaponstarttime; + RI.currententity->curstate.sequence = cl.local.weaponsequence; pStudioDraw->StudioDrawModel( STUDIO_RENDER ); diff --git a/engine/client/gl_vidnt.c b/engine/client/gl_vidnt.c index 7f791098..caa36f65 100644 --- a/engine/client/gl_vidnt.c +++ b/engine/client/gl_vidnt.c @@ -1062,6 +1062,19 @@ void VID_RestoreGamma( void ) SetDeviceGammaRamp( glw_state.hDC, glState.stateRamp ); } +/* +================= +VID_InitDefaultResolution +================= +*/ +void VID_InitDefaultResolution( void ) +{ + // we need to have something valid here + // until video subsystem initialized + glState.width = 640; + glState.height = 480; +} + /* ================= GL_SetPixelformat @@ -1155,9 +1168,6 @@ void R_SaveVideoMode( int vid_mode ) glState.width = vidmode[mode].width; glState.height = vidmode[mode].height; glState.wideScreen = vidmode[mode].wideScreen; - - Cvar_FullSet( "width", va( "%i", vidmode[mode].width ), FCVAR_READ_ONLY ); - Cvar_FullSet( "height", va( "%i", vidmode[mode].height ), FCVAR_READ_ONLY ); Cvar_SetValue( "vid_mode", mode ); // merge if it out of bounds MsgDev( D_NOTE, "Set: %s [%dx%d]\n", vidmode[mode].desc, vidmode[mode].width, vidmode[mode].height ); @@ -1375,8 +1385,8 @@ rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen ) R_SaveVideoMode( vid_mode ); - width = scr_width->value; - height = scr_height->value; + width = glState.width; + height = glState.height; // check our desktop attributes hDC = GetDC( GetDesktopWindow( )); @@ -1708,7 +1718,7 @@ void R_RenderInfo_f( void ) } Msg( "\n" ); - Msg( "MODE: %i, %i x %i %s\n", vid_mode->value, scr_width->value, scr_height->value, vidmode[(int)vid_mode->value].desc ); + Msg( "MODE: %i, %i x %i %s\n", vid_mode->value, glState.width, glState.height, vidmode[(int)vid_mode->value].desc ); Msg( "GAMMA: %s\n", (glConfig.deviceSupportsGamma) ? "hardware" : "software" ); Msg( "\n" ); Msg( "PICMIP: %i\n", gl_picmip->value ); diff --git a/engine/client/gl_warp.c b/engine/client/gl_warp.c index 8beed5c9..b498b373 100644 --- a/engine/client/gl_warp.c +++ b/engine/client/gl_warp.c @@ -788,7 +788,7 @@ void EmitWaterPolys( glpoly_t *polys, qboolean noCull, qboolean direction ) if( noCull ) pglDisable( GL_CULL_FACE ); // set the current waveheight - if( p->verts[0][2] >= RI.refdef.vieworg[2] ) + if( p->verts[0][2] >= RI.vieworg[2] ) waveHeight = -RI.currententity->curstate.scale; else waveHeight = RI.currententity->curstate.scale; diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 385bebe7..e1353a7b 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -17,7 +17,7 @@ GNU General Public License for more details. #include "sound.h" #include "client.h" #include "con_nprint.h" -#include "ref_params.h" +#include "gl_local.h" #include "pm_local.h" #define SND_CLIP_DISTANCE (float)(GI->soundclip_dist) @@ -881,7 +881,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv return; } - if( !pos ) pos = cl.refdef.vieworg; + if( !pos ) pos = RI.vieworg; // pick a channel to play on if( chan == CHAN_STATIC ) target_chan = SND_PickStaticChannel( ent, sfx ); @@ -1850,19 +1850,18 @@ void S_ExtraUpdate( void ) /* ============ -S_RenderFrame +SND_UpdateSound Called once each time through the main loop ============ */ -void S_RenderFrame( ref_params_t *fd ) +void SND_UpdateSound( void ) { int i, j, total; channel_t *ch, *combine; con_nprint_t info; if( !dma.initialized ) return; - if( !fd ) return; // too early // if the loading plaque is up, clear everything // out to make sure we aren't looping a dirty @@ -1873,16 +1872,16 @@ void S_RenderFrame( ref_params_t *fd ) // release raw-channels that no longer used more than 10 secs S_FreeIdleRawChannels(); - s_listener.entnum = fd->viewentity; // can be camera entity too - s_listener.frametime = fd->frametime; - s_listener.waterlevel = fd->waterlevel; + s_listener.entnum = cl.viewentity; // can be camera entity too + s_listener.frametime = (cl.time - cl.oldtime); + s_listener.waterlevel = cl.local.waterlevel; s_listener.active = CL_IsInGame(); s_listener.inmenu = CL_IsInMenu(); - s_listener.paused = fd->paused; + s_listener.paused = cl.paused; - VectorCopy( fd->vieworg, s_listener.origin ); - VectorCopy( fd->simvel, s_listener.velocity ); - AngleVectors( fd->viewangles, s_listener.forward, s_listener.right, s_listener.up ); + VectorCopy( RI.vieworg, s_listener.origin ); + VectorCopy( cl.simvel, s_listener.velocity ); + AngleVectors( RI.viewangles, s_listener.forward, s_listener.right, s_listener.up ); if( cl.worldmodel != NULL ) Mod_FatPVS( s_listener.origin, FATPHS_RADIUS, s_listener.pasbytes, world.visbytes, false, !s_phs->value ); diff --git a/engine/client/vgui/vgui_input.cpp b/engine/client/vgui/vgui_input.cpp index 51cb436b..5b319e9e 100644 --- a/engine/client/vgui/vgui_input.cpp +++ b/engine/client/vgui/vgui_input.cpp @@ -83,7 +83,7 @@ void VGUI_CursorSelect( Cursor *cursor ) void VGUI_ActivateCurrentCursor( void ) { - if( cls.key_dest != key_game || cl.refdef.paused ) + if( cls.key_dest != key_game || cl.paused ) return; if( host.mouse_visible ) diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 5a5fa074..bbda1aba 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -1016,7 +1016,7 @@ void Cmd_ForwardToServer( void ) if( cls.demoplayback ) { if( !Q_stricmp( Cmd_Argv( 0 ), "pause" )) - cl.refdef.paused ^= 1; + cl.paused ^= 1; return; } diff --git a/engine/common/common.h b/engine/common/common.h index d2522776..3930acbb 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -90,7 +90,6 @@ typedef enum } instance_t; #include "system.h" -#include "ref_params.h" #include "com_model.h" #include "crtlib.h" #include "cvar.h" @@ -144,8 +143,6 @@ void DBG_AssertFunction( qboolean fExpr, const char* szExpr, const char* szFile, #endif extern convar_t *gl_vsync; -extern convar_t *scr_width; -extern convar_t *scr_height; extern convar_t *scr_loading; extern convar_t *scr_download; extern convar_t *cmd_scripting; @@ -857,6 +854,7 @@ void CL_Crashed( void ); qboolean CL_NextDemo( void ); char *SV_Serverinfo( void ); void CL_Drop( void ); +void Con_Init( void ); void SCR_Init( void ); void SCR_UpdateScreen( void ); void SCR_BeginLoadingPlaque( qboolean is_background ); @@ -887,6 +885,7 @@ float Com_RandomFloat( float fMin, float fMax ); void TrimSpace( const char *source, char *dest ); const byte *GL_TextureData( unsigned int texnum ); void GL_FreeImage( const char *name ); +void VID_InitDefaultResolution( void ); void VID_RestoreGamma( void ); void UI_SetActiveMenu( qboolean fActive ); struct cmd_s *Cmd_GetFirstFunctionHandle( void ); diff --git a/engine/common/console.c b/engine/common/console.c index f9b34054..6180e633 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -26,6 +26,7 @@ convar_t *scr_conspeed; convar_t *con_fontsize; #define CON_TIMES 4 // notify lines +#define CON_MAX_TIMES 64 // notify max lines #define COLOR_DEFAULT '7' #define CON_HISTORY 64 #define MAX_DBG_NOTIFY 128 @@ -87,6 +88,7 @@ typedef struct int lines_first; // cyclic buffer int lines_count; + int num_times; // overlay lines count // console scroll int backscroll; // lines up from bottom to display @@ -303,6 +305,25 @@ void Con_ToggleConsole_f( void ) } } +/* +================ +Con_SetTimes_f +================ +*/ +void Con_SetTimes_f( void ) +{ + int newtimes; + + if( Cmd_Argc() != 2 ) + { + Msg( "Usage: contimes \n" ); + return; + } + + newtimes = Q_atoi( Cmd_Argv( 1 ) ); + con.num_times = bound( CON_TIMES, newtimes, CON_MAX_TIMES ); +} + /* ================ Con_FixTimes @@ -447,7 +468,7 @@ void Con_CheckResize( void ) if( con.curFont && con.curFont->hFontTexture ) charWidth = con.curFont->charWidths['M'] - 1; - width = ( scr_width->value / charWidth ) - 2; + width = ( glState.width / charWidth ) - 2; if( !glw_state.initialized ) width = 78; if( width == con.linewidth ) @@ -574,9 +595,9 @@ static void Con_LoadConchars( void ) Con_LoadConsoleFont( i, con.chars + i ); // select properly fontsize - if( scr_width->value <= 640 ) + if( glState.width <= 640 ) fontSize = 0; - else if( scr_width->value >= 1280 ) + else if( glState.width >= 1280 ) fontSize = 2; else fontSize = 1; @@ -599,8 +620,8 @@ static void Con_TextAdjustSize( int *x, int *y, int *w, int *h ) if( !x && !y && !w && !h ) return; // scale for screen sizes - xscale = scr_width->value / (float)clgame.scrInfo.iWidth; - yscale = scr_height->value / (float)clgame.scrInfo.iHeight; + xscale = (float)glState.width / (float)clgame.scrInfo.iWidth; + yscale = (float)glState.height / (float)clgame.scrInfo.iHeight; if( x ) *x *= xscale; if( y ) *y *= yscale; @@ -824,9 +845,10 @@ void Con_Init( void ) { int i; + if( host.type == HOST_DEDICATED ) + return; // dedicated server already have console + // must be init before startup video subsystem - scr_width = Cvar_Get( "width", "640", FCVAR_READ_ONLY, "screen width" ); - scr_height = Cvar_Get( "height", "480", FCVAR_READ_ONLY, "screen height" ); scr_conspeed = Cvar_Get( "scr_conspeed", "600", FCVAR_ARCHIVE, "console moving speed" ); con_notifytime = Cvar_Get( "con_notifytime", "3", FCVAR_ARCHIVE, "notify time to live" ); con_fontsize = Cvar_Get( "con_fontsize", "1", FCVAR_ARCHIVE, "console font number (0, 1 or 2)" ); @@ -837,6 +859,7 @@ void Con_Init( void ) con.maxlines = CON_MAXLINES; con.lines = (con_lineinfo_t *)Z_Malloc( con.maxlines * sizeof( *con.lines )); con.lines_first = con.lines_count = 0; + con.num_times = CON_TIMES; // default as 4 Con_CheckResize(); @@ -857,9 +880,10 @@ void Con_Init( void ) Cmd_AddCommand( "clear", Con_Clear_f, "clear console history" ); Cmd_AddCommand( "messagemode", Con_MessageMode_f, "enable message mode \"say\"" ); Cmd_AddCommand( "messagemode2", Con_MessageMode2_f, "enable message mode \"say_team\"" ); - - MsgDev( D_REPORT, "Console initialized.\n" ); + Cmd_AddCommand( "contimes", Con_SetTimes_f, "change number of console overlay lines (4-64)" ); con.initialized = true; + + MsgDev( D_INFO, "Console initialized.\n" ); } /* @@ -1694,10 +1718,10 @@ int Con_DrawDebugLines( void ) int fontTall; Con_DrawStringLen( con.notify[i].szNotify, &len, &fontTall ); - x = scr_width->value - Q_max( defaultX, len ) - 10; + x = glState.width - Q_max( defaultX, len ) - 10; fontTall += 1; - if( y + fontTall > (int)scr_height->value - 20 ) + if( y + fontTall > glState.height - 20 ) return count; count++; @@ -1746,7 +1770,7 @@ void Con_DrawNotify( void ) if( host.developer && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" ))) { - for( i = CON_LINES_COUNT - CON_TIMES; i < CON_LINES_COUNT; i++ ) + for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ ) { con_lineinfo_t *l = &CON_LINES( i ); @@ -1846,7 +1870,7 @@ void Con_DrawSolidConsole( int lines ) // draw the background GL_SetRenderMode( kRenderNormal ); pglColor4ub( 255, 255, 255, 255 ); // to prevent grab color from screenfade - R_DrawStretchPic( 0, lines - scr_height->value, scr_width->value, scr_height->value, 0, 0, 1, 1, con.background ); + R_DrawStretchPic( 0, lines - glState.height, glState.width, glState.height, 0, 0, 1, 1, con.background ); if( !con.curFont || host.developer <= 0 ) return; // nothing to draw @@ -1862,10 +1886,10 @@ void Con_DrawSolidConsole( int lines ) Q_snprintf( curbuild, MAX_STRING, "Xash3D %i/%g (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); - start = scr_width->value - stringLen; + start = glState.width - stringLen; stringLen = Con_StringLength( curbuild ); - fraction = lines / (float)scr_height->value; + fraction = lines / (float)glState.height; color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number for( i = 0; i < stringLen; i++ ) @@ -1932,13 +1956,13 @@ void Con_DrawConsole( void ) { if(( Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) && cls.key_dest != key_console ) con.vislines = con.showlines = 0; - else con.vislines = con.showlines = scr_height->value; + else con.vislines = con.showlines = glState.height; } else { if( host.developer >= 4 ) { - con.vislines = ((int)scr_height->value >> 1); // keep console open + con.vislines = (glState.height >> 1); // keep console open } else { @@ -1957,7 +1981,7 @@ void Con_DrawConsole( void ) case ca_disconnected: if( cls.key_dest != key_menu && host.developer ) { - Con_DrawSolidConsole( scr_height->value ); + Con_DrawSolidConsole( glState.height ); Key_SetKeyDest( key_console ); } break; @@ -1975,7 +1999,7 @@ void Con_DrawConsole( void ) if( Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) { if( cls.key_dest == key_console ) - Con_DrawSolidConsole( scr_height->value ); + Con_DrawSolidConsole( glState.height ); } else { @@ -2002,7 +2026,7 @@ void Con_DrawVersion( void ) // draws the current build byte *color = g_color_table[7]; int i, stringLen, width = 0, charH; - int start, height = scr_height->value; + int start, height = glState.height; qboolean draw_version = false; string curbuild; @@ -2024,7 +2048,7 @@ void Con_DrawVersion( void ) Q_snprintf( curbuild, MAX_STRING, "Xash3D v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); else Q_snprintf( curbuild, MAX_STRING, "v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); - start = scr_width->value - stringLen * 1.05f; + start = glState.width - stringLen * 1.05f; stringLen = Con_StringLength( curbuild ); height -= charH * 1.05f; @@ -2047,12 +2071,12 @@ void Con_RunConsole( void ) if( host.developer && cls.key_dest == key_console ) { if( cls.state == ca_disconnected ) - con.showlines = scr_height->value; // full screen - else con.showlines = ((int)scr_height->value >> 1); // half screen + con.showlines = glState.height; // full screen + else con.showlines = (glState.height >> 1); // half screen } else con.showlines = 0; // none visible - lines_per_frame = bound( 1, fabs( scr_conspeed->value ) * host.realframetime, scr_height->value ); + lines_per_frame = bound( 1, fabs( scr_conspeed->value ) * host.realframetime, glState.height ); if( cls.state == ca_connecting || cls.state == ca_connected ) lines_per_frame = 0; @@ -2119,18 +2143,9 @@ void Con_VidInit( void ) if( !con.background ) { - if( scr_width->value < 640 ) - { - if( FS_FileExists( "cached/conback400", false )) - con.background = GL_LoadTexture( "cached/conback400", NULL, 0, TF_IMAGE, NULL ); - else con.background = GL_LoadTexture( "cached/conback", NULL, 0, TF_IMAGE, NULL ); - } - else - { - if( FS_FileExists( "cached/conback640", false )) - con.background = GL_LoadTexture( "cached/conback640", NULL, 0, TF_IMAGE, NULL ); - else con.background = GL_LoadTexture( "cached/conback", NULL, 0, TF_IMAGE, NULL ); - } + if( FS_FileExists( "cached/conback640", false )) + con.background = GL_LoadTexture( "cached/conback640", NULL, 0, TF_IMAGE, NULL ); + else con.background = GL_LoadTexture( "cached/conback", NULL, 0, TF_IMAGE, NULL ); } } else @@ -2141,18 +2156,9 @@ void Con_VidInit( void ) if( !con.background ) { - if( scr_width->value < 640 ) - { - if( FS_FileExists( "cached/loading400", false )) - con.background = GL_LoadTexture( "cached/loading400", NULL, 0, TF_IMAGE, NULL ); - else con.background = GL_LoadTexture( "cached/loading", NULL, 0, TF_IMAGE, NULL ); - } - else - { - if( FS_FileExists( "cached/loading640", false )) - con.background = GL_LoadTexture( "cached/loading640", NULL, 0, TF_IMAGE, NULL ); - else con.background = GL_LoadTexture( "cached/loading", NULL, 0, TF_IMAGE, NULL ); - } + if( FS_FileExists( "cached/loading640", false )) + con.background = GL_LoadTexture( "cached/loading640", NULL, 0, TF_IMAGE, NULL ); + else con.background = GL_LoadTexture( "cached/loading", NULL, 0, TF_IMAGE, NULL ); } } diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 519bb576..b671a113 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -14,6 +14,7 @@ GNU General Public License for more details. */ #include "common.h" +#include "math.h" // fabs... convar_t *cvar_vars; // head of list convar_t *cmd_scripting; diff --git a/engine/common/host.c b/engine/common/host.c index 9081e455..0ddad06c 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -847,14 +847,18 @@ void Host_InitCommon( const char *progname, qboolean bChangeGame ) host.old_developer = host.developer; - Con_CreateConsole(); + Con_CreateConsole(); // system console used by dedicated server or show fatal errors - // first text message into console or log + // NOTE: this message couldn't be passed into game console but it doesn't matter MsgDev( D_NOTE, "Sys_LoadLibrary: Loading xash.dll - ok\n" ); + // get default screen res + VID_InitDefaultResolution(); + // startup cmds and cvars subsystem Cmd_Init(); Cvar_Init(); + Con_Init(); // early console running to catch all the messages // share developer level across all dlls Q_snprintf( dev_level, sizeof( dev_level ), "%i", host.developer ); diff --git a/engine/common/input.c b/engine/common/input.c index 9db66a24..2ec090f3 100644 --- a/engine/common/input.c +++ b/engine/common/input.c @@ -393,7 +393,7 @@ void Host_InputFrame( void ) } // release mouse during pause or console typeing - if( cl.refdef.paused && cls.key_dest == key_game ) + if( cl.paused && cls.key_dest == key_game ) shutdownMouse = true; if( shutdownMouse && !Cvar_VariableInteger( "fullscreen" )) diff --git a/mainui/menu_playersetup.cpp b/mainui/menu_playersetup.cpp index 982f8746..32deab79 100644 --- a/mainui/menu_playersetup.cpp +++ b/mainui/menu_playersetup.cpp @@ -479,7 +479,7 @@ static void UI_PlayerSetup_Init( void ) UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.view ); UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.name ); - if( !gMenu.m_gameinfo.flags & GFL_NOMODELS ) + if( !( gMenu.m_gameinfo.flags & GFL_NOMODELS )) { UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.model ); UI_AddItem( &uiPlayerSetup.menu, (void *)&uiPlayerSetup.topColor );