]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
video modes in menu now also set vid_pixelheight and vid_conwidth/vid_conheight
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 30 Nov 2005 15:10:07 +0000 (15:10 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 30 Nov 2005 15:10:07 +0000 (15:10 +0000)
improved video modes menu, it now has widescreen modes, refresh rate, and more information about the chosen mode
renamed vid_pixelaspect to vid_pixelheight and inverted its behavior (smaller value now means that a pixel is wider than it is tall)
eliminated r_refdef.fov* fields, redesigned to use frustum plane slopes (like glFrustum takes) and calculate fov from height*4/3 rather than width, so widescreen now automatically uses higher fov accordingly, but 4x3 modes are the same as they always were, this also required generating the frustum planes differently in the renderer
changed underwater view warping to use frustum scaling rather than angles, this makes it a little smoother

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

cl_input.c
cl_screen.c
cl_screen.h
client.h
gl_backend.c
gl_backend.h
gl_draw.c
gl_rmain.c
menu.c
render.h
view.c

index 85bfd8b0c08c4f5f3e64e4d4936b727ec3e88a07..18b4cfa99249d93cac72f3a514009f3d6a54e432 100644 (file)
@@ -407,18 +407,18 @@ void CL_Move (void)
                {
                        // strafing mode, all looking is movement
                        V_StopPitchDrift();
-                       cl.cmd.sidemove += m_side.value * in_mouse_x * sensitivity.value * cl.viewzoom;
+                       cl.cmd.sidemove += m_side.value * in_mouse_x * sensitivity.value;
                        if (noclip_anglehack)
-                               cl.cmd.upmove -= m_forward.value * in_mouse_y * sensitivity.value * cl.viewzoom;
+                               cl.cmd.upmove -= m_forward.value * in_mouse_y * sensitivity.value;
                        else
-                               cl.cmd.forwardmove -= m_forward.value * in_mouse_y * sensitivity.value * cl.viewzoom;
+                               cl.cmd.forwardmove -= m_forward.value * in_mouse_y * sensitivity.value;
                }
                else if ((in_mlook.state & 1) || freelook.integer)
                {
                        // mouselook, lookstrafe causes turning to become strafing
                        V_StopPitchDrift();
                        if (lookstrafe.integer)
-                               cl.cmd.sidemove += m_side.value * in_mouse_x * sensitivity.value * cl.viewzoom;
+                               cl.cmd.sidemove += m_side.value * in_mouse_x * sensitivity.value;
                        else
                                cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * sensitivity.value * cl.viewzoom;
                        cl.viewangles[PITCH] += m_pitch.value * in_mouse_y * sensitivity.value * cl.viewzoom;
@@ -427,7 +427,7 @@ void CL_Move (void)
                {
                        // non-mouselook, yaw turning and forward/back movement
                        cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * sensitivity.value * cl.viewzoom;
-                       cl.cmd.forwardmove -= m_forward.value * in_mouse_y * sensitivity.value * cl.viewzoom;
+                       cl.cmd.forwardmove -= m_forward.value * in_mouse_y * sensitivity.value;
                }
        }
 
@@ -471,8 +471,8 @@ void CL_UpdatePrydonCursor(void)
        cl.cmd.cursor_screen[1] = bound(-1, cl.cmd.cursor_screen[1], 1);
        cl.cmd.cursor_screen[2] = 1;
 
-       scale[0] = -tan(r_refdef.fov_x * M_PI / 360.0);
-       scale[1] = -tan(r_refdef.fov_y * M_PI / 360.0);
+       scale[0] = -r_refdef.frustum_x;
+       scale[1] = -r_refdef.frustum_y;
        scale[2] = 1;
 
        // trace distance
index 7765c999f4967da75734af47c04144c82c024dc5..d7baa8b2a1f3d727d54c940adc106cee994dd59e 100644 (file)
@@ -18,7 +18,7 @@ cvar_t scr_showbrand = {0, "showbrand","0"};
 cvar_t scr_printspeed = {0, "scr_printspeed","8"};
 cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640"};
 cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480"};
-cvar_t vid_pixelaspect = {CVAR_SAVE, "vid_pixelaspect", "1"};
+cvar_t vid_pixelheight = {CVAR_SAVE, "vid_pixelheight", "1"};
 cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1"};
 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9"};
 cvar_t scr_screenshot_gamma = {CVAR_SAVE, "scr_screenshot_gamma","2.2"};
@@ -605,7 +605,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_printspeed);
        Cvar_RegisterVariable (&vid_conwidth);
        Cvar_RegisterVariable (&vid_conheight);
