Hi,
I’m trying to update an addon for 2.8. At some point, this addon compute the 3Dview FOV from focal lens. The original code works great, it uses the same constants and equations than used in Blender’s source code. The FOV equation uses a sensor width of 32mm (hardcoded value), then the angle value is corrected because the 3dview have an hardcoded zoom factor of 2.
With the FOV value it’s easy to compute the real horizontal distance covered by the 3dView. The script bellow illustrate the FOV calculation for a sensor width of 32mm, a focal lens of 50mm and a camera distance fixed to 10 meters.
import math
distance = 10
aperture = 32
focal = 50
zoom = 2
fov = 2 * math.atan(aperture / (focal*2) ) #standard fov equation
fov = math.atan(math.tan(fov/2) * zoom) * 2 #zoom correction (see source code)
realw = math.tan(fov/2) * distance * 2 #simple trigo
print(math.degrees(fov), realw) #(65.2, 12.8)
For verifying these values, I reproduce the setup in the 3d view with another script and then I measure the horizontal distance with the ruler : in Blender 2.7 it gives me the correct distance (12.8m), but in 2.8 I get about 14.4m.
import bpy
for area in bpy.context.screen.areas:
for space in area.spaces:
if space.type == 'VIEW_3D':
s = space
s.lens = 50
r = s.region_3d
r.view_location = (0, 0, 0)
r.view_rotation = (1, 0, 0, 0)
r.view_distance = 10
checking the source code give me no clue about the origin of this difference. The relevant parts of the source code are
File DNA_camera_types.h
#define DEFAULT_SENSOR_WIDTH 32.0f
#define DEFAULT_SENSOR_HEIGHT 18.0f
File BKE_camera.h
#define CAMERA_PARAM_ZOOM_INIT_PERSP 2.0f
File view3d_utils.c
lens = v3d->lens;
sensor_size = DEFAULT_SENSOR_WIDTH;
zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
angle = focallength_to_fov(lens, sensor_size);
/* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */
angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
File math_rotation.c
* lens/angle conversion (radians) */
float focallength_to_fov(float focal_length, float sensor)
{
return 2.0f * atanf((sensor / 2.0f) / focal_length);
}
Any help will be appreciate !