From: Rudolf Polzer Date: Mon, 7 Mar 2016 21:07:48 +0000 (-0500) Subject: v_yshearing: Make the cvar take the max angle to apply the effect to; remove the... X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=ac239fc6019200f1b20a0057c74986cd67c6a4ef;p=xonotic%2Fdarkplaces.git v_yshearing: Make the cvar take the max angle to apply the effect to; remove the in_pitch hack for this as it is no longer needed then. This makes Y shearing mode actually useful together with higer FOV (less noticeable distortion). --- diff --git a/cl_input.c b/cl_input.c index 91da154c..b70a19ec 100644 --- a/cl_input.c +++ b/cl_input.c @@ -461,24 +461,6 @@ cvar_t cl_nodelta = {0, "cl_nodelta", "0", "disables delta compression of non-pl cvar_t cl_csqc_generatemousemoveevents = {0, "cl_csqc_generatemousemoveevents", "1", "enables calls to CSQC_InputEvent with type 2, for compliance with EXT_CSQC spec"}; extern cvar_t v_flipped; -extern cvar_t v_yshearing; - -static void IN_AddToPitch(float angle) -{ - // In Duke3D mode, aiming up/down looks like scrolling - so let input - // modify the pitch slope instead of the pitch angle to compensate. - // This can be turned off by v_yshearing 2. - if (v_yshearing.integer == 1) - { - float tp = tanf(cl.viewangles[PITCH] * M_PI / 180); - tp += angle * M_PI / 180; - cl.viewangles[PITCH] = atanf(tp) * 180 / M_PI; - } - else - { - cl.viewangles[PITCH] += angle; - } -} /* ================ @@ -505,15 +487,15 @@ static void CL_AdjustAngles (void) if (in_klook.state & 1) { V_StopPitchDrift (); - IN_AddToPitch(-speed*cl_pitchspeed.value * CL_KeyState (&in_forward)); - IN_AddToPitch(speed*cl_pitchspeed.value * CL_KeyState (&in_back)); + cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward); + cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back); } up = CL_KeyState (&in_lookup); down = CL_KeyState(&in_lookdown); - IN_AddToPitch(-speed*cl_pitchspeed.value * up); - IN_AddToPitch(-speed*cl_pitchspeed.value * down); + cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up; + cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down; if (up || down) V_StopPitchDrift (); @@ -679,7 +661,7 @@ void CL_Input (void) cl.cmd.sidemove += m_side.value * in_mouse_x * modulatedsensitivity; else cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * modulatedsensitivity * cl.viewzoom; - IN_AddToPitch(m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom); + cl.viewangles[PITCH] += m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom; } else { @@ -793,12 +775,12 @@ static void CL_UpdatePrydonCursor(void) } if (cl.cmd.cursor_screen[1] < -1) { - IN_AddToPitch(m_pitch.value * (cl.cmd.cursor_screen[1] - -1) * vid.height * sensitivity.value * cl.viewzoom); + cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - -1) * vid.height * sensitivity.value * cl.viewzoom; cl.cmd.cursor_screen[1] = -1; } if (cl.cmd.cursor_screen[1] > 1) { - IN_AddToPitch(m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.height * sensitivity.value * cl.viewzoom); + cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.height * sensitivity.value * cl.viewzoom; cl.cmd.cursor_screen[1] = 1; } */ diff --git a/clvm_cmds.c b/clvm_cmds.c index 8bc2ab98..f43bf7fe 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -725,8 +725,8 @@ void CSQC_R_RecalcView (void) extern matrix4x4_t viewmodelmatrix_nobob; extern matrix4x4_t viewmodelmatrix_withbob; Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.csqc_vieworigin[0], cl.csqc_vieworigin[1], cl.csqc_vieworigin[2], cl.csqc_viewangles[0], cl.csqc_viewangles[1], cl.csqc_viewangles[2], 1); - if (v_yshearing.integer) - Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix); + if (v_yshearing.value > 0) + Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix, v_yshearing.value); Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix); Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value); Matrix4x4_Concat(&viewmodelmatrix_withbob, &r_refdef.view.matrix, &cl.csqc_viewmodelmatrixfromengine); diff --git a/mathlib.c b/mathlib.c index 8f8e7b50..a58d76e8 100644 --- a/mathlib.c +++ b/mathlib.c @@ -549,35 +549,64 @@ void AngleVectorsFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t u } } -void AngleVectorsDuke3DFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up) +void AngleVectorsDuke3DFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up, double maxShearAngle) { - double angle, sr, tp, sy, cr, sgnp, cy; + double angle, sr, sy, cr, cy; + double sxx, sxz, szx, szz; + double cosMaxShearAngle = cos(maxShearAngle * (M_PI*2 / 360)); + double tanMaxShearAngle = tan(maxShearAngle * (M_PI*2 / 360)); angle = angles[YAW] * (M_PI*2 / 360); sy = sin(angle); cy = cos(angle); - angle = ANGLEMOD(angles[PITCH]); - // Avoid hitting tan(M_PI/2 * (2n+1))... - // TODO shouldn't this be a cvar? - // |pitch| <= 90 degrees. - if (angle <= 90 && angle > 80) - angle = 80; - if (angle >= 270 && angle < 280) - angle = 280; - // |pitch| > 90 degrees. - if (angle > 90 && angle < 100) - angle = 100; - if (angle < 270 && angle > 260) - angle = 260; - // Flip the view when "turning over". - sgnp = (angle > 90) && (angle < 270) ? -1.0 : 1.0; - angle *= (M_PI*2 / 360); - tp = tan(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + + // We will calculate a shear matrix pitch = [[sxx sxz][szx szz]]. + + if (fabs(cos(angle)) > cosMaxShearAngle) + { + // Pure shear. Keep the original sign of the coefficients. + sxx = 1; + sxz = 0; + szx = -tan(angle); + szz = 1; + // Covering angle per screen coordinate: + // d/dt arctan((sxz + t*szz) / (sxx + t*szx)) @ t=0 + // d_angle = det(S) / (sxx*sxx + szx*szx) + // = 1 / (1 + tan^2 angle) + // = cos^2 angle. + } + else + { + // A mix of shear and rotation. Implementation-wise, we're + // looking at a capsule, and making the screen surface + // tangential to it... and if we get here, we're looking at the + // two half-spheres of the capsule (and the cylinder part is + // handled above). + double x, y, h, t, d, f; + h = tanMaxShearAngle; + x = cos(angle); + y = sin(angle); + t = h * fabs(y) + sqrt(1 - (h * x) * (h * x)); + sxx = x * t; + sxz = y * t - h * (y > 0 ? 1.0 : -1.0); + szx = -y * t; + szz = x * t; + // BUT: keep the amount of a sphere we see in pitch direction + // invariant. + // Covering angle per screen coordinate: + // d_angle = det(S) / (sxx*sxx + szx*szx) + d = (sxx * szz - sxz * szx) / (sxx * sxx + szx * szx); + f = cosMaxShearAngle * cosMaxShearAngle / d; + sxz *= f; + szz *= f; + } + if (forward) { - forward[0] = cy*sgnp; - forward[1] = sy*sgnp; - forward[2] = -tp; + forward[0] = sxx*cy; + forward[1] = sxx*sy; + forward[2] = szx; } if (left || up) { @@ -588,15 +617,15 @@ void AngleVectorsDuke3DFLU (const vec3_t angles, vec3_t forward, vec3_t left, ve cr = cos(angle); if (left) { - left[0] = cr*-sy; - left[1] = cr*cy; - left[2] = sr*sgnp; + left[0] = sr*sxz*cy+cr*-sy; + left[1] = sr*sxz*sy+cr*cy; + left[2] = sr*szz; } if (up) { - up[0] = -sr*-sy; - up[1] = -sr*cy; - up[2] = cr*sgnp; + up[0] = cr*sxz*cy+-sr*-sy; + up[1] = cr*sxz*sy+-sr*cy; + up[2] = cr*szz; } } else @@ -609,9 +638,9 @@ void AngleVectorsDuke3DFLU (const vec3_t angles, vec3_t forward, vec3_t left, ve } if (up) { - up[0] = 0; - up[1] = 0; - up[2] = sgnp; + up[0] = sxz*cy; + up[1] = sxz*sy; + up[2] = szz; } } } diff --git a/mathlib.h b/mathlib.h index 0aa8d19c..cb674e51 100644 --- a/mathlib.h +++ b/mathlib.h @@ -253,7 +253,7 @@ void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) /// LordHavoc: proper matrix version of AngleVectors void AngleVectorsFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up); /// divVerent: improper matrix version of AngleVectors -void AngleVectorsDuke3DFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up); +void AngleVectorsDuke3DFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up, double maxShearAngle); /// LordHavoc: builds a [3][4] matrix void AngleMatrix (const vec3_t angles, const vec3_t translate, vec_t matrix[][4]); /// LordHavoc: calculates pitch/yaw/roll angles from forward and up vectors diff --git a/matrixlib.c b/matrixlib.c index a26b6f13..911f9ace 100644 --- a/matrixlib.c +++ b/matrixlib.c @@ -890,7 +890,7 @@ void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, doubl } } -void Matrix4x4_QuakeToDuke3D(const matrix4x4_t *in, matrix4x4_t *out) +void Matrix4x4_QuakeToDuke3D(const matrix4x4_t *in, matrix4x4_t *out, double maxShearAngle) { // Sorry - this isn't direct at all. We can't just use an alternative to // Matrix4x4_CreateFromQuakeEntity as in some cases the input for @@ -910,7 +910,7 @@ void Matrix4x4_QuakeToDuke3D(const matrix4x4_t *in, matrix4x4_t *out) scaleleft = VectorNormalizeLength(left); scaleup = VectorNormalizeLength(up); AnglesFromVectors(angles, forward, up, false); - AngleVectorsDuke3DFLU(angles, forward, left, up); + AngleVectorsDuke3DFLU(angles, forward, left, up, maxShearAngle); VectorScale(forward, scaleforward, forward); VectorScale(left, scaleleft, left); VectorScale(up, scaleup, up); diff --git a/matrixlib.h b/matrixlib.h index d15d9ccd..1ab8262d 100644 --- a/matrixlib.h +++ b/matrixlib.h @@ -81,7 +81,7 @@ void Matrix4x4_CreateScale3 (matrix4x4_t *out, double x, double y, double z); // creates a matrix for a quake entity void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, double z, double pitch, double yaw, double roll, double scale); // creates a duke3d view matrix for a quake view matrix ;) -void Matrix4x4_QuakeToDuke3D(const matrix4x4_t *in, matrix4x4_t *out); +void Matrix4x4_QuakeToDuke3D(const matrix4x4_t *in, matrix4x4_t *out, double maxShearAngle); // converts a matrix4x4 to a set of 3D vectors for the 3 axial directions, and the translate void Matrix4x4_ToVectors(const matrix4x4_t *in, vec_t vx[3], vec_t vy[3], vec_t vz[3], vec_t t[3]); diff --git a/view.c b/view.c index f036b7c6..082365d4 100644 --- a/view.c +++ b/view.c @@ -110,7 +110,7 @@ cvar_t v_deathtiltangle = {0, "v_deathtiltangle", "80", "what roll angle to use // Prophecy camera pitchangle by Alexander "motorsep" Zubov cvar_t chase_pitchangle = {CVAR_SAVE, "chase_pitchangle", "55", "chase cam pitch angle"}; -cvar_t v_yshearing = {0, "v_yshearing", "0", "be all out of gum (1 = vertical slope input, 2 = vertical pitch input)"}; +cvar_t v_yshearing = {0, "v_yshearing", "0", "be all out of gum (set this to the maximum angle to allow Y shearing for - try values like 75)"}; float v_dmg_time, v_dmg_roll, v_dmg_pitch; @@ -524,8 +524,8 @@ void V_CalcRefdefUsing (const matrix4x4_t *entrendermatrix, const vec3_t clviewa r_refdef.view.matrix = *entrendermatrix; Matrix4x4_AdjustOrigin(&r_refdef.view.matrix, 0, 0, clstatsviewheight); } - if (v_yshearing.integer) - Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix); + if (v_yshearing.value > 0) + Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix, v_yshearing.value); Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix); Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value); Matrix4x4_Copy(&viewmodelmatrix_withbob, &viewmodelmatrix_nobob); @@ -859,16 +859,16 @@ void V_CalcRefdefUsing (const matrix4x4_t *entrendermatrix, const vec3_t clviewa viewangles[2] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; } Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, vieworg[0], vieworg[1], vieworg[2], viewangles[0], viewangles[1], viewangles[2], 1); - if (v_yshearing.integer) - Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix); + if (v_yshearing.value > 0) + Matrix4x4_QuakeToDuke3D(&r_refdef.view.matrix, &r_refdef.view.matrix, v_yshearing.value); // calculate a viewmodel matrix for use in view-attached entities Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix); Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value); Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix_withbob, gunorg[0], gunorg[1], gunorg[2], gunangles[0], gunangles[1], gunangles[2], cl_viewmodel_scale.value); - if (v_yshearing.integer) - Matrix4x4_QuakeToDuke3D(&viewmodelmatrix_withbob, &viewmodelmatrix_withbob); + if (v_yshearing.value > 0) + Matrix4x4_QuakeToDuke3D(&viewmodelmatrix_withbob, &viewmodelmatrix_withbob, v_yshearing.value); VectorCopy(vieworg, cl.csqc_vieworiginfromengine); VectorCopy(viewangles, cl.csqc_viewanglesfromengine);