-       Cvar_RegisterVariable (&vid_pixelaspect);
+       Cvar_RegisterVariable (&vid_pixelheight);
        Cvar_RegisterVariable (&scr_screenshot_jpeg);
        Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
        Cvar_RegisterVariable (&scr_screenshot_gamma);
@@ -1232,8 +1232,8 @@ static void R_Envmap_f (void)
        r_refdef.width = size;
        r_refdef.height = size;
 
-       r_refdef.fov_x = 90;
-       r_refdef.fov_y = 90;
+       r_refdef.frustum_x = tan(90 * M_PI / 360.0);
+       r_refdef.frustum_y = tan(90 * M_PI / 360.0);
 
        buffer1 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
        buffer2 = (unsigned char *)Mem_Alloc(tempmempool, size * size * 3);
index 49175273f6421bf5eeffed361dfd85969c18e951..a6bcb3524c450921fe590d1260b8b6ce50308d3f 100644 (file)
@@ -72,7 +72,7 @@ void SHOWLMP_clear(void);
 
 extern cvar_t vid_conwidth;
 extern cvar_t vid_conheight;
-extern cvar_t vid_pixelaspect;
+extern cvar_t vid_pixelheight;
 extern cvar_t scr_screenshot_jpeg;
 extern cvar_t scr_screenshot_jpeg_quality;
 extern cvar_t scr_screenshot_gamma;
index 6e9c3b3e8a9783b669abb7d4f22ded44936b7d69..c52361e2a58721002f4c0f262cf67930aaffc4cf 100644 (file)
--- a/client.h
+++ b/client.h
@@ -869,11 +869,11 @@ typedef struct refdef_s
 {
        // area to render in
        int x, y, width, height;
-       float fov_x, fov_y;
+       float frustum_x, frustum_y;
 
        // these are set for water warping before
-       // fov_x/fov_y are calculated
-       float fovscale_x, fovscale_y;
+       // frustum_x/frustum_y are calculated
+       float frustumscale_x, frustumscale_y;
 
        // view transform
        matrix4x4_t viewentitymatrix;
index bb4d3dc039570160aa62142c8f403ccf871f758c..1e7e788c6231f403899db61559279cd566c36d7a 100644 (file)
@@ -274,9 +274,8 @@ void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix)
        memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
 }
 
-void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, double zFar)
+void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
 {
-       double xmax, ymax;
        double m[16];
 
        if (!r_render.integer)
@@ -285,11 +284,8 @@ void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, doub
        // set up viewpoint
        qglMatrixMode(GL_PROJECTION);CHECKGLERROR
        qglLoadIdentity();CHECKGLERROR
-       // pyramid slopes
-       xmax = zNear * tan(fovx * M_PI / 360.0);
-       ymax = zNear * tan(fovy * M_PI / 360.0);
        // set view pyramid
-       qglFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar);CHECKGLERROR
+       qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
        qglGetDoublev(GL_PROJECTION_MATRIX, m);
        backend_projectmatrix.m[0][0] = m[0];
        backend_projectmatrix.m[1][0] = m[1];
@@ -311,7 +307,7 @@ void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, doub
        GL_SetupView_Orientation_Identity();
 }
 
-void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear)
+void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
 {
        double nudge, m[16];
 
@@ -323,12 +319,12 @@ void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, dou
        qglLoadIdentity();CHECKGLERROR
        // set view pyramid
        nudge = 1.0 - 1.0 / (1<<23);
-       m[ 0] = 1.0 / tan(fovx * M_PI / 360.0);
+       m[ 0] = 1.0 / frustumx;
        m[ 1] = 0;
        m[ 2] = 0;
        m[ 3] = 0;
        m[ 4] = 0;
-       m[ 5] = 1.0 / tan(fovy * M_PI / 360.0);
+       m[ 5] = 1.0 / frustumy;
        m[ 6] = 0;
        m[ 7] = 0;
        m[ 8] = 0;
@@ -1737,17 +1733,6 @@ void R_ClearScreen(void)
        }
 }
 
-/*
-====================
-CalcFov
-====================
-*/
-float CalcFov (float fov_x, float width, float height)
-{
-       // calculate vision size and alter by aspect, then convert back to angle
-       return atan (((height/width)/vid_pixelaspect.value)*tan(fov_x/360.0*M_PI))*360.0/M_PI;
-}
-
 int r_stereo_side;
 
 void SCR_DrawScreen (void)
