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;
+ }
+}
/*
================
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 ();
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
{
}
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;
}
*/
//============================================================================
//[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);
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];
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)
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)
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)
{
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);
}
}
+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)
{
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
}
}
+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
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]);
// 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;
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);
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);
Cvar_RegisterVariable (&v_deathtilt);
Cvar_RegisterVariable (&v_deathtiltangle);
+
+ Cvar_RegisterVariable (&v_yshearing);
}