SUBSIM Radio Room Forums



SUBSIM: The Web's #1 resource for all submarine & naval simulations since 1997

Go Back   SUBSIM Radio Room Forums > Silent Hunter 3 - 4 - 5 > SH5 Mods Workshop
Forget password? Reset here

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
Old 06-15-12, 02:53 PM   #1
radcapricorn
Helmsman
 
Join Date: Jun 2011
Posts: 105
Downloads: 181
Uploads: 0
Default [TEC] Periscope, AngularAngle, FOV

I don't know if this was posted before, at least I saw many threads for SH3/SH5 concerning calibration of scopes for different resolutions, but in all these threads only trial and error approach was proposed (i.e. draw a line and see if it is at proper bearing, etc.). In light of latest FOV thread I made a slight detour from my touchpads exploits into camera area. Here's what I came up with:

- AngularAngle is camera's horizontal FOV at 1x zoom. This means that in order to properly calibrate periscope, you need to determine what FOV your scope camera should have at 1x zoom. Disambiguation: this does not mean your scope's low power zoom should be set to 1. It just means that in order to get correct FOV for the scope at given zoom, you need to set AngularAngle for 1x zoom.
- Stock graticules (SH3/SH5) tell the truth (in degrees). They are calculated for actual camera FOV, and are resized accordingly when zoom changes.
- You can't make scopes with FOV that is non-multiple at different zoom levels (i.e French scopes), since you can only specify one FOV
- formulas to calculate AngularAngle for given periscope ocular:

For SH3 (with no resolution patch):

AngularAngle = 2 * atan( ZoomAtThisFOV * w * N * tan( PeriscopeFOV / 2 ) )

For SH4/SH5:

AngularAngle = 2 * atan( ZoomAtThisFOV * N * tan( PeriscopeFOV / 2 ) )

where:

- PeriscopeFOV is actual periscope field of view (i.e. 38 for German scopes, 32 for US scopes)
- ZoomAtThisFOV: zoom at which PeriscopeFOV is achieved (i.e. 1.5 for German/US scopes)
- w (in SH3 formula) is viewport width. I.e. CameraParams.Viewport.Right-CameraParams.Viewport.Left
- N is Resolution / OcularPixels (see below)

It is convenient to set ZoomAtThisFOV to scope's low-power zoom (i.e. 1.5) and PeriscopeFOV to scope's low-power FOV (i.e. 38 for German scopes, 32 for US scopes in SH4).

About N: you need to determine how many pixels your ocular's diameter would take at given resolution. This may vary depending on how you set up your periscope screen in .ini files, thus it is beyond the scope of this post. Then you divide your camera's horizontal resolution by this value. Why I say "camera's" here is because for SH3 it may differ from actual screen resolution.

Below is some math and illustrations on how I came up with these formulas.

Here we go. Let's start with finding out full FOV for camera when we only have our scope FOV.



Here A is our monitor, B is our ocular, C is the distance between camera and view plane, FOVscope is periscope FOV, FOVcamera is camera FOV.

What we know: A (horizontal resolution), B (ocular size), FOVscope (obviously). Let's do some math:

1) tan(FOVscope/2) = B/(2*C)
2) tan(FOVcamera/2) = A/(2*C)

From (1) C = B / (2 * tan(FOVscope/2)). Putting that into (2) gives us

tan(FOVcamera/2) = (A/B) * tan(FOVscope/2)

From here, we could calculate FOVcamera, but we don't need to just yet. For now, let's just rename A/B as N:

tan(FOVcamera/2) = N * tan(FOVscope/2)

So far so good, but all this is for the scope low-power zoom, which is not necessary 1. And we need AngularAngle at 1x zoom. Let's take a look at another image:



Looks exactly like the previous one, except some names are different.
The game implements zoom by reducing FOV so that viewed objects appear larger. So here FOVcamera is AngularAngle (i.e. field of view at 1x zoom), FOVzoom is camera FOV after zoom is applied, B is some object that totally fills the view when zoom is applied. Now, when zoom is applied, FOV is reduced so that object appears larger. If put in other words, total viewed "width" is reduced by our zoom factor. So here, A/B = zoom.