@@ -1797,8 +1782,16 @@ void SCR_DrawScreen (void)
                        }
 
                        // LordHavoc: viewzoom (zoom in for sniper rifles, etc)
-                       r_refdef.fov_x = scr_fov.value * r_refdef.fovscale_x;
-                       r_refdef.fov_y = CalcFov (scr_fov.value, r_refdef.width, r_refdef.height) * r_refdef.fovscale_y;
+                       // 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.frustum_y = tan(scr_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
+                       r_refdef.frustum_x = r_refdef.frustum_y * (float)r_refdef.width / (float)r_refdef.height / vid_pixelheight.value;
+
+                       r_refdef.frustum_x *= r_refdef.frustumscale_x;
+                       r_refdef.frustum_y *= r_refdef.frustumscale_y;
 
                        R_RenderView();
 
@@ -1810,8 +1803,12 @@ void SCR_DrawScreen (void)
                                r_refdef.height = vid.height * sizey;
                                r_refdef.x = (vid.width - r_refdef.width)/2;
                                r_refdef.y = 0;
-                               r_refdef.fov_x = scr_zoomwindow_fov.value * r_refdef.fovscale_x;
-                               r_refdef.fov_y = CalcFov(scr_zoomwindow_fov.value, r_refdef.width, r_refdef.height) * r_refdef.fovscale_y;
+
+                               r_refdef.frustum_y = tan(scr_zoomwindow_fov.value * cl.viewzoom * M_PI / 360.0) * (3.0/4.0);
+                               r_refdef.frustum_x = r_refdef.frustum_y * vid_pixelheight.value * (float)r_refdef.width / (float)r_refdef.height;
+
+                               r_refdef.frustum_x *= r_refdef.frustumscale_x;
+                               r_refdef.frustum_y *= r_refdef.frustumscale_y;
 
                                R_RenderView();
                        }
index 198e17f8d1b929ad15786d6f10032c4bff9f7485..fa7961a90963be31edd94d12a950eaaa796920b0 100644 (file)
@@ -9,8 +9,8 @@ extern int polygonelements[768];
 
 void GL_SetupView_Orientation_Identity(void);
 void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix);
-void GL_SetupView_Mode_Perspective(double fovx, double fovy, double zNear, double zFar);
-void GL_SetupView_Mode_PerspectiveInfiniteFarClip(double fovx, double fovy, double zNear);
+void GL_SetupView_Mode_Perspective(double frustumx, double frustumy, double zNear, double zFar);
+void GL_SetupView_Mode_PerspectiveInfiniteFarClip(double frustumx, double frustumy, double zNear);
 void GL_SetupView_Mode_Ortho(double x1, double y1, double x2, double y2, double zNear, double zFar);
 void GL_BlendFunc(int blendfunc1, int blendfunc2);
 void GL_DepthMask(int state);
index 41836e13a3199864547c879cfb6868359d82b4c4..7509ea46e907ee13011d656d526cbf21cd7f0a47 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -535,8 +535,6 @@ void R_DrawQueue(void)
        r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
        r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
        r_view_z = 0;
-       r_view_fov_x = bound(0.1, r_refdef.fov_x, 170);
-       r_view_fov_y = bound(0.1, r_refdef.fov_y, 170);
        r_view_matrix = r_refdef.viewentitymatrix;
        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
 
index 143c4fb127bad11cd6ffcef8ba76ea54bcd8bfb4..d1291faa51a0e1b00773313dd0ea6a5b2fceec74 100644 (file)
@@ -62,8 +62,6 @@ int r_view_z;
 int r_view_width;
 int r_view_height;
 int r_view_depth;
-float r_view_fov_x;
-float r_view_fov_y;
 matrix4x4_t r_view_matrix;
 
 //
@@ -716,34 +714,118 @@ static void R_SetFrustum(void)
        Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
        VectorNegate(r_viewleft, r_viewright);
 
-       // LordHavoc: note to all quake engine coders, the special case for 90
-       // degrees assumed a square view (wrong), so I removed it, Quake2 has it
-       // disabled as well.
+#if 0
+       frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
+       frustum[0].normal[1] = 0 - 0;
+       frustum[0].normal[2] = -1 - 0;
+       frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
+       frustum[1].normal[1] = 0 + 0;
+       frustum[1].normal[2] = -1 + 0;
+       frustum[2].normal[0] = 0 - 0;
+       frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
+       frustum[2].normal[2] = -1 - 0;
+       frustum[3].normal[0] = 0 + 0;
+       frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
+       frustum[3].normal[2] = -1 + 0;
+#endif
 
