Graphics.NonstandardAspectRatios - lordmundi/wikidoctest GitHub Wiki
Nonstandard Aspect Ratios
Customer:
I want to define a camera that has a "non-4:3" aspect ratio, such as an HDTV camera that has a 16:9 aspect ratio. Also, I would like that aspect ratio enforced so that it is maintained independent of the size of the viewport.
Developer:
You sure you want that? I mean, 4:3 cameras are fine… and they are cool. Are you saying you don't want to be cool?
Customer:
Yes, I really want that. My application requires a different aspect ratio to modeled as a physical camera. And no, I don't want to quit my job.
Developer:
Ok then. Get comfortable.
First things first. If you want an aspect ratio enforced, you are going to need the cctv plugin running.
Customer:
Ok, that's not so bad. Isn't it already running by default?
Developer:
In versions before EDGE v2.4 it was. For versions >= v2.4 it was removed in the default loads, so you'll need to add it in.
Customer:
OK. Then why did you mention it?
Developer:
Well, because it is the reason this is difficult. It assumes a 4:3 aspect ratio.
Customer:
Then maybe I shouldn't run that. Sounds bad.
Developer:
Don't you listen? I said you need to run the cctv plugin. The DOUG gods demand it. Do you want to suffer the wrath of the DOUG gods?
Customer:
No. I dare not go up against the DOUG gods.
Developer:
Ok then. You need to keep the cctv plugin running.
Customer:
So, how do I get what I want?
Developer:
Well, you will have to define your camera in the typical manner. See the article on Adding a camera if you don't know how to do this. If you want zoom stops you will also want to associate a camera type with the "type" attribute to specify the near and far vertical FOV limits.
The difference is, we are going to define a special lens using the cctv plugin and apply that lens to the camera. This is how we are going to get the different aspect ratio that we want.
To do this, we are going to add a CCTV_INFO block to the bottom of our $USERDATA/configs/user_models.cfg (you might want to grep around to make sure you don't already have a block like this, but you probably don't). For example:
CCTV_INFO
{
# Vertical = atan( tan( Horizontal / 2 ) / aspect_ratio ) * 2
# OR
# use "-" to have it auto-compute from the aspect ration and HFOV
LENS_INFO
{
# LENS-NAME HORIZONTAL-FOV-RANGE VERTICAL-FOV-RANGE OPTICAL-AXIS-OFFSETS FILM-PLANE
# MIN MAX MIN MAX H V ASPECT-RATIO DISTORTION_FUNCTION
#
example_lens 0.2 90.0 - - 0.0 0.0 1.77777 NONE
}
example_cam
{
5.0 80.0 example_lens
}
}
If we add that to the bottom of our user_models.cfg, we are telling the cctv plugin to define a new lens called example_lens with an aspect ratio of 1.7777. We define the horizontal FOV range and then we define the vertical FOV range as "-" to tell the plugin to auto-calculate the values based on the horizontal range and the aspect ratio.
Next we tell the plugin that we want to apply the "example_lens" lens to the "example_cam" camera between the horizontal FOV range 5.0 - 80.0. If we wanted, we could define multiple ranges here and lenses to dynamically switch the lens based on the HFOV we are currently at. But that is a little more advanced than you probably need. Also, keep in mind that this range is the doug HFOV (dhfov) and not the actual HFOV (ahfov).
Customer:
Uhh… the doug HFOV?
Developer:
Dude. You interrupted me. I was on a roll.
Customer:
I'm sorry.
Developer:
Where was I? Did I mention you weren't cool? 4:3 cameras are cool.
Customer:
Yes. You were talking about doug HFOV and actual HFOV.
Developer:
Ah yes. As I was saying, before somebody interrupted me, this range is the doug HFOV. Basically, the cctv plugin assumes a 4:3 ratio. If you want to see the actual HFOV, you need to use the FOV overlay. The article about using the FOV overlay explains this in more detail. Basically, there are various reasons why the HFOV in the view would not match the HFOV that doug stores internally for a camera that is shown in the camera edit dialog. Applying a different lens via the cctv plugin is one of those reasons.
So, you will probably want to go back to your camera definition and add the "show( FOV );" attribute to it so that you can see the actual FOV for the camera.
If you rerun DOUG now, and then assign the "example_cam" to a viewport, you should see a view that is having the aspect ratio enforced, but is wider than 4:3. You should also see the FOV in the upper left. You should be able to resize the DOUG window and see the FOV stay constant.
Now comes the fun part. If the data internal to DOUG doesn't represent the actual HFOV, how do you know what to set it to in order to get a specific actual HFOV? Like I said. The fun part.
Let's look at this from the point of view of the entire zoomable range of the camera. Basically, you have the range defined in 3 places. You have the VFOV range defined in the camera type. This is a doug VFOV and it manages the zoom limits. Then there is the HFOV range defined for the camera in the CCTV_INFO block (the one for the camera, not the lens). This is a doug HFOV range, but only serves to define the mapping of the doug HFOV range to the lens range. Lastly you have the HFOV range defined for the lens. This is an actual HFOV range.
So, how do these 3 play together? Well the doug_VFOV range (the one in the camera type and used for zoom limits) and doug_HFOV range (the one used to map a HFOV range to a custom lens) are related by the 1.33333 factor from the 4:3 assumption. The problem is that their half-tangents are related by these numbers, not the numbers themselves. For example, let's say we had a camera defined that used a type attribute called "EXAMPLE_TYPE":
node(example_cam); type( EXAMPLE_TYPE ); xyz( 0.0, 0.0, 0.0 ); parent( CM_Cam ); show( FOV, NAME );
and then, further down where we define camera types, we define a type called "EXAMPLE_TYPE"
EXAMPLE_TYPE c 3.851 64.266445
That is a doug VFOV range. These numbers are based off of the doug HFOV range we defined above (5.0 - 80.0) in the following manner:
{ dVFOV } = 2 \times \arctan{\displaystyle \left(\tan{\left(dHFOV \over 2\right)} \over 1.33333 \right)}
In pseudo-code, this is basically dividing the horizontal in half, taking the tangent, dividing by the aspect ratio, then taking the inverse tangent, and multiplying by 2.
As you can see the numbers are still related by the aspect ratio, except it is the half-tangent that is related. Also, you may notice the numbers from the calculation are slightly different than the ones i used above (3.751 != 3.851). This is because I like to close the zoom stops just slightly inside of the mapped range. I did it by a tenth of a degree in this case.
So that gets you the relationship from the doug HFOV and doug VFOV, which isn't so bad. The tricky part is relating the doug_HFOV with the actual_HFOV. Think of a marker somewhere on a number line between the min and max of the doug_HFOV range showing the current doug_HFOV. If you took that percentage on that number line and applied it to the number line with the actual_HFOV range, you would almost be correct. For example, if the current doug_HFOV was 3 and our range for doug_HFOV was 0 to 10, we would be 30 percent down the number line, and then could go 30 percent of the range defined for the actual_HFOV.
But that isn't quite it. The reason is because the number lines we are talking about here are based on the half-tangent space of the angles, and not the angles themselves.
So, to get the actual mapping in the half-tangent space, we have the following relationship:
This math is wrong… Don't use this math until i correct it!!! (You can use everything else in the article) — frankie May 30, 2007, at 10:19 AM
{ aHFOV } = 2 \times \arctan{\displaystyle \left(\tan{\left(minactualHFOV \over 2\right)} + {{\bf percent }\left(\bf actualHFOVrange \right)} \right)}
where:
{ \bf percent } = \frac {\displaystyle \tan{\left(dHFOV \over 2\right)} - \tan{\left(mindougHFOV \over 2\right)}} {\displaystyle \bf dougHFOVrange }
{ \bf dougHFOVrange } = \displaystyle \tan{\left(maxdougHFOV \over 2\right)} - \tan{\left(mindougHFOV \over 2\right)}
{ \bf actualHFOVrange } = \displaystyle \tan{\left(maxactualHFOV \over 2\right)} - \tan{\left(minactualHFOV \over 2\right)}
That will convert a doug_HFOV reading to an actual_HFOV range and vice versa.
You still there?
Customer:
Yeah. I was just converting my cameras and my study to use 4:3 aspect ratios. I want to be cool.
Developer:
See? 4:3 is cool.