v_yshearing: Make the cvar take the max angle to apply the effect to; remove the...
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 7 Mar 2016 21:36:27 +0000 (21:36 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 7 Mar 2016 21:36:27 +0000 (21:36 +0000)
This makes Y shearing mode actually useful together with higer FOV (less
noticeable distortion).

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12247 d7cf8633-e32d-0410-b094-e92efae38249

cl_input.c
clvm_cmds.c
mathlib.c
mathlib.h
matrixlib.c
matrixlib.h
view.c

index 91da154..b70a19e 100644 (file)
@@ -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;
        }
        */
index 8bc2ab9..f43bf7f 100644 (file)
@@ -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);
index 8f8e7b5..a58d76e 100644 (file)
--- 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;
                        }
                }
        }
index 0aa8d19..cb674e5 100644 (file)
--- 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
index a26b6f1..911f9ac 100644 (file)
@@ -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);
index d15d9cc..1ab8262 100644 (file)
@@ -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 f036b7c..082365d 100644 (file)
--- 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);