Permalink
Browse files

mint-arena: Add cg_weaponFov cvar

Draw view weapon in a separate scene with it's own field of view.
This allows increasing the world FOV without screwing up the weapon
position.

cg_weaponFov defaults to 90 so the weapon stays on the screen as
expected. Setting cg_weaponFov to 0 will use value from cg_fov like
vanilla Q3.
  • Loading branch information...
zturtleman committed Feb 15, 2017
1 parent 8681f9b commit e1174e390b2718f2e6288f6cbe0ed39747d99bae
Showing with 58 additions and 30 deletions.
  1. +3 −0 code/cgame/cg_draw.c
  2. +6 −2 code/cgame/cg_local.h
  3. +2 −0 code/cgame/cg_main.c
  4. +32 −21 code/cgame/cg_view.c
  5. +15 −7 code/cgame/cg_weapons.c
View
@@ -3026,6 +3026,9 @@ void CG_DrawActive( stereoFrame_t stereoView ) {
// draw 3D view
trap_R_RenderScene( &cg.refdef );
// draw the 3D view weapon
CG_DrawViewWeapon( &cg.cur_lc->predictedPlayerState );
// draw status bar and other floating elements
CG_Draw2D(stereoView);
View
@@ -734,7 +734,7 @@ typedef struct {
// view rendering
refdef_t refdef;
vec3_t refdefViewAngles; // will be converted to refdef.viewaxis
float fov; // either range checked cg_fov or forced value
float viewWeaponFov; // either range checked cg_weaponFov or forced value
// first person view pos, set even when rendering third person view
vec3_t firstPersonViewOrg;
@@ -1361,6 +1361,7 @@ extern vmCvar_t cg_ignore;
extern vmCvar_t cg_simpleItems;
extern vmCvar_t cg_fov;
extern vmCvar_t cg_zoomFov;
extern vmCvar_t cg_weaponFov;
extern vmCvar_t cg_splitviewVertical;
extern vmCvar_t cg_splitviewThirdEqual;
extern vmCvar_t cg_splitviewTextScale;
@@ -1532,9 +1533,12 @@ void CG_SetupFrustum( void );
qboolean CG_CullPoint( vec3_t pt );
qboolean CG_CullPointAndRadius( const vec3_t pt, vec_t radius );
qboolean CG_CalcFov( refdef_t *refdef, qboolean viewWeapon );
void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback );
//
// cg_drawtools.c
//
@@ -1735,7 +1739,7 @@ void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean fles
void CG_RailTrail( playerInfo_t *pi, vec3_t start, vec3_t end );
void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi );
void CG_AddViewWeapon (playerState_t *ps);
void CG_DrawViewWeapon (playerState_t *ps );
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team );
void CG_DrawWeaponSelect( void );
View
@@ -200,6 +200,7 @@ vmCvar_t cg_ignore;
vmCvar_t cg_simpleItems;
vmCvar_t cg_fov;
vmCvar_t cg_zoomFov;
vmCvar_t cg_weaponFov;
vmCvar_t cg_splitviewVertical;
vmCvar_t cg_splitviewThirdEqual;
vmCvar_t cg_splitviewTextScale;
@@ -335,6 +336,7 @@ static cvarTable_t cgameCvarTable[] = {
{ &cg_ignore, "cg_ignore", "0", 0, RANGE_ALL }, // used for debugging
{ &cg_zoomFov, "cg_zoomfov", "22.5", CVAR_ARCHIVE, RANGE_FLOAT(1, 160) },
{ &cg_fov, "cg_fov", "90", CVAR_ARCHIVE, RANGE_FLOAT(1, 160) },
{ &cg_weaponFov, "cg_weaponFov", "90", CVAR_ARCHIVE, RANGE_FLOAT( 0, 160 ) },
{ &cg_viewsize, "cg_viewsize", "100", CVAR_ARCHIVE, RANGE_INT( 30, 100 ) },
{ &cg_shadows, "cg_shadows", "1", CVAR_ARCHIVE, RANGE_ALL },
{ &cg_gibs, "cg_gibs", "1", CVAR_ARCHIVE, RANGE_BOOL },
View
@@ -560,7 +560,7 @@ Fixed fov at intermissions, otherwise account for fov variable and zooms.
#define WAVE_AMPLITUDE 1
#define WAVE_FREQUENCY 0.4
static int CG_CalcFov( void ) {
qboolean CG_CalcFov( refdef_t *refdef, qboolean viewWeapon ) {
float x;
float phase;
float v;
@@ -571,17 +571,27 @@ static int CG_CalcFov( void ) {
if ( cg.cur_lc->predictedPlayerState.pm_type == PM_INTERMISSION ) {
// if in intermission, use a fixed value
cg.fov = fov_x = 90;
fov_x = 90;
if ( viewWeapon ) {
cg.viewWeaponFov = fov_x;
}
} else {
// user selectable
if ( cgs.dmflags & DF_FIXED_FOV ) {
// dmflag to prevent wide fov for all players
fov_x = 90;
} else {
fov_x = cg_fov.value;
if ( viewWeapon && cg_weaponFov.value > 0 ) {
fov_x = cg_weaponFov.value;
} else {
fov_x = cg_fov.value;
}
}
cg.fov = fov_x;
if ( viewWeapon ) {
cg.viewWeaponFov = fov_x;
}
// account for zooms
zoomFov = cg_zoomFov.value;
@@ -605,41 +615,43 @@ static int CG_CalcFov( void ) {
// Based on LordHavoc's code for Darkplaces
// http://www.quakeworld.nu/forum/topic/53/what-does-your-qw-look-like/page/30
const float baseAspect = 0.75f; // 3/4
const float aspect = (float)cg.refdef.width/(float)cg.refdef.height;
const float aspect = (float)refdef->width/(float)refdef->height;
const float desiredFov = fov_x;
fov_x = atan( tan( desiredFov*M_PI / 360.0f ) * baseAspect*aspect )*360.0f / M_PI;
}
x = cg.refdef.width / tan( fov_x / 360 * M_PI );
fov_y = atan2( cg.refdef.height, x );
x = refdef->width / tan( fov_x / 360 * M_PI );
fov_y = atan2( refdef->height, x );
fov_y = fov_y * 360 / M_PI;
// warp if underwater
contents = CG_PointContents( cg.refdef.vieworg, -1 );
contents = CG_PointContents( refdef->vieworg, -1 );
if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ){
phase = cg.time / 1000.0 * WAVE_FREQUENCY * M_PI * 2;
v = WAVE_AMPLITUDE * sin( phase );
fov_x += v;
fov_y -= v;
cg.refdef.rdflags |= RDF_UNDERWATER;
refdef->rdflags |= RDF_UNDERWATER;
}
else {
cg.refdef.rdflags &= ~RDF_UNDERWATER;
refdef->rdflags &= ~RDF_UNDERWATER;
}
// set it
cg.refdef.fov_x = fov_x;
cg.refdef.fov_y = fov_y;
refdef->fov_x = fov_x;
refdef->fov_y = fov_y;
if ( !cg.cur_lc->zoomed ) {
cg.cur_lc->zoomSensitivity = 1;
} else {
cg.cur_lc->zoomSensitivity = cg.refdef.fov_y / 75.0;
if ( !viewWeapon ) {
if ( !cg.cur_lc->zoomed ) {
cg.cur_lc->zoomSensitivity = 1;
} else {
cg.cur_lc->zoomSensitivity = cg.refdef.fov_y / 75.0;
}
}
return (cg.refdef.rdflags & RDF_UNDERWATER);
return (refdef->rdflags & RDF_UNDERWATER) ? qtrue : qfalse;
}
@@ -763,7 +775,7 @@ static int CG_CalcViewValues( void ) {
angles[ROLL] = 0;
VectorCopy(angles, cg.refdefViewAngles);
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
return CG_CalcFov();
return CG_CalcFov( &cg.refdef, qfalse );
} else {
cg.cameraMode = qfalse;
}
@@ -774,7 +786,7 @@ static int CG_CalcViewValues( void ) {
VectorCopy( ps->origin, cg.refdef.vieworg );
VectorCopy( ps->viewangles, cg.refdefViewAngles );
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
return CG_CalcFov();
return CG_CalcFov( &cg.refdef, qfalse );
}
cg.bobcycle = ( ps->bobCycle & 128 ) >> 7;
@@ -833,7 +845,7 @@ static int CG_CalcViewValues( void ) {
cg.cur_lc->lastViewAngles[ROLL] = cg.refdefViewAngles[ROLL];
// field of view
return CG_CalcFov();
return CG_CalcFov( &cg.refdef, qfalse );
}
@@ -1114,7 +1126,6 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
CG_AddLocalEntities();
CG_AddAtmosphericEffects();
}
CG_AddViewWeapon( &cg.cur_lc->predictedPlayerState );
// finish up the rest of the refdef
if ( cg.testModelEntity.hModel ) {
View
@@ -1352,12 +1352,13 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
/*
==============
CG_AddViewWeapon
CG_DrawViewWeapon
Add the weapon, and flash for the player's view
Draw the weapon and flash for the player's view
==============
*/
void CG_AddViewWeapon( playerState_t *ps ) {
void CG_DrawViewWeapon( playerState_t *ps ) {
refdef_t refdef;
refEntity_t hand;
centity_t *cent;
playerInfo_t *pi;
@@ -1398,14 +1399,19 @@ void CG_AddViewWeapon( playerState_t *ps ) {
return;
}
// copy world refdef and set weapon field of view.
refdef = cg.refdef;
refdef.rdflags = RDF_NOWORLDMODEL;
CG_CalcFov( &refdef, qtrue );
VectorClear(fovOffset);
if ( cg.fov > 90 ) {
if ( cg.viewWeaponFov > 90 ) {
// drop gun lower at higher fov
fovOffset[2] = -0.2 * ( cg.fov - 90 ) * cg.refdef.fov_x / cg.fov;
} else if ( cg.fov < 90 ) {
fovOffset[2] = -0.2 * ( cg.viewWeaponFov - 90 ) * cg.refdef.fov_x / cg.viewWeaponFov;
} else if ( cg.viewWeaponFov < 90 ) {
// move gun forward at lowerer fov
fovOffset[0] = -0.2 * ( cg.fov - 90 ) * cg.refdef.fov_x / cg.fov;
fovOffset[0] = -0.2 * ( cg.viewWeaponFov - 90 ) * cg.refdef.fov_x / cg.viewWeaponFov;
}
cent = &cg.cur_lc->predictedPlayerEntity; // &cg_entities[cg.snap->ps.playerNum];
@@ -1441,6 +1447,8 @@ void CG_AddViewWeapon( playerState_t *ps ) {
// add everything onto the hand
CG_AddPlayerWeapon( &hand, ps, &cg.cur_lc->predictedPlayerEntity, ps->persistant[PERS_TEAM] );
trap_R_RenderScene( &refdef );
}
/*

1 comment on commit e1174e3

@KuehnhammerTobias

This comment has been minimized.

Show comment
Hide comment
@KuehnhammerTobias

KuehnhammerTobias Feb 17, 2017

Contributor

I think these changes are breaking the correct lightning of the (weapon) view model -> not lightmapped anymore (trap_R_RenderScene/RDF_NOWORLDMODEL).

Contributor

KuehnhammerTobias commented on e1174e3 Feb 17, 2017

I think these changes are breaking the correct lightning of the (weapon) view model -> not lightmapped anymore (trap_R_RenderScene/RDF_NOWORLDMODEL).

Please sign in to comment.