Reworked v_isometric code significantly, it now defaults to a proper isometric view...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 15 Apr 2018 23:23:11 +0000 (23:23 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 15 Apr 2018 23:23:11 +0000 (23:23 +0000)
Added R_Viewport_InitOrtho3D which more correctly implements the VF_PERSPECTIVE=0 case for CSQC, with correct camera orientation and all that.  This may break existing mods that tried to use that feature but I doubt there are any as it was pretty broken before.

Reworked how R_CanSeeBox (and other vis code) determine if the view is able to use vieworigin based culling or not, this is now a separate property (r_refdef.view.usevieworiginculling) and can be turned on or off for reflection views and such.  This is also exposed as v_isometric_usevieworiginculling for the v_isometric case.

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

cl_screen.c
client.h
gl_backend.c
gl_backend.h
gl_rmain.c
gl_rsurf.c
view.c

index 9213784..71a74c0 100644 (file)
@@ -2135,33 +2135,21 @@ static void SCR_DrawScreen (void)
                        r_refdef.view.z = 0;
                }
 
-               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
-               }
+               // 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,
index cbc0fc0..67013dd 100644 (file)
--- a/client.h
+++ b/client.h
@@ -1815,6 +1815,12 @@ typedef struct r_refdef_view_s
        vec3_t frustumcorner[4];
        // if turned off it renders an ortho view
        int useperspective;
+       // allows visibility culling based on the view origin (e.g. pvs and R_CanSeeBox)
+       // this is turned off by:
+       // r_trippy
+       // !r_refdef.view.useperspective
+       // (sometimes) r_refdef.view.useclipplane
+       int usevieworiginculling;
        float ortho_x, ortho_y;
 
        // screen area to render in
index fa8fc68..d1455af 100644 (file)
@@ -914,6 +914,48 @@ void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int
 #endif
 }
 
+void R_Viewport_InitOrtho3D(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
+{
+       matrix4x4_t tempmatrix, basematrix;
+       float m[16];
+       memset(v, 0, sizeof(*v));
+
+       v->type = R_VIEWPORTTYPE_PERSPECTIVE;
+       v->cameramatrix = *cameramatrix;
+       v->x = x;
+       v->y = y;
+       v->z = 0;
+       v->width = width;
+       v->height = height;
+       v->depth = 1;
+       memset(m, 0, sizeof(m));
+       m[0]  = 1.0 / frustumx;
+       m[5]  = 1.0 / frustumy;
+       m[10] = -2 / (farclip - nearclip);
+       m[14] = -(farclip + nearclip) / (farclip - nearclip);
+       m[15] = 1;
+       v->screentodepth[0] = -farclip / (farclip - nearclip);
+       v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
+
+       Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
+       Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
+       Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
+       Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
+
+       if (nearplane)
+               R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
+
+       if(v_flipped.integer)
+       {
+               m[0] = -m[0];
+               m[4] = -m[4];
+               m[8] = -m[8];
+               m[12] = -m[12];
+       }
+
+       Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
+}
+
 void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
 {
        matrix4x4_t tempmatrix, basematrix;
index b770d68..6095374 100644 (file)
@@ -25,6 +25,7 @@ extern unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out);
 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor);
 void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float x1, float y1, float x2, float y2, float zNear, float zFar, const float *nearplane);
+void R_Viewport_InitOrtho3D(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane);
 void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float zNear, float zFar, const float *nearplane);
 void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float zNear, const float *nearplane);
 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane);
index 1cfb035..2902109 100644 (file)
@@ -5057,7 +5057,7 @@ qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t
                return true;
 
        // view origin is not used for culling in portal/reflection/refraction renders or isometric views
-       if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
+       if (!r_refdef.view.usevieworiginculling)
                return true;
 
        if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
@@ -5478,16 +5478,16 @@ static void R_View_SetFrustum(const int *scissor)
        }
        else
        {
-               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);
+               VectorScale(left, -1.0f, r_refdef.view.frustum[0].normal);
+               VectorScale(left,  1.0f, r_refdef.view.frustum[1].normal);
+               VectorScale(up, -1.0f, r_refdef.view.frustum[2].normal);
+               VectorScale(up,  1.0f, r_refdef.view.frustum[3].normal);
+               VectorScale(forward, -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.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) - r_refdef.farclip;
        }
        r_refdef.view.numfrustumplanes = 5;
 
@@ -5534,7 +5534,7 @@ static void R_View_UpdateWithScissor(const int *myscissor)
 {
        R_Main_ResizeViewCache();
        R_View_SetFrustum(myscissor);
-       R_View_WorldVisibility(r_refdef.view.useclipplane);
+       R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
        R_View_UpdateEntityVisible();
 }
 
@@ -5542,7 +5542,7 @@ static void R_View_Update(void)
 {
        R_Main_ResizeViewCache();
        R_View_SetFrustum(NULL);
-       R_View_WorldVisibility(r_refdef.view.useclipplane);
+       R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
        R_View_UpdateEntityVisible();
 }
 
@@ -5579,7 +5579,7 @@ void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *view
        rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
 
        if (!r_refdef.view.useperspective)
-               R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
+               R_Viewport_InitOrtho3D(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
        else if (vid.stencil && r_useinfinitefarclip.integer)
                R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
        else
@@ -6079,6 +6079,8 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t
                        }
 
                        r_refdef.view.clipplane = p->plane;