Using the same math as above, we get:

tan(FOVcamera/2) = A/B * tan(FOVzoom/2)

and

FOVcamera = 2 * atan( A/B * tan(FOVzoom/2) )

Now, this FOVcamera is AngularAngle and A/B = zoom:

AngularAngle = 2 * atan( zoom * tan(FOVzoom/2) )

What's the FOVzoom then? It's the FOVcamera from previous step, i.e. full field of view for our periscope camera at low-power zoom level:

tan(FOVzoom/2) = N * tan(FOVscope/2)

Let's put that in:

AngularAngle = 2 * atan( zoom * N * tan(FOVscope/2) )

This is it. I hope that's clear enough

Also I think clever minds should be able to translate it from resolution-tied calculations to aspect-ratio tied ones (basically the same thing, only ocular diameter should be properly scaled). I just didn't bother

Example: suppose you have a 760x760 ocular image for 38-degree scope with minimal zoom of 1.5. Suppose you want the ocular to take as much space as possible, but still appear in full (i.e. full circle on screen). Let's calculate AngularAngle for 4:3 resolution, taking 1024x768 as reference. At this resolution, your ocular would be 768x768 pixels.

Resolution = 1024
ZoomAtThisFOV = 1.5
PeriscopeFOV = 38
OcularPixels = 768

AngularAngle = 2 * atan( 1.5 * (1024 / 768) * tan( 38 / 2 ) ) = 69.106888959867263457785057221729 ~= 69.10689

This value should hold for any 4:3 resolution.

Now, let's make our resolution 1680x1050 (16:10 or 8:5) and replace the ocular image with another one: a 1920x1920 image, but actual ocular is only 1900x1900 (some "black" space is present).
At 1680x1050, the whole image would be rescaled to 1050x1050. This means that actual ocular size would be ((1900/1920)*1050) = 1039.0625 pixels.

Resolution = 1680
ZoomAtThisFOV = 1.5
PeriscopeFOV = 38
OcularPixels = 1039.0625

AngularAngle = 2 * atan( 1.5 * (1680 / 1039.0625) * tan( 38 / 2 ) ) = 79.729506598014914131775270825077 ~= 79.72951

Again, for such image, this AngularAngle should be the same for any 16:10 (8:5) resolution.

That's it. You get as much precision as fits into Single (or at least into S3D edit field), and no more time loss on manual search for appropriate FOV.

EDIT: slight off-topic. It turns out that SH5 does not use viewport parameters for cameras (at least I haven't noticed any effect: it still uses entire screen to render), neither does SH4. But SH3 does. This brings additional coefficient to this formula for SH3:

AngularAngle = 2 * atan( zoom * w * N * tan ( FOVscope/2 ) )

Here w is viewport width calculated as Viewport.Right - Viewport.Left.
Reason it's here is that SH3 actually uses viewport parameters in CameraParams. Viewport.Left and Viewport.Right are "normalized device coordinates" in the range [0,1] that show where on the screen camera viewport starts/ends. So, actual camera render area may be less than entire screen. If you remember that N is Resolution / OcularPixels, where Resolution is horizontal size of screen, you can now see why we need to multiply by w: the actual camera's horizontal resolution may be less than Resolution.

This is for SH3 without any widescreen patches (i.e. A is always 1024). This may be useful for people still interested in modding SH3.

Don't forget to properly convert angles if your calculator expects radians instead of degrees

PS. Of course, this is also applicable to binoculars/UZO/TBT AngularAngles. Just use the correct OcularPixels, especially if your ocular is not round (as is popular for binoculars): take full ocular width in pixels as it would appear at given resolution.

Last edited by radcapricorn; 06-28-12 at 10:52 AM. Reason: Added correct SH3 formula
radcapricorn is offline   Reply With Quote
 


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 08:03 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Copyright © 1995- 2025 Subsim®
"Subsim" is a registered trademark, all rights reserved.