-       // rotate R_VIEWFORWARD right by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
+#if 0
+       zNear = 1.0;
+       nudge = 1.0 - 1.0 / (1<<23);
+       frustum[4].normal[0] = 0 - 0;
+       frustum[4].normal[1] = 0 - 0;
+       frustum[4].normal[2] = -1 - -nudge;
+       frustum[4].dist = 0 - -2 * zNear * nudge;
+       frustum[5].normal[0] = 0 + 0;
+       frustum[5].normal[1] = 0 + 0;
+       frustum[5].normal[2] = -1 + -nudge;
+       frustum[5].dist = 0 + -2 * zNear * nudge;
+#endif
+
+
+
+#if 0
+       frustum[0].normal[0] = m[3] - m[0];
+       frustum[0].normal[1] = m[7] - m[4];
+       frustum[0].normal[2] = m[11] - m[8];
+       frustum[0].dist = m[15] - m[12];
+
+       frustum[1].normal[0] = m[3] + m[0];
+       frustum[1].normal[1] = m[7] + m[4];
+       frustum[1].normal[2] = m[11] + m[8];
+       frustum[1].dist = m[15] + m[12];
+
+       frustum[2].normal[0] = m[3] - m[1];
+       frustum[2].normal[1] = m[7] - m[5];
+       frustum[2].normal[2] = m[11] - m[9];
+       frustum[2].dist = m[15] - m[13];
+
+       frustum[3].normal[0] = m[3] + m[1];
+       frustum[3].normal[1] = m[7] + m[5];
+       frustum[3].normal[2] = m[11] + m[9];
+       frustum[3].dist = m[15] + m[13];
+
+       frustum[4].normal[0] = m[3] - m[2];
+       frustum[4].normal[1] = m[7] - m[6];
+       frustum[4].normal[2] = m[11] - m[10];
+       frustum[4].dist = m[15] - m[14];
+
+       frustum[5].normal[0] = m[3] + m[2];
+       frustum[5].normal[1] = m[7] + m[6];
+       frustum[5].normal[2] = m[11] + m[10];
+       frustum[5].dist = m[15] + m[14];
+#endif
+
+
+
+       VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
+       VectorMAM(1, r_viewforward, 1.0 /  r_refdef.frustum_x, r_viewleft, frustum[1].normal);
+       VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
+       VectorMAM(1, r_viewforward, 1.0 /  r_refdef.frustum_y, r_viewup, frustum[3].normal);
+       VectorCopy(r_viewforward, frustum[4].normal);
+       VectorNormalize(frustum[0].normal);
+       VectorNormalize(frustum[1].normal);
+       VectorNormalize(frustum[2].normal);
+       VectorNormalize(frustum[3].normal);
        frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
+       frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
+       frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
+       frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
+       frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
        PlaneClassify(&frustum[0]);
+       PlaneClassify(&frustum[1]);
+       PlaneClassify(&frustum[2]);
+       PlaneClassify(&frustum[3]);
+       PlaneClassify(&frustum[4]);
+
+       // LordHavoc: note to all quake engine coders, Quake had a special case
+       // for 90 degrees which assumed a square view (wrong), so I removed it,
+       // Quake2 has it disabled as well.
+
+       // rotate R_VIEWFORWARD right by FOV_X/2 degrees
+       //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
+       //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
+       //PlaneClassify(&frustum[0]);
 
        // rotate R_VIEWFORWARD left by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
-       frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
-       PlaneClassify(&frustum[1]);
+       //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
+       //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
+       //PlaneClassify(&frustum[1]);
 
        // rotate R_VIEWFORWARD up by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
-       frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
-       PlaneClassify(&frustum[2]);
+       //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
+       //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
+       //PlaneClassify(&frustum[2]);
 
        // rotate R_VIEWFORWARD down by FOV_X/2 degrees
-       RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
-       frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
-       PlaneClassify(&frustum[3]);
+       //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
+       //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
+       //PlaneClassify(&frustum[3]);
 
        // nearclip plane
-       VectorCopy(r_viewforward, frustum[4].normal);
-       frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
-       PlaneClassify(&frustum[4]);
+       //VectorCopy(r_viewforward, frustum[4].normal);
+       //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
+       //PlaneClassify(&frustum[4]);
 }
 
 static void R_BlendView(void)
@@ -981,8 +1063,6 @@ void R_RenderView(void)
        r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
        r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
        r_view_z = 0;
