v_yshearing: Make view and input behave more like Duke Nukem 3D ;)
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 4 Mar 2016 20:41:09 +0000 (20:41 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 4 Mar 2016 20:41:09 +0000 (20:41 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12246 d7cf8633-e32d-0410-b094-e92efae38249

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

index b70a19e..91da154 100644 (file)
@@ -461,6 +461,24 @@ 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;
+       }
+}
 
 /*
 ================
@@ -487,15 +505,15 @@ static void CL_AdjustAngles (void)
        if (in_klook.state & 1)
        {
                V_StopPitchDrift ();
-               cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
-               cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
+               IN_AddToPitch(-speed*cl_pitchspeed.value * CL_KeyState (&in_forward));
+               IN_AddToPitch(speed*cl_pitchspeed.value * CL_KeyState (&in_back));
        }
 
        up = CL_KeyState (&in_lookup);
        down = CL_KeyState(&in_lookdown);
 
-       cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
-       cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
+       IN_AddToPitch(-speed*cl_pitchspeed.value * up);
+       IN_AddToPitch(-speed*cl_pitchspeed.value * down);
 
        if (up || down)
                V_StopPitchDrift ();
@@ -661,7 +679,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;
-                       cl.viewangles[PITCH] += m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom;
+                       IN_AddToPitch(m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom);
                }
                else
                {
@@ -775,12 +793,12 @@ static void CL_UpdatePrydonCursor(void)
        }
        if (cl.cmd.cursor_screen[1] < -1)
        {
-               cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - -1) * vid.height * sensitivity.value * cl.viewzoom;
+               IN_AddToPitch(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)
        {
-               cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.height * sensitivity.value * cl.viewzoom;
+               IN_AddToPitch(m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.height * sensitivity.value * cl.viewzoom);
                cl.cmd.cursor_screen[1] = 1;
        }
        */
index 9d41dda..8bc2ab9 100644 (file)
@@ -719,11 +719,14 @@ static void VM_CL_getlight (prvm_prog_t *prog)
 //============================================================================
 //[515]: SCENE MANAGER builtins
 
+extern cvar_t v_yshearing;
 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);
        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);
@@ -1177,7 +1180,7 @@ static void VM_CL_project (prvm_prog_t *prog)
 
        VM_SAFEPARMCOUNT(1, VM_CL_project);
        VectorCopy(PRVM_G_VECTOR(OFS_PARM0), f);
-       Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix);
+       Matrix4x4_Invert_Full(&m, &r_refdef.view.matrix);
        Matrix4x4_Transform(&m, f, v);
        if(v_flipped.integer)
                v[1] = -v[1];
index b1ac3ff..3c497f4 100644 (file)
@@ -1097,7 +1097,7 @@ void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatri
        m[14] = -2 * nearclip * farclip / (farclip - nearclip);
 
        Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
-       Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
+       Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
        Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
 
        if (nearplane)
@@ -1125,7 +1125,7 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri
        m[14] = -2 * nearclip * farclip / (farclip - nearclip);
 
        Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
-       Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
+       Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
        Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
 
        switch(vid.renderpath)
index 3f8ba42..6f00380 100644 (file)
@@ -3100,7 +3100,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
                GL_AlphaToCoverage(false);
        Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
        Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
-       Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
+       Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
        Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
        switch(vid.renderpath)
        {
@@ -5840,7 +5840,7 @@ void R_RenderView_UpdateViewVectors(void)
        Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
        VectorNegate(r_refdef.view.left, r_refdef.view.right);
        // make an inverted copy of the view matrix for tracking sprites
-       Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+       Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
 }
 
 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
index 60cc04b..8f8e7b5 100644 (file)
--- a/mathlib.c
+++ b/mathlib.c
@@ -549,6 +549,74 @@ 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)
+{
+       double angle, sr, tp, sy, cr, sgnp, cy;
+
+       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);
+       if (forward)
+       {
+               forward[0] = cy*sgnp;
+               forward[1] = sy*sgnp;
+               forward[2] = -tp;
+       }
+       if (left || up)
+       {
+               if (angles[ROLL])
+               {
+                       angle = angles[ROLL] * (M_PI*2 / 360);
+                       sr = sin(angle);
+                       cr = cos(angle);
+                       if (left)
+                       {
+                               left[0] = cr*-sy;
+                               left[1] = cr*cy;
+                               left[2] = sr*sgnp;
+                       }
+                       if (up)
+                       {
+                               up[0] = -sr*-sy;
+                               up[1] = -sr*cy;
+                               up[2] = cr*sgnp;
+                       }
+               }
+               else
+               {
+                       if (left)
+                       {
+                               left[0] = -sy;
+                               left[1] = cy;
+                               left[2] = 0;
+                       }
+                       if (up)
+                       {
+                               up[0] = 0;
+                               up[1] = 0;
+                               up[2] = sgnp;
+                       }
+               }
+       }
+}
+
 // LordHavoc: calculates pitch/yaw/roll angles from forward and up vectors
 void AnglesFromVectors (vec3_t angles, const vec3_t forward, const vec3_t up, qboolean flippitch)
 {
index 9a9cd73..0aa8d19 100644 (file)
--- a/mathlib.h
+++ b/mathlib.h
@@ -252,6 +252,8 @@ void R_ConcatTransforms (const float in1[3*4], const float in2[3*4], float out[3
 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);
 /// 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 78c859c..a26b6f1 100644 (file)
@@ -890,6 +890,54 @@ void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, doubl
        }
 }
 
