Client: add camera.qc and viewmodel.qc, better restructure how we apply

effects to the view. Add CVARs v_cambob, v_camroll, v_bobstyle...
This commit is contained in:
Marco Cawthorne 2021-07-19 08:36:19 +02:00
parent 37c5c6efdd
commit affa7b4a0c
5 changed files with 239 additions and 62 deletions

79
src/client/camera.qc Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct
{
float m_flSpeed;
float m_flFracSin;
float m_flTime;
float m_flMove;
float m_flDelta;
int m_iCycle;
} g_camBobVars[4], *pCamBob;
/* tilts the camera for a head-bob like effect when moving */
void
Camera_RunBob(__inout vector camera_angle)
{
if (!autocvar(v_cambob, 0, "Enables bobbing effect for the first-person camera"))
return;
int s = (float)getproperty(VF_ACTIVESEAT);
pCamBob = &g_camBobVars[s];
/* we don't really care about the vertical velocity */
vector speed = pSeat->m_vecPredictedVelocity;
speed[2] = 0.0f;
pCamBob->m_flSpeed = vlen(speed);
/* don't bother on low speeds */
if ( pCamBob->m_flSpeed < 5.0f ) {
pCamBob->m_flMove = 0.0f;
pCamBob->m_flTime = 0.0f; /* progress has halted, start anew */
return;
} else if (pSeat->m_ePlayer.flags & FL_ONGROUND) {
pCamBob->m_flMove = clframetime * (pCamBob->m_flSpeed * 0.01);
}
pCamBob->m_flTime = (pCamBob->m_flTime += pCamBob->m_flMove);
pCamBob->m_flFracSin = fabs(sin(pCamBob->m_flTime * M_PI));
pCamBob->m_iCycle = (int)pCamBob->m_flTime;
pCamBob->m_flDelta = (pCamBob->m_flFracSin * 0.0025f) * pCamBob->m_flSpeed;
camera_angle[0] += pCamBob->m_flDelta;
if (pCamBob->m_iCycle & 1) {
pCamBob->m_flDelta = -pCamBob->m_flDelta;
}
camera_angle[2] += pCamBob->m_flDelta;
}
/* applies a tilt to the camera for when we're strafing left to right */
float
Camera_StrafeRoll(__inout vector camera_angle)
{
if (!autocvar(v_camroll, 1, "Enables strafe-roll for the first-person camera"))
return;
float roll;
makevectors(camera_angle);
roll = dotproduct(pSeat->m_vecPredictedVelocity, v_right);
roll *= 0.015f;
camera_angle[2] += roll;
}

View File

@ -35,14 +35,9 @@ var float FONT_20;
var float FONT_CON;
/* clientside cvars */
var float autocvar_cl_bob = 0;
var float autocvar_v_bob = 0.01;
var float autocvar_v_bobcycle = 0.8;
var float autocvar_v_bobup = 0.5;
var float autocvar_zoom_sensitivity = 1.0f;
var int autocvar_cl_smoothstairs = TRUE;
var int autocvar_cl_thirdperson = FALSE;
var int autocvar_v_bobclassic = TRUE;
var int autocvar_v_lefthanded = FALSE;
var string autocvar_cl_logofile = "lambda";
var vector autocvar_cl_logocolor = [255,0,0];
@ -134,8 +129,6 @@ struct
int m_iLastWeapon;
int m_iOldWeapon;
float m_flBobTime;
float m_flBob;
/* damage overlay */
float m_flDamageAlpha;

View File

@ -15,6 +15,8 @@ predict.qc
npc.qc
entities.qc
modelevent.qc
camera.qc
viewmodel.qc
view.qc
damage.qc
chat.qc

View File