-       r_view_fov_x = bound(1, r_refdef.fov_x, 170);
-       r_view_fov_y = bound(1, r_refdef.fov_y, 170);
        r_view_matrix = r_refdef.viewentitymatrix;
        GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
        r_rtworld = r_shadow_realtime_world.integer;
@@ -1034,9 +1114,9 @@ void R_RenderScene(void)
 
        r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
        if (r_rtworldshadows || r_rtdlightshadows)
-               GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
+               GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
        else
-               GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
+               GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
 
        GL_SetupView_Orientation_FromEntity(&r_view_matrix);
 
diff --git a/menu.c b/menu.c
index 80953b1688b62d89644ac7ad5a9246a939b01d39..eca046cf10cc57a4d5641b4e92e6d23284f74e44 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -2722,40 +2722,116 @@ void M_Reset_Draw (void)
 //=============================================================================
 /* VIDEO MENU */
 
-#define VIDEO_ITEMS 5
+// note: if modes are added to the beginning of this list, update VID_DEFAULT
+typedef struct video_resolution_s
+{
+       const char *type;
+       int width, height;
+       int conwidth, conheight;
+       double pixelheight; // pixel aspect
+}
+video_resolution_t;
+video_resolution_t video_resolutions[] =
+{
+{"Standard 4x3"              ,  320, 240, 320, 240, 1     },
+{"Standard 4x3"              ,  400, 300, 400, 300, 1     },
+{"Standard 4x3"              ,  512, 384, 512, 384, 1     },
+{"Standard 4x3"              ,  640, 480, 640, 480, 1     },
+{"Standard 4x3"              ,  800, 600, 640, 480, 1     },
+{"Standard 4x3"              , 1024, 768, 640, 480, 1     },
+{"Standard 4x3"              , 1152, 864, 640, 480, 1     },
+{"Standard 4x3"              , 1280, 960, 640, 480, 1     },
+{"Standard 4x3"              , 1600,1200, 640, 480, 1     },
+{"Standard 4x3"              , 1792,1344, 640, 480, 1     },
+{"Standard 4x3"              , 1920,1440, 640, 480, 1     },
+{"Standard 4x3"              , 2048,1536, 640, 480, 1     },
+{"Short Pixel (CRT) 5x4"     ,  320, 256, 320, 256, 0.9375},
+{"Short Pixel (CRT) 5x4"     ,  640, 512, 640, 512, 0.9375},
+{"Short Pixel (CRT) 5x4"     , 1280,1024, 640, 512, 0.9375},
+{"Tall Pixel (CRT) 8x5"      ,  320, 200, 320, 200, 1.2   },
+{"Tall Pixel (CRT) 8x5"      ,  640, 400, 640, 400, 1.2   },
+{"Tall Pixel (CRT) 8x5"      ,  840, 525, 640, 400, 1.2   },
+{"Tall Pixel (CRT) 8x5"      ,  960, 600, 640, 400, 1.2   },
+{"Tall Pixel (CRT) 8x5"      , 1680,1050, 640, 400, 1.2   },
+{"Tall Pixel (CRT) 8x5"      , 1920,1200, 640, 400, 1.2   },
+{"Square Pixel (LCD) 5x4"    ,  320, 256, 320, 256, 1     },
+{"Square Pixel (LCD) 5x4"    ,  640, 512, 640, 512, 1     },
+{"Square Pixel (LCD) 5x4"    , 1280,1024, 640, 512, 1     },
+{"WideScreen 5x3"            ,  640, 384, 640, 384, 1     },
+{"WideScreen 5x3"            , 1280, 768, 640, 384, 1     },
+{"WideScreen 8x5"            ,  320, 200, 320, 200, 1     },
+{"WideScreen 8x5"            ,  640, 400, 640, 400, 1     },
+{"WideScreen 8x5"            ,  840, 525, 640, 400, 1     },
+{"WideScreen 8x5"            ,  960, 600, 640, 400, 1     },
+{"WideScreen 8x5"            , 1680,1050, 640, 400, 1     },
+{"WideScreen 8x5"            , 1920,1200, 640, 400, 1     },
+{"WideScreen 8x5"            , 2560,1600, 640, 400, 1     },
+{"WideScreen 8x5"            , 3840,2400, 640, 400, 1     },
+{"WideScreen 14x9"           ,  840, 540, 640, 400, 1     },
+{"WideScreen 14x9"           , 1680,1080, 640, 400, 1     },
+{"WideScreen 16x9"           ,  640, 360, 640, 360, 1     },
+{"WideScreen 16x9"           ,  683, 384, 683, 384, 1     },
+{"WideScreen 16x9"           ,  960, 540, 640, 360, 1     },
+{"WideScreen 16x9"           , 1280, 720, 640, 360, 1     },
+{"WideScreen 16x9"           , 1366, 768, 683, 384, 1     },
+{"WideScreen 16x9"           , 1920,1080, 640, 360, 1     },
+{"WideScreen 16x9"           , 2560,1440, 640, 360, 1     },
+{"WideScreen 16x9"           , 3840,2160, 640, 360, 1     },
+{"NTSC 3x2"                  ,  360, 240, 360, 240, 1.125 },
+{"NTSC 3x2"                  ,  720, 480, 720, 480, 1.125 },
+{"PAL 14x11"                 ,  360, 283, 360, 283, 0.9545},
+{"PAL 14x11"                 ,  720, 566, 360, 566, 0.9545},
+{"NES 8x7"                   ,  256, 224, 256, 224, 1.1667},
+{"SNES 8x7"                  ,  512, 448, 512, 448, 1.1667},
+{NULL, 0, 0, 0, 0, 0}
+};
+// this is the number of the default mode (640x480) in the list above
+#define VID_DEFAULT 3
+#define VID_RES_COUNT ((int)(sizeof(video_resolutions) / sizeof(video_resolutions[0])) - 1)
 