+                       // reflected view origin may be in solid, so don't cull with it
+                       r_refdef.view.usevieworiginculling = false;
                        // reverse the cullface settings for this render
                        r_refdef.view.cullface_front = GL_FRONT;
                        r_refdef.view.cullface_back = GL_BACK;
@@ -6207,6 +6209,8 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t
                        
                        // camera needs no clipplane
                        r_refdef.view.useclipplane = false;
+                       // TODO: is the camera origin always valid?  if so we don't need to clear this
+                       r_refdef.view.usevieworiginculling = false;
 
                        PlaneClassify(&r_refdef.view.clipplane);
 
@@ -6983,6 +6987,7 @@ void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, i
                return;
        }
 
+       r_refdef.view.usevieworiginculling = !r_trippy.value && r_refdef.view.useperspective;
        if (v_isometric.integer && r_refdef.view.ismain)
                V_MakeViewIsometric();
 
index 84027b1..cd4c08b 100644 (file)
@@ -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 || !r_refdef.view.useperspective)
+               if (!viewleaf || viewleaf->clusterindex < 0 || forcenovis || !r_refdef.view.usevieworiginculling)
                {
                        // 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 df73f19..77aed89 100644 (file)
--- a/view.c
+++ b/view.c
@@ -94,22 +94,27 @@ cvar_t v_idlescale = {0, "v_idlescale", "0", "how much of the quake 'drunken vie
 
 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_xx = {0, "v_isometric_xx", "1", "camera matrix"};
+cvar_t v_isometric_xy = {0, "v_isometric_xy", "0", "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_yx = {0, "v_isometric_yx", "0", "camera matrix"};
+cvar_t v_isometric_yy = {0, "v_isometric_yy", "1", "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_tx = {0, "v_isometric_tx", "0", "camera position (player-relative)"};
+cvar_t v_isometric_ty = {0, "v_isometric_ty", "0", "camera position (player-relative)"};
+cvar_t v_isometric_tz = {0, "v_isometric_tz", "0", "camera position (player-relative)"};
+cvar_t v_isometric_rot_pitch = {0, "v_isometric_rot_pitch", "60", "camera rotation"};
+cvar_t v_isometric_rot_yaw = {0, "v_isometric_rot_yaw", "135", "camera rotation"};
+cvar_t v_isometric_rot_roll = {0, "v_isometric_rot_roll", "0", "camera rotation"};
+cvar_t v_isometric_relx = {0, "v_isometric_relx", "0", "camera position*forward"};
+cvar_t v_isometric_rely = {0, "v_isometric_rely", "0", "camera position*left"};
+cvar_t v_isometric_relz = {0, "v_isometric_relz", "0", "camera position*up"};
+cvar_t v_isometric_flipcullface = {0, "v_isometric_flipcullface", "0", "flips the backface culling"};
 cvar_t v_isometric_locked_orientation = {0, "v_isometric_locked_orientation", "1", "camera rotation is fixed"};
+cvar_t v_isometric_usevieworiginculling = {0, "v_isometric_usevieworiginculling", "0", "check visibility to the player location (can look pretty weird)"};
 
 cvar_t crosshair = {CVAR_SAVE, "crosshair", "0", "selects crosshair to use (0 is none)"};
 
@@ -968,7 +973,18 @@ void V_MakeViewIsometric(void)
        matrix4x4_t relative;
        matrix4x4_t modifiedview;
        matrix4x4_t modify;
+       vec3_t forward, left, up, org;
        float t[4][4];
+
+       r_refdef.view.useperspective = false;
+       r_refdef.view.usevieworiginculling = !r_trippy.value && v_isometric_usevieworiginculling.integer;
+       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
+
        t[0][0] = v_isometric_xx.value;
        t[0][1] = v_isometric_xy.value;
        t[0][2] = v_isometric_xz.value;
@@ -998,6 +1014,16 @@ void V_MakeViewIsometric(void)
        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);
+       Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, org);
+       VectorMAMAMAM(1.0f, org, v_isometric_relx.value, forward, v_isometric_rely.value, left, v_isometric_relz.value, up, org);
+       Matrix4x4_FromVectors(&r_refdef.view.matrix, forward, left, up, org);
+
+       if (v_isometric_flipcullface.integer)
+       {
+               int a = r_refdef.view.cullface_front;
+               r_refdef.view.cullface_front = r_refdef.view.cullface_back;
+               r_refdef.view.cullface_back = a;
+       }
 }
 
 
@@ -1200,7 +1226,12 @@ void V_Init (void)
        Cvar_RegisterVariable(&v_isometric_rot_pitch);
        Cvar_RegisterVariable(&v_isometric_rot_yaw);
        Cvar_RegisterVariable(&v_isometric_rot_roll);
+       Cvar_RegisterVariable(&v_isometric_relx);
+       Cvar_RegisterVariable(&v_isometric_rely);
+       Cvar_RegisterVariable(&v_isometric_relz);
+       Cvar_RegisterVariable(&v_isometric_flipcullface);
        Cvar_RegisterVariable(&v_isometric_locked_orientation);
+       Cvar_RegisterVariable(&v_isometric_usevieworiginculling);
 
        Cvar_RegisterVariable (&v_idlescale);
        Cvar_RegisterVariable (&crosshair);