From c045878e6948f00e52f17c9df6beefa2dfdfd868 Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 14 Apr 2018 06:54:35 +0000 Subject: [PATCH] Added v_isometric cvars, this mode is mostly a curiosity but it's useful for testing engine compatibility with non-perspective rendering. Fixed a few bugs where distance culling was misbehaving with non-perspective rendering. Make r_refdef.view.ismain more useful - it's now cleared after R_RenderView rather than before, so R_RenderView can make use of it (for r_motionblur ghost texture updates and anything else that wants to happen just on the main view). git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12396 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_particles.c | 4 +-- cl_screen.c | 45 ++++++++++++++++++++--------- clvm_cmds.c | 15 ++++++---- csprogs.c | 1 - gl_rmain.c | 23 +++++++++------ gl_rsurf.c | 2 +- view.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 135 insertions(+), 32 deletions(-) diff --git a/cl_particles.c b/cl_particles.c index b159698c..4247755d 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -2612,7 +2612,7 @@ void R_DrawDecals (void) if (!drawdecals) continue; - if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size)) + if (!r_refdef.view.useperspective || (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size))) R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL); continue; killdecal: @@ -3132,7 +3132,7 @@ void R_DrawParticles (void) continue; } // anything else just has to be in front of the viewer and visible at this distance - if (DotProduct(p->org, r_refdef.view.forward) >= minparticledist_start && VectorDistance2(p->org, r_refdef.view.origin) < drawdist2 * (p->size * p->size)) + if (!r_refdef.view.useperspective || (DotProduct(p->org, r_refdef.view.forward) >= minparticledist_start && VectorDistance2(p->org, r_refdef.view.origin) < drawdist2 * (p->size * p->size))) R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL); break; } diff --git a/cl_screen.c b/cl_screen.c index 7fb41d15..afdeab60 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -1844,6 +1844,7 @@ static void R_Envmap_f (void) r_refdef.view.depth = 1; r_refdef.view.useperspective = true; r_refdef.view.isoverlay = false; + r_refdef.view.ismain = true; r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0); r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0); @@ -2065,6 +2066,8 @@ void R_ClearScreen(qboolean fogcolor) } int r_stereo_side; +extern cvar_t v_isometric; +extern cvar_t v_isometric_verticalfov; static void SCR_DrawScreen (void) { @@ -2128,20 +2131,34 @@ static void SCR_DrawScreen (void) r_refdef.view.z = 0; } - // LordHavoc: viewzoom (zoom in for sniper rifles, etc) - // LordHavoc: this is designed to produce widescreen fov values - // when the screen is wider than 4/3 width/height aspect, to do - // this it simply assumes the requested fov is the vertical fov - // for a 4x3 display, if the ratio is not 4x3 this makes the fov - // higher/lower according to the ratio - r_refdef.view.useperspective = true; - r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom; - r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value; - - r_refdef.view.frustum_x *= r_refdef.frustumscale_x; - r_refdef.view.frustum_y *= r_refdef.frustumscale_y; - r_refdef.view.ortho_x = atan(r_refdef.view.frustum_x) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView - r_refdef.view.ortho_y = atan(r_refdef.view.frustum_y) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView + if (v_isometric.integer) + { + r_refdef.view.useperspective = false; + r_refdef.view.frustum_y = v_isometric_verticalfov.value * cl.viewzoom; + r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value; + r_refdef.view.frustum_x *= r_refdef.frustumscale_x; + r_refdef.view.frustum_y *= r_refdef.frustumscale_y; + r_refdef.view.ortho_x = r_refdef.view.frustum_x; // used by VM_CL_R_SetView + r_refdef.view.ortho_y = r_refdef.view.frustum_y; // used by VM_CL_R_SetView + } + else + { + // LordHavoc: viewzoom (zoom in for sniper rifles, etc) + // LordHavoc: this is designed to produce widescreen fov values + // when the screen is wider than 4/3 width/height aspect, to do + // this it simply assumes the requested fov is the vertical fov + // for a 4x3 display, if the ratio is not 4x3 this makes the fov + // higher/lower according to the ratio + r_refdef.view.useperspective = true; + r_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0 / 4.0) * cl.viewzoom; + r_refdef.view.frustum_x = r_refdef.view.frustum_y * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value; + + r_refdef.view.frustum_x *= r_refdef.frustumscale_x; + r_refdef.view.frustum_y *= r_refdef.frustumscale_y; + r_refdef.view.ortho_x = atan(r_refdef.view.frustum_x) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView + r_refdef.view.ortho_y = atan(r_refdef.view.frustum_y) * (360.0 / M_PI); // abused as angle by VM_CL_R_SetView + } + r_refdef.view.ismain = true; // if CSQC is loaded, it is required to provide the CSQC_UpdateView function, // and won't render a view if it does not call that. diff --git a/clvm_cmds.c b/clvm_cmds.c index 47344845..5ee778f9 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -3252,18 +3252,15 @@ static void VM_CL_GetEntity (prvm_prog_t *prog) // --blub static void VM_CL_R_RenderScene (prvm_prog_t *prog) { + qboolean ismain = r_refdef.view.ismain; double t = Sys_DirtyTime(); VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene); // update the views - if(r_refdef.view.ismain) + if(ismain) { // set the main view csqc_main_r_refdef_view = r_refdef.view; - - // clear the flags so no other view becomes "main" unless CSQC sets VF_MAINVIEW - r_refdef.view.ismain = false; - csqc_original_r_refdef_view.ismain = false; } // we need to update any RENDER_VIEWMODEL entities at this point because @@ -3280,6 +3277,14 @@ static void VM_CL_R_RenderScene (prvm_prog_t *prog) // callprofile fixing hack: do not include this time in what is counted for CSQC_UpdateView t = Sys_DirtyTime() - t;if (t < 0 || t >= 1800) t = 0; prog->functions[PRVM_clientfunction(CSQC_UpdateView)].totaltime -= t; + + // update the views + if (ismain) + { + // clear the flags so no other view becomes "main" unless CSQC sets VF_MAINVIEW + r_refdef.view.ismain = false; + csqc_original_r_refdef_view.ismain = false; + } } //void(string texturename, float flag[, float is2d]) R_BeginPolygon diff --git a/csprogs.c b/csprogs.c index 3e609ea8..f0a01a26 100644 --- a/csprogs.c +++ b/csprogs.c @@ -476,7 +476,6 @@ qboolean CL_VM_UpdateView (double frametime) return false; R_TimeReport("pre-UpdateView"); CSQC_BEGIN - r_refdef.view.ismain = true; csqc_original_r_refdef_view = r_refdef.view; csqc_main_r_refdef_view = r_refdef.view; //VectorCopy(cl.viewangles, oldangles); diff --git a/gl_rmain.c b/gl_rmain.c index 386d12f3..5eaff437 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -5474,15 +5474,15 @@ static void R_View_SetFrustum(const int *scissor) } else { - VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal); - VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal); - VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal); - VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal); - VectorCopy(forward, r_refdef.view.frustum[4].normal); - r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x; - r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x; - r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y; - r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y; + VectorScale(forward, -1.0f, r_refdef.view.frustum[0].normal); + VectorScale(forward, 1.0f, r_refdef.view.frustum[1].normal); + VectorScale(left, -1.0f, r_refdef.view.frustum[2].normal); + VectorScale(left, 1.0f, r_refdef.view.frustum[3].normal); + VectorScale(up, -1.0f, r_refdef.view.frustum[4].normal); + r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x; + r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x; + r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y; + r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y; r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip; } r_refdef.view.numfrustumplanes = 5; @@ -6920,6 +6920,8 @@ R_RenderView */ int dpsoftrast_test; extern cvar_t r_shadow_bouncegrid; +extern cvar_t v_isometric; +extern void V_MakeViewIsometric(void); void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height) { matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix; @@ -6978,6 +6980,9 @@ void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, i return; } + if (v_isometric.integer && r_refdef.view.ismain) + V_MakeViewIsometric(); + r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value; if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D) diff --git a/gl_rsurf.c b/gl_rsurf.c index d0477c3d..84027b1d 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -487,7 +487,7 @@ void R_View_WorldVisibility(qboolean forcenovis) // if floating around in the void (no pvs data available, and no // portals available), simply use all on-screen leafs. - if (!viewleaf || viewleaf->clusterindex < 0 || forcenovis || r_trippy.integer) + if (!viewleaf || viewleaf->clusterindex < 0 || forcenovis || r_trippy.integer || !r_refdef.view.useperspective) { // no visibility method: (used when floating around in the void) // simply cull each leaf to the frustum (view pyramid) diff --git a/view.c b/view.c index cb352ef7..df73f194 100644 --- a/view.c +++ b/view.c @@ -92,6 +92,25 @@ cvar_t v_ipitch_level = {0, "v_ipitch_level", "0.3", "v_idlescale pitch amount"} cvar_t v_idlescale = {0, "v_idlescale", "0", "how much of the quake 'drunken view' effect to use"}; +cvar_t v_isometric = {0, "v_isometric", "0", "changes view to isometric (non-perspective)"}; +cvar_t v_isometric_verticalfov = { 0, "v_isometric_verticalfov", "512", "vertical field of view in game units (horizontal is computed using aspect ratio based on this)"}; +cvar_t v_isometric_xx = {0, "v_isometric_xx", "0", "camera matrix"}; +cvar_t v_isometric_xy = {0, "v_isometric_xy", "-1", "camera matrix"}; +cvar_t v_isometric_xz = {0, "v_isometric_xz", "0", "camera matrix"}; +cvar_t v_isometric_yx = {0, "v_isometric_yx", "-1", "camera matrix"}; +cvar_t v_isometric_yy = {0, "v_isometric_yy", "0", "camera matrix"}; +cvar_t v_isometric_yz = {0, "v_isometric_yz", "0", "camera matrix"}; +cvar_t v_isometric_zx = {0, "v_isometric_zx", "0", "camera matrix"}; +cvar_t v_isometric_zy = {0, "v_isometric_zy", "0", "camera matrix"}; +cvar_t v_isometric_zz = {0, "v_isometric_zz", "1", "camera matrix"}; +cvar_t v_isometric_tx = {0, "v_isometric_tx", "1767", "camera position"}; +cvar_t v_isometric_ty = {0, "v_isometric_ty", "1767", "camera position"}; +cvar_t v_isometric_tz = {0, "v_isometric_tz", "1425", "camera position"}; +cvar_t v_isometric_rot_pitch = {0, "v_isometric_rot_pitch", "0", "camera rotation"}; +cvar_t v_isometric_rot_yaw = {0, "v_isometric_rot_yaw", "-45", "camera rotation"}; +cvar_t v_isometric_rot_roll = {0, "v_isometric_rot_roll", "-60", "camera rotation"}; +cvar_t v_isometric_locked_orientation = {0, "v_isometric_locked_orientation", "1", "camera rotation is fixed"}; + cvar_t crosshair = {CVAR_SAVE, "crosshair", "0", "selects crosshair to use (0 is none)"}; cvar_t v_centermove = {0, "v_centermove", "0.15", "how long before the view begins to center itself (if freelook/+mlook/+jlook/+klook are off)"}; @@ -943,6 +962,45 @@ void V_CalcRefdef (void) } } +void V_MakeViewIsometric(void) +{ + // when using isometric view to play normal games we have to rotate the camera to make the Ortho matrix do the right thing (forward as up the screen, etc) + matrix4x4_t relative; + matrix4x4_t modifiedview; + matrix4x4_t modify; + float t[4][4]; + t[0][0] = v_isometric_xx.value; + t[0][1] = v_isometric_xy.value; + t[0][2] = v_isometric_xz.value; + t[0][3] = 0.0f; + t[1][0] = v_isometric_yx.value; + t[1][1] = v_isometric_yy.value; + t[1][2] = v_isometric_yz.value; + t[1][3] = 0.0f; + t[2][0] = v_isometric_zx.value; + t[2][1] = v_isometric_zy.value; + t[2][2] = v_isometric_zz.value; + t[2][3] = 0.0f; + t[3][0] = 0.0f; + t[3][1] = 0.0f; + t[3][2] = 0.0f; + t[3][3] = 1.0f; + Matrix4x4_FromArrayFloatGL(&modify, t[0]); + + // if the orientation is locked, extract the origin and create just a translate matrix to start with + if (v_isometric_locked_orientation.integer) + { + vec3_t vx, vy, vz, origin; + Matrix4x4_ToVectors(&r_refdef.view.matrix, vx, vy, vz, origin); + Matrix4x4_CreateTranslate(&r_refdef.view.matrix, origin[0], origin[1], origin[2]); + } + + Matrix4x4_Concat(&modifiedview, &r_refdef.view.matrix, &modify); + Matrix4x4_CreateFromQuakeEntity(&relative, v_isometric_tx.value, v_isometric_ty.value, v_isometric_tz.value, v_isometric_rot_pitch.value, v_isometric_rot_yaw.value, v_isometric_rot_roll.value, 1.0f); + Matrix4x4_Concat(&r_refdef.view.matrix, &modifiedview, &relative); +} + + void V_FadeViewFlashs(void) { // don't flash if time steps backwards @@ -1125,6 +1183,25 @@ void V_Init (void) Cvar_RegisterVariable (&v_iroll_level); Cvar_RegisterVariable (&v_ipitch_level); + Cvar_RegisterVariable(&v_isometric); + Cvar_RegisterVariable(&v_isometric_verticalfov); + Cvar_RegisterVariable(&v_isometric_xx); + Cvar_RegisterVariable(&v_isometric_xy); + Cvar_RegisterVariable(&v_isometric_xz); + Cvar_RegisterVariable(&v_isometric_yx); + Cvar_RegisterVariable(&v_isometric_yy); + Cvar_RegisterVariable(&v_isometric_yz); + Cvar_RegisterVariable(&v_isometric_zx); + Cvar_RegisterVariable(&v_isometric_zy); + Cvar_RegisterVariable(&v_isometric_zz); + Cvar_RegisterVariable(&v_isometric_tx); + Cvar_RegisterVariable(&v_isometric_ty); + Cvar_RegisterVariable(&v_isometric_tz); + Cvar_RegisterVariable(&v_isometric_rot_pitch); + Cvar_RegisterVariable(&v_isometric_rot_yaw); + Cvar_RegisterVariable(&v_isometric_rot_roll); + Cvar_RegisterVariable(&v_isometric_locked_orientation); + Cvar_RegisterVariable (&v_idlescale); Cvar_RegisterVariable (&crosshair); -- 2.39.2