From: divverent Date: Fri, 4 Mar 2016 20:41:09 +0000 (+0000) Subject: v_yshearing: Make view and input behave more like Duke Nukem 3D ;) X-Git-Tag: xonotic-v0.8.5~88^2~75 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=953f1f8feaa55e272118605371c13bf0f68585da v_yshearing: Make view and input behave more like Duke Nukem 3D ;) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12246 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_input.c b/cl_input.c index b70a19ec..91da154c 100644 --- a/cl_input.c +++ b/cl_input.c @@ -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; } */ diff --git a/clvm_cmds.c b/clvm_cmds.c index 9d41dda6..8bc2ab98 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -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]; diff --git a/gl_backend.c b/gl_backend.c index b1ac3ff2..3c497f48 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -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) diff --git a/gl_rmain.c b/gl_rmain.c index 3f8ba42d..6f003803 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -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); diff --git a/mathlib.c b/mathlib.c index 60cc04b0..8f8e7b50 100644 --- 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) { diff --git a/mathlib.h b/mathlib.h index 9a9cd732..0aa8d19c 100644 --- 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 diff --git a/matrixlib.c b/matrixlib.c index 78c859cf..a26b6f13 100644 --- a/matrixlib.c +++ b/matrixlib.c @@ -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 diff --git a/matrixlib.h b/matrixlib.h index 232f1add..d15d9ccd 100644 --- a/matrixlib.h +++ b/matrixlib.h @@ -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 fef4c4cb..f036b7c6 100644 --- 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); }