+#define VIDEO_ITEMS 7
 int video_cursor = 0;
-int video_cursor_table[] = {56, 68, 80, 100, 130};
-// note: if modes are added to the beginning of this list, update the
-// video_resolution = x; in M_Menu_Video_f below
-unsigned short video_resolutions[][2] = {{320,240}, {400,300}, {512,384}, {640,480}, {800,600}, {1024,768}, {1152,864}, {1280,960}, {1280,1024}, {1600,1200}, {1792,1344}, {1920,1440}, {2048,1536}, {0,0}};
-// this is the number of the 640x480 mode in the list
-#define VID_640 3
-#define VID_RES_COUNT ((int)(sizeof(video_resolutions) / sizeof(video_resolutions[0])) - 1)
+int video_cursor_table[] = {56, 68, 88, 100, 112, 132, 162};
 int video_resolution;
 
-
 void M_Menu_Video_f (void)
 {
+       int i;
+
        key_dest = key_menu;
        m_state = m_video;
        m_entersound = true;
 
-       // Look for the current resolution
-       for (video_resolution = 0; video_resolution < VID_RES_COUNT; video_resolution++)
+       // Look for the closest match to the current resolution
+       video_resolution = 0;
+       for (i = 1;i < VID_RES_COUNT;i++)
        {
-               if (video_resolutions[video_resolution][0] == vid.width &&
-                       video_resolutions[video_resolution][1] == vid.height)
-                       break;
-       }
-
-       // Default to VID_640 if we didn't find it
-       if (video_resolution == VID_RES_COUNT)
-       {
-               // may need to update this number if mode list changes
-               video_resolution = VID_640;
-               Cvar_SetValueQuick (&vid_width, video_resolutions[video_resolution][0]);
-               Cvar_SetValueQuick (&vid_height, video_resolutions[video_resolution][1]);
+               // if the new mode would be a worse match in width, skip it
+               if (fabs(video_resolutions[i].width - vid.width) > fabs(video_resolutions[video_resolution].width - vid.width))
+                       continue;
+               // if it is equal in width, check height
+               if (video_resolutions[i].width == vid.width && video_resolutions[video_resolution].width == vid.width)
+               {
+                       // if the new mode would be a worse match in height, skip it
+                       if (fabs(video_resolutions[i].height - vid.height) > fabs(video_resolutions[video_resolution].height - vid.height))
+                               continue;
+                       // if it is equal in width and height, check pixel aspect
+                       if (video_resolutions[i].height == vid.height && video_resolutions[video_resolution].height == vid.height)
+                       {
+                               // if the new mode would be a worse match in pixel aspect, skip it
+                               if (fabs(video_resolutions[i].pixelheight - vid_pixelheight.value) > fabs(video_resolutions[video_resolution].pixelheight - vid_pixelheight.value))
+                                       continue;
+                               // if it is equal in everything, skip it (prefer earlier modes)
+                               if (video_resolutions[i].pixelheight == vid_pixelheight.value && video_resolutions[video_resolution].pixelheight == vid_pixelheight.value)
+                                       continue;
+                               // better match for width, height, and pixel aspect
+                               video_resolution = i;
+                       }
+                       else // better match for width and height
+                               video_resolution = i;
+               }
+               else // better match for width
+                       video_resolution = i;
        }
 }
 