@ -14,8 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_v_camroll = TRUE;
void
View_Init(void)
{
@ -58,7 +56,7 @@ View_AddEvent(void(void) pCallback, float flTime)
pSeat->m_flEventMdl = pSeat->m_eViewModel.modelindex;
}
void
void
View_CalcViewport(int s, float fWinWidth, float fWinHeight)
{
//FIXME: this is awkward. renderscene internally rounds to pixels.
@ -96,45 +94,6 @@ View_CalcViewport(int s, float fWinWidth, float fWinHeight)
}
}
void
View_CalcBob(void)
{
float cycle;
vector vel;
if (self.flags & FL_ONGROUND == -1) {
return;
}
pSeat->m_flBobTime += clframetime;
cycle = pSeat->m_flBobTime - (int)(pSeat->m_flBobTime / autocvar_v_bobcycle) * autocvar_v_bobcycle;
cycle /= autocvar_v_bobcycle;
if (cycle < autocvar_v_bobup) {
cycle = MATH_PI * cycle / autocvar_v_bobup;
} else {
cycle = MATH_PI + MATH_PI * (cycle - autocvar_v_bobup)/(1.0 - autocvar_v_bobup);
}
vel = pSeat->m_vecPredictedVelocity;
vel[2] = 0;
float flBob = sqrt(vel[0] * vel[0] + vel[1] * vel[1]) * autocvar_v_bob;
flBob = flBob * 0.3 + flBob * 0.7 * sin(cycle);
pSeat->m_flBob = bound(-7, flBob, 4);
}
float
View_CalcRoll(void)
{
float roll;
makevectors(view_angles);
roll = dotproduct(pSeat->m_vecPredictedVelocity, v_right);
roll *= 0.015f;
return autocvar_v_camroll ? roll : 0;
}
/*
====================
View_DrawViewModel
@ -159,13 +118,12 @@ View_DrawViewModel(void)
return;
}
View_CalcBob();
View_UpdateWeapon(m_eViewModel, m_eMuzzleflash);
float fBaseTime2 = m_eViewModel.frame1time;
float fBaseTime = m_eViewModel.frame1time;
m_eViewModel.frame2time = pl.weapontime;
m_eViewModel.frame1time = pl.weapontime;
m_eViewModel.frame1time = pl.weapontime;
Event_Callback(m_eViewModel.frame1time, fBaseTime2);
processmodelevents(m_eViewModel.modelindex, m_eViewModel.frame, fBaseTime,
m_eViewModel.frame1time, ClientGame_ModelEvent);
@ -174,20 +132,12 @@ View_DrawViewModel(void)
m_eViewModel.angles = view_angles;
m_eViewModel.colormap = pSeat->m_ePlayer.colormap;
// Give the gun a tilt effect like in old HL/CS versions
if (autocvar_v_bobclassic == 1) {
m_eViewModel.angles[2] = -pSeat->m_flBob;
}
/* now apply the scale hack */
m_eViewModel.scale = autocvar_r_viewmodelscale;
pSeat->m_flBob *= autocvar_r_viewmodelscale;
m_eViewModel.origin = pSeat->m_vecPredictedOrigin + pl.view_ofs;
m_eViewModel.origin += [0,0,-1] + (v_forward * (pSeat->m_flBob * 0.4))
+ (v_forward * autocvar_v_gunofs[0])
+ (v_right * autocvar_v_gunofs[1])
+ (v_up * autocvar_v_gunofs[2]);
Viewmodel_CalcBob();
Viewmodel_ApplyBob(m_eViewModel);
// Left-handed weapons
if (autocvar_v_lefthanded) {
@ -220,7 +170,8 @@ View_DrawViewModel(void)
}
if (pl.movetype == MOVETYPE_WALK) {
view_angles[2] = View_CalcRoll();
Camera_StrafeRoll(view_angles);
Camera_RunBob(view_angles);
setproperty(VF_ANGLES, view_angles + pl.punchangle);
}
}

