Inside3D!
     

Re: Fixes for widescreen displays (Part 2: 3D)

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials
View previous topic :: View next topic  
Author Message
mh



Joined: 12 Jan 2008
Posts: 909

PostPosted: Fri Dec 19, 2008 12:15 am    Post subject: Re: Fixes for widescreen displays (Part 2: 3D) Reply with quote

mh wrote:
OK, I posted parts of this one on QuakeSrc back in the day, but it didn't survive the Great Catastrophe, so here it is again in improved, debugged and 2008 form.

If you've ever played Quake on a widescreen display, you'll have noticed that while the width is correct, the top and bottom of the 3D views is cut off. You can obviously fix this by setting the value of the fov cvar to something higher (102 worked well for me), but you shouldn't have to. You'll also have noticed that the console, status bar pictures and menus are stretched. These two tutorials will resolve all of that.

The first one we're going to do is the 2D stuff, but before I even start anything...

BEGIN DISCLAIMER
Some people may feel that a wider FOV is cheating. I'm taking the viewpoint that as Quake lets you set the FOV anyway, there is no cheating involved, at least beyond what's possible with normal Quake. Server administrators should propose a protocol extension that requires servers to examine FOV settings and enforce them on clients if there are any bad feelings about this.
END DISCLAIMER


Here we go again. Very Happy

This one is even easier than the last, as it all revolves around the SCR_CalcRefdef and CalcFov functions in gl_screen.c; so let's jump right in.

The first thing we do is replace CalcFov with these two:
Code:
float SCR_CalcFovX (float fov_y, float width, float height)
{
   float   a;
   float   y;

   // bound, don't crash
   if (fov_y < 1) fov_y = 1;
   if (fov_y > 179) fov_y = 179;

   y = height / tan (fov_y / 360 * M_PI);

   a = atan (width / y);

    a = a * 360 / M_PI;

    return a;
}


float SCR_CalcFovY (float fov_x, float width, float height)
{
   float   a;
   float   x;

   // bound, don't crash
   if (fov_x < 1) fov_x = 1;
   if (fov_x > 179) fov_x = 179;

   x = width / tan (fov_x / 360 * M_PI);

   a = atan (height / x);

    a = a * 360 / M_PI;

    return a;
}


The second one (SCR_CalcFovY) is the exact same as the old CalcFov, but with the Sys_Error removed. If you look closely, you'll actually notice that both are the same function - you just flip width and height - but I prefer to keep them separate so that it's more obvious what's going on.

Speaking of obvious, all we're doing here is calculating an X FOV from a given Y FOV and vice-versa.

Now we need to actually use them, so pop this code into SCR_CalcRefdef. Again, I've given the line just before and after so you'll know where to insert it:
Code:
   r_refdef.fov_x = scr_fov.value;

   // calculate y fov as if the screen was 640 x 432; this ensures that the top and bottom
   // don't get clipped off if we have a widescreen display
   r_refdef.fov_y = SCR_CalcFovY (r_refdef.fov_x, 640, 432);

   // now recalculate fov_x so that it's correctly proportioned for fov_y
   r_refdef.fov_x = SCR_CalcFovX (r_refdef.fov_y, r_refdef.vrect.width, r_refdef.vrect.height);

   scr_vrect = r_refdef.vrect;


That's literally it. We calculate the y fov (which is used for our projection matrix and frustum culling) as if the screen was 640 x 432, which seems as bit weird (why not 480?), but was chosen as Quake's "intended aspect ratio" (i.e. running at 640 x 480 with a full status bar showing), thus ensuring that we get a consistent vertical field of view, irrespective of the screen's resolution. Then we recalculate the horizontal field of view to get the extra stuff at the sides.

This code, by the way, will work for any aspect ratio - there's no need to check for a widescreen display aspect as part of it. However, you might notice that if you have a display that's narrower than 4:3 you'll start losing stuff at the sides. Fortunately, this is rarer, and even at the only common resolution it affects (1280 x 1024) there's no dramatic loss.

We really should fix that too, though, but that's a project for another day!
_________________
DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines
Back to top
View user's profile Send private message Visit poster's website
mh



Joined: 12 Jan 2008
Posts: 909

PostPosted: Sun Dec 21, 2008 4:23 pm    Post subject: Reply with quote

There's a part 3 to come here, by the way - fixing what happens when you play at a fullscreen resolution that's not the same aspect as your monitor. Very Happy
_________________
DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines
Back to top
View user's profile Send private message Visit poster's website
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Mon Apr 26, 2010 11:48 pm    Post subject: Reply with quote

mh wrote:
There's a part 3 to come here, by the way - fixing what happens when you play at a fullscreen resolution that's not the same aspect as your monitor. Very Happy


This set has been very useful, but I cannot find part 3.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
mh



Joined: 12 Jan 2008
Posts: 909

PostPosted: Thu May 06, 2010 12:20 pm    Post subject: Reply with quote

I can't even remember if I ever did it! Laughing
_________________
DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group