From e70e9a88d8b092245509e015b9c53a2bea8f4b49 Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Fri, 25 Mar 2022 09:10:24 +0100 Subject: [PATCH] initial freelook implementation, rendering part (#472) * initial freelook implementation, rendering part * fix freelook for different view sizes * simplify implementation * correct view angle for different screen sizes * implement view angle centering * go the cmd->look route * mouselook config toggle and key binding * remove unnecessary restriction * save mouselook in config file * enable vertical mouse by default * remove obsolete comments * do not center view when hitting ground anymore * sprite clipping optimizations * center player view in G_PlayerReborn() * Revert "center player view in G_PlayerReborn()" This reverts commit b307511ac27781adb9173e2c108e71c57993cebc. * minor simplification --- Source/d_player.h | 4 ++++ Source/d_ticcmd.h | 2 ++ Source/g_game.c | 18 +++++++++++++++++- Source/g_game.h | 1 + Source/m_input.h | 2 ++ Source/m_menu.c | 14 +++++++++++--- Source/m_misc.c | 17 ++++++++++++++++- Source/p_inter.c | 2 ++ Source/p_telept.c | 4 ++++ Source/p_user.c | 31 +++++++++++++++++++++++++++++++ Source/r_data.h | 6 ++++++ Source/r_main.c | 29 ++++++++++++++++++++++++++--- Source/r_main.h | 1 + Source/r_plane.c | 2 +- Source/r_plane.h | 2 +- Source/r_things.c | 7 +++++-- 16 files changed, 130 insertions(+), 12 deletions(-) diff --git a/Source/d_player.h b/Source/d_player.h index 217e8f71..d19746e4 100644 --- a/Source/d_player.h +++ b/Source/d_player.h @@ -178,6 +178,10 @@ typedef struct player_s // [Woof!] show centered "A secret is revealed!" message char* centermessage; + // [crispy] free look / mouse look + int lookdir, oldlookdir; + boolean centering; + } player_t; diff --git a/Source/d_ticcmd.h b/Source/d_ticcmd.h index 8366b21c..bfdbfb1b 100644 --- a/Source/d_ticcmd.h +++ b/Source/d_ticcmd.h @@ -44,6 +44,8 @@ typedef struct short consistancy; // checks for net game byte chatchar; byte buttons; + + int lookdir; } ticcmd_t; #endif diff --git a/Source/g_game.c b/Source/g_game.c index 3e1520e9..d35e5574 100644 --- a/Source/g_game.c +++ b/Source/g_game.c @@ -124,6 +124,7 @@ boolean haswolflevels = false;// jff 4/18/98 wolf levels present byte *savebuffer; int autorun = false; // always running? // phares int novert = false; +int mouselook = false; int default_complevel; @@ -311,6 +312,13 @@ void G_BuildTiccmd(ticcmd_t* cmd) else tspeed = speed; + // [crispy] mouse look + if (mouselook == -1) + { + mouselook = 0; + cmd->lookdir = TOCENTER; + } + // turn 180 degrees in one keystroke? // phares // | if (M_InputGameActive(input_reverse)) // V @@ -472,7 +480,12 @@ void G_BuildTiccmd(ticcmd_t* cmd) cmd->buttons |= BT_USE; } - if (!novert) + // [crispy] mouse look + if (mouselook) + { + cmd->lookdir = mousey; + } + else if (!novert) { forward += mousey; } @@ -969,6 +982,9 @@ static void G_PlayerFinishLevel(int player) p->fixedcolormap = 0; // cancel ir gogles p->damagecount = 0; // no palette changes p->bonuscount = 0; + // [crispy] reset additional player properties + p->oldlookdir = p->lookdir = 0; + p->centering = false; } // [crispy] format time for level statistics diff --git a/Source/g_game.h b/Source/g_game.h index 7eb1ca13..9ba0ae26 100644 --- a/Source/g_game.h +++ b/Source/g_game.h @@ -79,6 +79,7 @@ extern int key_enter; extern int key_help; extern int autorun; // always running? // phares extern int novert; +extern int mouselook; extern int defaultskill; //jff 3/24/98 default skill extern boolean haswolflevels; //jff 4/18/98 wolf levels present diff --git a/Source/m_input.h b/Source/m_input.h index adf4b5e8..f575046d 100644 --- a/Source/m_input.h +++ b/Source/m_input.h @@ -46,6 +46,8 @@ enum input_prevweapon, input_nextweapon, + input_mouselook, + input_weapon1, input_weapon2, input_weapon3, diff --git a/Source/m_menu.c b/Source/m_menu.c index b59ba58a..968c6866 100644 --- a/Source/m_menu.c +++ b/Source/m_menu.c @@ -2741,10 +2741,11 @@ setup_menu_t keys_settings1[] = // Key Binding screen strings {"STRAFE" ,S_INPUT ,m_scrn,KB_X,KB_Y+9*8,{0},input_strafe}, {"AUTORUN" ,S_INPUT ,m_scrn,KB_X,KB_Y+10*8,{0},input_autorun}, {"VERTICAL MOUSE",S_INPUT ,m_scrn,KB_X,KB_Y+11*8,{0},input_novert}, + {"MOUSELOOK" ,S_INPUT ,m_scrn,KB_X,KB_Y+12*8,{0},input_mouselook}, - {"TURN LEFT" ,S_INPUT ,m_scrn,KB_X,KB_Y+13*8,{0},input_turnleft}, - {"TURN RIGHT" ,S_INPUT ,m_scrn,KB_X,KB_Y+14*8,{0},input_turnright}, - {"180 TURN" ,S_INPUT ,m_scrn,KB_X,KB_Y+15*8,{0},input_reverse}, + {"TURN LEFT" ,S_INPUT ,m_scrn,KB_X,KB_Y+14*8,{0},input_turnleft}, + {"TURN RIGHT" ,S_INPUT ,m_scrn,KB_X,KB_Y+15*8,{0},input_turnright}, + {"180 TURN" ,S_INPUT ,m_scrn,KB_X,KB_Y+16*8,{0},input_reverse}, // Button for resetting to defaults {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, @@ -4903,6 +4904,13 @@ boolean M_Responder (event_t* ev) // return true; // [FG] don't let toggles eat keys } + if (M_InputActivated(input_mouselook)) + { + mouselook = mouselook ? -1 : 1; + dprintf("Mouselook %s", mouselook == 1 ? "On" : "Off"); + // return true; // [FG] don't let toggles eat keys + } + if (ch == key_help) // Help key { M_StartControlPanel (); diff --git a/Source/m_misc.c b/Source/m_misc.c index 55db58b1..2cda559e 100644 --- a/Source/m_misc.c +++ b/Source/m_misc.c @@ -380,7 +380,7 @@ default_t defaults[] = { { //jff 4/3/98 allow unlimited sensitivity "mouse_sensitivity_vert", (config_t *) &mouseSensitivity_vert, NULL, - {0}, {0,UL}, number, ss_none, wad_no, + {10}, {0,UL}, number, ss_none, wad_no, "adjust vertical (y) mouse sensitivity" }, @@ -433,6 +433,13 @@ default_t defaults[] = { "1 to disable vertical mouse movement" }, + { + "mouselook", + (config_t *) &mouselook, NULL, + {0}, {0,1}, number, ss_none, wad_no, + "1 to enable mouselook" + }, + { // killough 2/21/98: default to 10 "screenblocks", (config_t *) &screenblocks, NULL, @@ -685,6 +692,14 @@ default_t defaults[] = { input_backward, { {input_type_key, 's'}, {input_type_key, KEYD_DOWNARROW} } }, + { + "input_mouselook", + NULL, NULL, + {0}, {UL,UL}, input, ss_keys, wad_no, + "key to toggle mouselook", + input_mouselook, { {0, 0} } + }, + { // phares 3/7/98 "input_menu_right", NULL, NULL, diff --git a/Source/p_inter.c b/Source/p_inter.c index e71136fb..cbfd3c22 100644 --- a/Source/p_inter.c +++ b/Source/p_inter.c @@ -702,6 +702,8 @@ static void P_KillMobj(mobj_t *source, mobj_t *target) target->flags &= ~MF_SOLID; target->player->playerstate = PST_DEAD; P_DropWeapon (target->player); + // [crispy] center view when dying + target->player->centering = true; if (target->player == &players[consoleplayer] && automapactive) if (!demoplayback) // killough 11/98: don't switch out in demos, though diff --git a/Source/p_telept.c b/Source/p_telept.c index d4ef88be..daa362d3 100644 --- a/Source/p_telept.c +++ b/Source/p_telept.c @@ -79,7 +79,11 @@ int EV_Teleport(line_t *line, int side, mobj_t *thing) } if (player) + { player->viewz = thing->z + player->viewheight; + // [crispy] center view after teleporting + player->centering = true; + } // spawn teleport fog and emit sound at source S_StartSound(P_SpawnMobj(oldx, oldy, oldz, MT_TFOG), sfx_telept); diff --git a/Source/p_user.c b/Source/p_user.c index 68229a38..42035964 100644 --- a/Source/p_user.c +++ b/Source/p_user.c @@ -231,6 +231,18 @@ void P_MovePlayer (player_t* player) (mo->state == states+S_PLAY)) P_SetMobjState(mo,S_PLAY_RUN1); } + + // [crispy] apply lookdir delta + if (cmd->lookdir == TOCENTER) + { + player->centering = true; + } + else if (!menuactive && !demoplayback) + { + player->lookdir = BETWEEN(-LOOKDIRMIN * MLOOKUNIT, + LOOKDIRMAX * MLOOKUNIT, + player->lookdir + cmd->lookdir); + } } #define ANG5 (ANG90/18) @@ -312,6 +324,7 @@ void P_PlayerThink (player_t* player) player->mo->oldz = player->mo->z; player->mo->oldangle = player->mo->angle; player->oldviewz = player->viewz; + player->oldlookdir = player->lookdir; // killough 2/8/98, 3/21/98: // (this code is necessary despite questions raised elsewhere in a comment) @@ -332,6 +345,24 @@ void P_PlayerThink (player_t* player) player->mo->flags &= ~MF_JUSTATTACKED; } + // [crispy] center view + if (player->centering) + { + if (player->lookdir > 0) + { + player->lookdir -= 8 * MLOOKUNIT; + } + else if (player->lookdir < 0) + { + player->lookdir += 8 * MLOOKUNIT; + } + if (abs(player->lookdir) < 8 * MLOOKUNIT) + { + player->lookdir = 0; + player->centering = false; + } + } + if (player->playerstate == PST_DEAD) { P_DeathThink (player); diff --git a/Source/r_data.h b/Source/r_data.h index 00ee64cd..23b5beef 100644 --- a/Source/r_data.h +++ b/Source/r_data.h @@ -33,6 +33,12 @@ #include "r_defs.h" #include "r_state.h" +#define LOOKDIRMIN 110 // [crispy] -110, actually +#define LOOKDIRMAX 90 +#define LOOKDIRS (LOOKDIRMIN+1+LOOKDIRMAX) // [crispy] lookdir range: -110..0..90 +#define MLOOKUNIT 8 +#define TOCENTER INT_MIN + // Retrieve column data for span blitting. byte *R_GetColumn(int tex, int col); byte *R_GetColumnMod(int tex, int col); diff --git a/Source/r_main.c b/Source/r_main.c index 86486711..5d367687 100644 --- a/Source/r_main.c +++ b/Source/r_main.c @@ -57,6 +57,7 @@ angle_t viewangle; fixed_t viewcos, viewsin; player_t *viewplayer; extern lighttable_t **walllights; +fixed_t viewheightfrac; // [FG] sprite clipping optimizations // // precalculated math tables @@ -356,6 +357,8 @@ void R_InitLightTables (void) boolean setsizeneeded; int setblocks; +static int viewblocks; + void R_SetViewSize(int blocks) { setsizeneeded = true; @@ -368,7 +371,7 @@ void R_SetViewSize(int blocks) void R_ExecuteSetViewSize (void) { - int i; + int i, j; setsizeneeded = false; @@ -408,12 +411,15 @@ void R_ExecuteSetViewSize (void) viewheight = scaledviewheight << hires; // killough 11/98 viewwidth_nonwide = scaledviewwidth_nonwide << hires; + viewblocks = MIN(setblocks, 10) << hires; + centery = viewheight/2; centerx = viewwidth/2; centerxfrac = centerx<mo->oldy + FixedMul(player->mo->y - player->mo->oldy, fractionaltic); viewz = player->oldviewz + FixedMul(player->viewz - player->oldviewz, fractionaltic); viewangle = R_InterpolateAngle(player->mo->oldangle, player->mo->angle, fractionaltic) + viewangleoffset; + lookdir = (player->oldlookdir + (player->lookdir - player->oldlookdir) * FIXED2DOUBLE(fractionaltic)) / MLOOKUNIT; } else { @@ -562,9 +575,19 @@ void R_SetupFrame (player_t *player) viewy = player->mo->y; viewz = player->viewz; // [FG] moved here viewangle = player->mo->angle + viewangleoffset; + lookdir = player->lookdir / MLOOKUNIT; } extralight = player->extralight; + // apply new yslope[] whenever "lookdir", "viewheight" or "hires" change + tempCentery = viewheight/2 + lookdir * viewblocks / 10; + if (centery != tempCentery) + { + centery = tempCentery; + centeryfrac = centery << FRACBITS; + yslope = yslopes[LOOKDIRMIN + lookdir]; + } + viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; diff --git a/Source/r_main.h b/Source/r_main.h index 32bfda2f..59477b30 100644 --- a/Source/r_main.h +++ b/Source/r_main.h @@ -48,6 +48,7 @@ extern fixed_t projection; extern int validcount; extern int linecount; extern int loopcount; +extern fixed_t viewheightfrac; // [FG] sprite clipping optimizations // // Rendering stats diff --git a/Source/r_plane.c b/Source/r_plane.c index 0567a474..f72fcc25 100644 --- a/Source/r_plane.c +++ b/Source/r_plane.c @@ -94,7 +94,7 @@ static fixed_t cachedxstep[MAX_SCREENHEIGHT]; static fixed_t cachedystep[MAX_SCREENHEIGHT]; static fixed_t xoffs,yoffs; // killough 2/28/98: flat offsets -fixed_t yslope[MAX_SCREENHEIGHT], distscale[MAX_SCREENWIDTH]; +fixed_t *yslope, yslopes[LOOKDIRS][MAX_SCREENHEIGHT], distscale[MAX_SCREENWIDTH]; // // R_InitPlanes diff --git a/Source/r_plane.h b/Source/r_plane.h index a4044c0d..1215ca7c 100644 --- a/Source/r_plane.h +++ b/Source/r_plane.h @@ -38,7 +38,7 @@ extern int *lastopening; // [FG] 32-bit integer math extern int floorclip[], ceilingclip[]; // [FG] 32-bit integer math -extern fixed_t yslope[], distscale[]; +extern fixed_t *yslope, yslopes[LOOKDIRS][MAX_SCREENHEIGHT], distscale[]; void R_InitPlanes(void); void R_ClearPlanes(void); diff --git a/Source/r_things.c b/Source/r_things.c index 7d4d8a03..ab756328 100644 --- a/Source/r_things.c +++ b/Source/r_things.c @@ -542,8 +542,8 @@ void R_ProjectSprite (mobj_t* thing) gzt = interpz + spritetopoffset[lump]; // killough 4/9/98: clip things which are out of view due to height - if (interpz > viewz + FixedDiv(centeryfrac, xscale) || - gzt < viewz - FixedDiv(centeryfrac-viewheight, xscale)) + if (interpz > viewz + FixedDiv(viewheightfrac, xscale) || + gzt < (int64_t)viewz - FixedDiv(viewheightfrac - viewheight, xscale)) return; // killough 3/27/98: exclude things totally separated @@ -730,6 +730,9 @@ void R_DrawPSprite (pspdef_t *psp) vis->startfrac = 0; } + // [crispy] free look + vis->texturemid += (centery - viewheight/2) * pspriteiscale; + if (vis->x1 > x1) vis->startfrac += vis->xiscale*(vis->x1-x1);