152
src/client/viewmodel.qc Normal file
View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var float autocvar_v_bob = 0.01;
var float autocvar_v_bobcycle = 0.8;
var float autocvar_v_bobup = 0.5;
var int autocvar_v_bobstyle = 1;
enum
{
BOB_NONE,
BOB_CLASSIC,
BOB_VISIONS
};
struct
{
float m_flBobTime;
float m_flBob;
float m_flBobCycle;
float m_flSpeed;
} g_viewBobVars[4], *pViewBob;
/* classic bob, similar to Q1 and HL */
void
Viewmodel_ClassicBobCalc(void)
{
vector vel;
pViewBob->m_flBobTime += clframetime;
pViewBob->m_flBobCycle = pViewBob->m_flBobTime - (int)(pViewBob->m_flBobTime / autocvar_v_bobcycle) * autocvar_v_bobcycle;
pViewBob->m_flBobCycle /= autocvar_v_bobcycle;
if (pViewBob->m_flBobCycle < autocvar_v_bobup) {
pViewBob->m_flBobCycle = MATH_PI * pViewBob->m_flBobCycle / autocvar_v_bobup;
} else {
pViewBob->m_flBobCycle = MATH_PI + MATH_PI * (pViewBob->m_flBobCycle - autocvar_v_bobup)/(1.0 - autocvar_v_bobup);
}
vel = pSeat->m_vecPredictedVelocity;
vel[2] = 0;
pViewBob->m_flSpeed = vlen(vel);
float flBob = pViewBob->m_flSpeed * autocvar_v_bob;
flBob = flBob * 0.3 + flBob * 0.7 * sin(pViewBob->m_flBobCycle);
pViewBob->m_flBob = bound(-7, flBob, 4);
}
void
Viewmodel_ClassicBobRun(entity gun)
{
// Give the gun a tilt effect like in old HL/CS versions
if (autocvar(v_bobclassic, 1, "Viewmodel bob classic tilt switch") == 1) {
gun.angles[2] = -pViewBob->m_flBob;
}
gun.origin += [0,0,-1] + (v_forward * (pViewBob->m_flBob * 0.4))
+ (v_forward * autocvar_v_gunofs[0])
+ (v_right * autocvar_v_gunofs[1])
+ (v_up * autocvar_v_gunofs[2]);
}
/* Vera Visions signature bob */
void
Viewmodel_VisionsBobCalc(void)
{
/* same for now */
Viewmodel_ClassicBobCalc();
}
void
Viewmodel_VisionsBobRun(entity gun)
{
float sintime;
float strength;
gun.angles[2] = -pViewBob->m_flBob;
vector angmod;
angmod[0] += pViewBob->m_flBob * 0.5f;
angmod[1] += pViewBob->m_flBob;
angmod[2] += pViewBob->m_flBob * 2.0f;
gun.angles += angmod * 2.0f;
/* sway with speed */
sintime = sin( time * 1.5f);
strength = pViewBob->m_flSpeed * 0.01f;
gun.angles[0] += strength * sintime;
gun.angles[1] += strength * sintime;
gun.angles[2] += strength * sintime;
gun.origin += [0,0,-1] - (v_up * (-pViewBob->m_flBob * 0.2))
+ (v_forward * autocvar_v_gunofs[0])
+ (v_right * autocvar_v_gunofs[1])
+ (v_up * autocvar_v_gunofs[2]);
}
/* bob vars are calculated separately from application, so that if there's
* more than one viewmodel we won't affect the speed of the bob by running
* the math too many times */
void
Viewmodel_CalcBob(void)
{
int s = (float)getproperty(VF_ACTIVESEAT);
pViewBob = &g_viewBobVars[s];
switch (autocvar_v_bobstyle)
{
case BOB_CLASSIC:
Viewmodel_ClassicBobCalc();
break;
case BOB_VISIONS:
Viewmodel_VisionsBobCalc();
break;
default:
break;
}
/* make sure it's adjusted for scale */
pViewBob->m_flBob *= autocvar_r_viewmodelscale;
}
void
Viewmodel_ApplyBob(entity gun)
{
int s = (float)getproperty(VF_ACTIVESEAT);
pViewBob = &g_viewBobVars[s];
switch (autocvar_v_bobstyle)
{
case BOB_CLASSIC:
Viewmodel_ClassicBobRun(gun);
break;
case BOB_VISIONS:
Viewmodel_VisionsBobRun(gun);
break;
default:
break;
}
}