+void Matrix4x4_QuakeToDuke3D(const matrix4x4_t *in, matrix4x4_t *out)
+{
+       // Sorry - this isn't direct at all. We can't just use an alternative to
+       // Matrix4x4_CreateFromQuakeEntity as in some cases the input for
+       // generating the view matrix is generated externally.
+       vec3_t forward, left, up, angles;
+       double scaleforward, scaleleft, scaleup;
+#ifdef MATRIX4x4_OPENGLORIENTATION
+       VectorSet(forward, in->m[0][0], in->m[0][1], in->m[0][2]);
+       VectorSet(left, in->m[1][0], in->m[1][1], in->m[1][2]);
+       VectorSet(up, in->m[2][0], in->m[2][1], in->m[2][2]);
+#else
+       VectorSet(forward, in->m[0][0], in->m[1][0], in->m[2][0]);
+       VectorSet(left, in->m[0][1], in->m[1][1], in->m[2][1]);
+       VectorSet(up, in->m[0][2], in->m[1][2], in->m[2][2]);
+#endif
+       scaleforward = VectorNormalizeLength(forward);
+       scaleleft = VectorNormalizeLength(left);
+       scaleup = VectorNormalizeLength(up);
+       AnglesFromVectors(angles, forward, up, false);
+       AngleVectorsDuke3DFLU(angles, forward, left, up);
+       VectorScale(forward, scaleforward, forward);
+       VectorScale(left, scaleleft, left);
+       VectorScale(up, scaleup, up);
+       *out = *in;
+#ifdef MATRIX4x4_OPENGLORIENTATION
+       out->m[0][0] = forward[0];
+       out->m[1][0] = left[0];
+       out->m[2][0] = up[0];
+       out->m[0][1] = forward[1];
+       out->m[1][1] = left[1];
+       out->m[2][1] = up[1];
+       out->m[0][2] = forward[2];
+       out->m[1][2] = left[2];
+       out->m[2][2] = up[2];
+#else
+       out->m[0][0] = forward[0];
+       out->m[0][1] = left[0];
+       out->m[0][2] = up[0];
+       out->m[1][0] = forward[1];
+       out->m[1][1] = left[1];
+       out->m[1][2] = up[1];
+       out->m[2][0] = forward[2];
+       out->m[2][1] = left[2];
+       out->m[2][2] = up[2];
+#endif
+}
+
 void Matrix4x4_ToVectors(const matrix4x4_t *in, float vx[3], float vy[3], float vz[3], float t[3])
 {
 #ifdef MATRIX4x4_OPENGLORIENTATION
index 232f1ad..d15d9cc 100644 (file)
@@ -80,6 +80,8 @@ void Matrix4x4_CreateScale (matrix4x4_t *out, double x);
 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);
 
 // 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 fef4c4c..f036b7c 100644 (file)
--- a/view.c
+++ b/view.c
@@ -110,6 +110,8 @@ 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)"};
+
 float  v_dmg_time, v_dmg_roll, v_dmg_pitch;
 
 
@@ -522,6 +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);
                Matrix4x4_Copy(&viewmodelmatrix_nobob, &r_refdef.view.matrix);
                Matrix4x4_ConcatScale(&viewmodelmatrix_nobob, cl_viewmodel_scale.value);
                Matrix4x4_Copy(&viewmodelmatrix_withbob, &viewmodelmatrix_nobob);
@@ -855,12 +859,17 @@ 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);
 
                // 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);
+
                VectorCopy(vieworg, cl.csqc_vieworiginfromengine);
                VectorCopy(viewangles, cl.csqc_viewanglesfromengine);
 
@@ -1139,5 +1148,7 @@ void V_Init (void)
 
        Cvar_RegisterVariable (&v_deathtilt);
        Cvar_RegisterVariable (&v_deathtiltangle);
+
+       Cvar_RegisterVariable (&v_yshearing);
 }