@@ -2763,7 +2839,6 @@ void M_Menu_Video_f (void)
 void M_Video_Draw (void)
 {
        cachepic_t      *p;
-       const char* string;
 
        M_Background(320, 200);
 
@@ -2771,25 +2846,36 @@ void M_Video_Draw (void)
        p = Draw_CachePic("gfx/vidmodes", false);
        M_DrawPic((320-p->width)/2, 4, "gfx/vidmodes");
 
-       // Resolution
-       M_Print(16, video_cursor_table[0], "            Resolution");
-       string = va("%dx%d", video_resolutions[video_resolution][0], video_resolutions[video_resolution][1]);
-       M_Print(220, video_cursor_table[0], string);
+       // Current Resolution
+       M_Print(16, video_cursor_table[0], "    Current Resolution");
+       if (vid_supportrefreshrate && vid.fullscreen)
+               M_Print(220, video_cursor_table[0], va("%dx%d %dhz", vid.width, vid.height, vid.refreshrate));
+       else
+               M_Print(220, video_cursor_table[0], va("%dx%d", vid.width, vid.height));
+
+       // Proposed Resolution
+       M_Print(16, video_cursor_table[1], "        New Resolution");
+       M_Print(220, video_cursor_table[1], va("%dx%d", video_resolutions[video_resolution].width, video_resolutions[video_resolution].height));
+       M_Print(96, video_cursor_table[1] + 8, va("Type: %s", video_resolutions[video_resolution].type));
 
        // Bits per pixel
-       M_Print(16, video_cursor_table[1], "        Bits per pixel");
-       M_Print(220, video_cursor_table[1], (vid_bitsperpixel.integer == 32) ? "32" : "16");
+       M_Print(16, video_cursor_table[2], "        Bits per pixel");
+       M_Print(220, video_cursor_table[2], (vid_bitsperpixel.integer == 32) ? "32" : "16");
+
+       // Refresh Rate
+       M_ItemPrint(16, video_cursor_table[3], "          Refresh Rate", vid_supportrefreshrate);
+       M_DrawSlider(220, video_cursor_table[3], vid_refreshrate.integer, 60, 150);
 
        // Fullscreen
-       M_Print(16, video_cursor_table[2], "            Fullscreen");
-       M_DrawCheckbox(220, video_cursor_table[2], vid_fullscreen.integer);
+       M_Print(16, video_cursor_table[4], "            Fullscreen");
+       M_DrawCheckbox(220, video_cursor_table[4], vid_fullscreen.integer);
 
        // "Apply" button
-       M_Print(220, video_cursor_table[3], "Apply");
+       M_Print(220, video_cursor_table[5], "Apply");
 
        // Vertical Sync
-       M_ItemPrint (0, video_cursor_table[4], "         Vertical Sync", gl_videosyncavailable);
-       M_DrawCheckbox(220, video_cursor_table[4], vid_vsync.integer);
+       M_ItemPrint(16, video_cursor_table[6], "         Vertical Sync", gl_videosyncavailable);
+       M_DrawCheckbox(220, video_cursor_table[6], vid_vsync.integer);
 
        // Cursor
        M_DrawCharacter(200, video_cursor_table[video_cursor], 12+((int)(realtime*4)&1));
@@ -2803,30 +2889,35 @@ void M_Menu_Video_AdjustSliders (int dir)
        switch (video_cursor)
        {
                // Resolution
-               case 0:
+               case 1:
                {
-                       int new_resolution = video_resolution + dir;
-                       if (gamemode == GAME_FNIGGIUM ? new_resolution < VID_640 : new_resolution < 0)
-                               video_resolution = VID_RES_COUNT - 1;
-                       else if (new_resolution > VID_RES_COUNT - 1)
-                               video_resolution = gamemode == GAME_FNIGGIUM ? VID_640 : 0;
-                       else
-                               video_resolution = new_resolution;
-
-                       Cvar_SetValueQuick (&vid_width, video_resolutions[video_resolution][0]);
-                       Cvar_SetValueQuick (&vid_height, video_resolutions[video_resolution][1]);
+                       int r;
+                       for(r = 0;r < VID_RES_COUNT;r++)
+                       {
+                               video_resolution += dir;
+                               if (video_resolution >= VID_RES_COUNT)
+                                       video_resolution = 0;
+                               if (video_resolution < 0)
+                                       video_resolution = VID_RES_COUNT - 1;
+                               if (video_resolutions[video_resolution].width >= vid_minwidth.integer && video_resolutions[video_resolution].height >= vid_minheight.integer)
+                                       break;
+                       }
                        break;
                }
 
                // Bits per pixel
-               case 1:
+               case 2:
                        Cvar_SetValueQuick (&vid_bitsperpixel, (vid_bitsperpixel.integer == 32) ? 16 : 32);
                        break;
-               case 2:
+               // Refresh Rate
+               case 3:
+                       Cvar_SetValueQuick (&vid_refreshrate, vid_refreshrate.integer + dir);
+                       break;
+               case 4:
                        Cvar_SetValueQuick (&vid_fullscreen, !vid_fullscreen.integer);
                        break;
 
-               case 4:
+               case 6:
                        Cvar_SetValueQuick (&vid_vsync, !vid_vsync.integer);
                        break;
        }
@@ -2840,9 +2931,9 @@ void M_Video_Key (int key, char ascii)
                case K_ESCAPE:
                        // vid_shared.c has a copy of the current video config. We restore it
                        Cvar_SetValueQuick(&vid_fullscreen, vid.fullscreen);
-                       Cvar_SetValueQuick(&vid_width, vid.width);
-                       Cvar_SetValueQuick(&vid_height, vid.height);
                        Cvar_SetValueQuick(&vid_bitsperpixel, vid.bitsperpixel);
+                       if (vid_supportrefreshrate)
+                               Cvar_SetValueQuick(&vid_refreshrate, vid.refreshrate);
 
                        S_LocalSound ("sound/misc/menu1.wav");
                        M_Menu_Options_f ();
@@ -2852,7 +2943,12 @@ void M_Video_Key (int key, char ascii)
                        m_entersound = true;
                        switch (video_cursor)
                        {
-                               case 3:
+                               case 5:
+                                       Cvar_SetValueQuick (&vid_width, video_resolutions[video_resolution].width);
+                                       Cvar_SetValueQuick (&vid_height, video_resolutions[video_resolution].height);
+                                       Cvar_SetValueQuick (&vid_conwidth, video_resolutions[video_resolution].conwidth);
+                                       Cvar_SetValueQuick (&vid_conheight, video_resolutions[video_resolution].conheight);
+                                       Cvar_SetValueQuick (&vid_pixelheight, video_resolutions[video_resolution].pixelheight);
                                        Cbuf_AddText ("vid_restart\n");
                                        M_Menu_Options_f ();
                                        break;
index e6ff9e79aeab82f4e9ab20aba74e32ca056b2af6..c877265a86eb7d7b976531c93ee39cd5d1c9734a 100644 (file)
--- a/render.h
+++ b/render.h
@@ -162,8 +162,6 @@ extern int r_view_z;
 extern int r_view_width;
 extern int r_view_height;
 extern int r_view_depth;
-extern float r_view_fov_x;
-extern float r_view_fov_y;
 extern matrix4x4_t r_view_matrix;
 
 extern mleaf_t         *r_viewleaf, *r_oldviewleaf;
diff --git a/view.c b/view.c
index 60da3e3dfdf007f4bdf4d4c732300c5637b68ca0..3c4d5314821cceac1a411a025ac19c2464e7afbf 100644 (file)
--- a/view.c
+++ b/view.c
@@ -514,8 +514,8 @@ void V_CalcViewBlend(void)
        r_refdef.viewblend[1] = 0;
        r_refdef.viewblend[2] = 0;
        r_refdef.viewblend[3] = 0;
-       r_refdef.fovscale_x = cl.viewzoom;
-       r_refdef.fovscale_y = cl.viewzoom;
+       r_refdef.frustumscale_x = 1;
+       r_refdef.frustumscale_y = 1;
        if (cls.state == ca_connected && cls.signon == SIGNONS && gl_polyblend.value > 0)
        {
                // set contents color
@@ -525,8 +525,8 @@ void V_CalcViewBlend(void)
                supercontents = CL_PointSuperContents(vieworigin);
                if (supercontents & SUPERCONTENTS_LIQUIDSMASK)
                {
-                       r_refdef.fovscale_x *= 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
-                       r_refdef.fovscale_y *= 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
+                       r_refdef.frustumscale_x *= 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
+                       r_refdef.frustumscale_y *= 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
                        if (supercontents & SUPERCONTENTS_LAVA)
                        {
                                cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255;