Cycles: Adding field-of-view options to the equirectangular panorama camera
This patch adds the option to set minimum/maximum latitude/longitude values for the equirectangular panorama camera in Cycles, as discussed in T34400. The separate functions in kernel_projection.h are needed because the regular ones are also used as helper functions for environment map sampling. Reviewers: #cycles, sergey Reviewed By: #cycles, sergey Subscribers: dingto, sergey, brecht Differential Revision: https://developer.blender.org/D960
This commit is contained in:

committed by
Sergey Sharybin

parent
193871ae7d
commit
4118c1b4e6
@@ -582,6 +582,34 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
|
|||||||
min=0.01, soft_max=15.0, max=100.0,
|
min=0.01, soft_max=15.0, max=100.0,
|
||||||
default=10.5,
|
default=10.5,
|
||||||
)
|
)
|
||||||
|
cls.latitude_min = FloatProperty(
|
||||||
|
name="Min latitude",
|
||||||
|
description="Minimum latitude (vertical angle) for the equirectangular lens",
|
||||||
|
min=-0.5 * math.pi, max=0.5 * math.pi,
|
||||||
|
subtype='ANGLE',
|
||||||
|
default=-0.5 * math.pi,
|
||||||
|
)
|
||||||
|
cls.latitude_max = FloatProperty(
|
||||||
|
name="Max latitude",
|
||||||
|
description="Maximum latitude (vertical angle) for the equirectangular lens",
|
||||||
|
min=-0.5 * math.pi, max=0.5 * math.pi,
|
||||||
|
subtype='ANGLE',
|
||||||
|
default=0.5 * math.pi,
|
||||||
|
)
|
||||||
|
cls.longitude_min = FloatProperty(
|
||||||
|
name="Min longitude",
|
||||||
|
description="Minimum longitude (horizontal angle) for the equirectangular lens",
|
||||||
|
min=-math.pi, max=math.pi,
|
||||||
|
subtype='ANGLE',
|
||||||
|
default=-math.pi,
|
||||||
|
)
|
||||||
|
cls.longitude_max = FloatProperty(
|
||||||
|
name="Max longitude",
|
||||||
|
description="Maximum longitude (horizontal angle) for the equirectangular lens",
|
||||||
|
min=-math.pi, max=math.pi,
|
||||||
|
subtype='ANGLE',
|
||||||
|
default=math.pi,
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
|
@@ -53,6 +53,10 @@ struct BlenderCamera {
|
|||||||
PanoramaType panorama_type;
|
PanoramaType panorama_type;
|
||||||
float fisheye_fov;
|
float fisheye_fov;
|
||||||
float fisheye_lens;
|
float fisheye_lens;
|
||||||
|
float latitude_min;
|
||||||
|
float latitude_max;
|
||||||
|
float longitude_min;
|
||||||
|
float longitude_max;
|
||||||
|
|
||||||
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
|
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
|
||||||
float sensor_width;
|
float sensor_width;
|
||||||
@@ -147,6 +151,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
|
|||||||
|
|
||||||
bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
|
bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
|
||||||
bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
|
bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
|
||||||
|
bcam->latitude_min = RNA_float_get(&ccamera, "latitude_min");
|
||||||
|
bcam->latitude_max = RNA_float_get(&ccamera, "latitude_max");
|
||||||
|
bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
|
||||||
|
bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
|
||||||
|
|
||||||
bcam->ortho_scale = b_camera.ortho_scale();
|
bcam->ortho_scale = b_camera.ortho_scale();
|
||||||
|
|
||||||
@@ -332,6 +340,11 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
|
|||||||
cam->panorama_type = bcam->panorama_type;
|
cam->panorama_type = bcam->panorama_type;
|
||||||
cam->fisheye_fov = bcam->fisheye_fov;
|
cam->fisheye_fov = bcam->fisheye_fov;
|
||||||
cam->fisheye_lens = bcam->fisheye_lens;
|
cam->fisheye_lens = bcam->fisheye_lens;
|
||||||
|
cam->latitude_min = bcam->latitude_min;
|
||||||
|
cam->latitude_max = bcam->latitude_max;
|
||||||
|
|
||||||
|
cam->longitude_min = bcam->longitude_min;
|
||||||
|
cam->longitude_max = bcam->longitude_max;
|
||||||
|
|
||||||
/* anamorphic lens bokeh */
|
/* anamorphic lens bokeh */
|
||||||
cam->aperture_ratio = bcam->aperture_ratio;
|
cam->aperture_ratio = bcam->aperture_ratio;
|
||||||
|
@@ -55,18 +55,18 @@ ccl_device float3 spherical_to_direction(float theta, float phi)
|
|||||||
|
|
||||||
/* Equirectangular coordinates <-> Cartesian direction */
|
/* Equirectangular coordinates <-> Cartesian direction */
|
||||||
|
|
||||||
ccl_device float2 direction_to_equirectangular(float3 dir)
|
ccl_device float2 direction_to_equirectangular_range(float3 dir, float4 range)
|
||||||
{
|
{
|
||||||
float u = -atan2f(dir.y, dir.x)/(M_2PI_F) + 0.5f;
|
float u = (atan2f(dir.y, dir.x) - range.y) / range.x;
|
||||||
float v = atan2f(dir.z, hypotf(dir.x, dir.y))/M_PI_F + 0.5f;
|
float v = (acosf(dir.z / len(dir)) - range.w) / range.z;
|
||||||
|
|
||||||
return make_float2(u, v);
|
return make_float2(u, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device float3 equirectangular_to_direction(float u, float v)
|
ccl_device float3 equirectangular_range_to_direction(float u, float v, float4 range)
|
||||||
{
|
{
|
||||||
float phi = M_PI_F*(1.0f - 2.0f*u);
|
float phi = range.x*u + range.y;
|
||||||
float theta = M_PI_F*(1.0f - v);
|
float theta = range.z*v + range.w;
|
||||||
|
|
||||||
return make_float3(
|
return make_float3(
|
||||||
sinf(theta)*cosf(phi),
|
sinf(theta)*cosf(phi),
|
||||||
@@ -74,6 +74,16 @@ ccl_device float3 equirectangular_to_direction(float u, float v)
|
|||||||
cosf(theta));
|
cosf(theta));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ccl_device float2 direction_to_equirectangular(float3 dir)
|
||||||
|
{
|
||||||
|
return direction_to_equirectangular_range(dir, make_float4(-M_2_PI_F, M_PI_F, -M_PI_F, M_PI_F));
|
||||||
|
}
|
||||||
|
|
||||||
|
ccl_device float3 equirectangular_to_direction(float u, float v)
|
||||||
|
{
|
||||||
|
return equirectangular_range_to_direction(u, v, make_float4(-M_2_PI_F, M_PI_F, -M_PI_F, M_PI_F));
|
||||||
|
}
|
||||||
|
|
||||||
/* Fisheye <-> Cartesian direction */
|
/* Fisheye <-> Cartesian direction */
|
||||||
|
|
||||||
ccl_device float2 direction_to_fisheye(float3 dir, float fov)
|
ccl_device float2 direction_to_fisheye(float3 dir, float fov)
|
||||||
@@ -180,7 +190,7 @@ ccl_device float3 panorama_to_direction(KernelGlobals *kg, float u, float v)
|
|||||||
{
|
{
|
||||||
switch(kernel_data.cam.panorama_type) {
|
switch(kernel_data.cam.panorama_type) {
|
||||||
case PANORAMA_EQUIRECTANGULAR:
|
case PANORAMA_EQUIRECTANGULAR:
|
||||||
return equirectangular_to_direction(u, v);
|
return equirectangular_range_to_direction(u, v, kernel_data.cam.equirectangular_range);
|
||||||
case PANORAMA_FISHEYE_EQUIDISTANT:
|
case PANORAMA_FISHEYE_EQUIDISTANT:
|
||||||
return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov);
|
return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov);
|
||||||
case PANORAMA_FISHEYE_EQUISOLID:
|
case PANORAMA_FISHEYE_EQUISOLID:
|
||||||
@@ -194,7 +204,7 @@ ccl_device float2 direction_to_panorama(KernelGlobals *kg, float3 dir)
|
|||||||
{
|
{
|
||||||
switch(kernel_data.cam.panorama_type) {
|
switch(kernel_data.cam.panorama_type) {
|
||||||
case PANORAMA_EQUIRECTANGULAR:
|
case PANORAMA_EQUIRECTANGULAR:
|
||||||
return direction_to_equirectangular(dir);
|
return direction_to_equirectangular_range(dir, kernel_data.cam.equirectangular_range);
|
||||||
case PANORAMA_FISHEYE_EQUIDISTANT:
|
case PANORAMA_FISHEYE_EQUIDISTANT:
|
||||||
return direction_to_fisheye(dir, kernel_data.cam.fisheye_fov);
|
return direction_to_fisheye(dir, kernel_data.cam.fisheye_fov);
|
||||||
case PANORAMA_FISHEYE_EQUISOLID:
|
case PANORAMA_FISHEYE_EQUISOLID:
|
||||||
|
@@ -767,6 +767,7 @@ typedef struct KernelCamera {
|
|||||||
int panorama_type;
|
int panorama_type;
|
||||||
float fisheye_fov;
|
float fisheye_fov;
|
||||||
float fisheye_lens;
|
float fisheye_lens;
|
||||||
|
float4 equirectangular_range;
|
||||||
|
|
||||||
/* matrices */
|
/* matrices */
|
||||||
Transform cameratoworld;
|
Transform cameratoworld;
|
||||||
|
@@ -47,6 +47,10 @@ Camera::Camera()
|
|||||||
panorama_type = PANORAMA_EQUIRECTANGULAR;
|
panorama_type = PANORAMA_EQUIRECTANGULAR;
|
||||||
fisheye_fov = M_PI_F;
|
fisheye_fov = M_PI_F;
|
||||||
fisheye_lens = 10.5f;
|
fisheye_lens = 10.5f;
|
||||||
|
latitude_min = -M_PI_2_F;
|
||||||
|
latitude_max = M_PI_2_F;
|
||||||
|
longitude_min = -M_PI_F;
|
||||||
|
longitude_max = M_PI_F;
|
||||||
fov = M_PI_4_F;
|
fov = M_PI_4_F;
|
||||||
|
|
||||||
sensorwidth = 0.036f;
|
sensorwidth = 0.036f;
|
||||||
@@ -253,6 +257,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
|||||||
kcam->panorama_type = panorama_type;
|
kcam->panorama_type = panorama_type;
|
||||||
kcam->fisheye_fov = fisheye_fov;
|
kcam->fisheye_fov = fisheye_fov;
|
||||||
kcam->fisheye_lens = fisheye_lens;
|
kcam->fisheye_lens = fisheye_lens;
|
||||||
|
kcam->equirectangular_range = make_float4(longitude_min - longitude_max, -longitude_min,
|
||||||
|
latitude_min - latitude_max, -latitude_min + M_PI_2_F);
|
||||||
|
|
||||||
/* sensor size */
|
/* sensor size */
|
||||||
kcam->sensorwidth = sensorwidth;
|
kcam->sensorwidth = sensorwidth;
|
||||||
@@ -316,7 +322,11 @@ bool Camera::modified(const Camera& cam)
|
|||||||
(aperture_ratio == cam.aperture_ratio) &&
|
(aperture_ratio == cam.aperture_ratio) &&
|
||||||
(panorama_type == cam.panorama_type) &&
|
(panorama_type == cam.panorama_type) &&
|
||||||
(fisheye_fov == cam.fisheye_fov) &&
|
(fisheye_fov == cam.fisheye_fov) &&
|
||||||
(fisheye_lens == cam.fisheye_lens));
|
(fisheye_lens == cam.fisheye_lens) &&
|
||||||
|
(latitude_min == cam.latitude_min) &&
|
||||||
|
(latitude_max == cam.latitude_max) &&
|
||||||
|
(longitude_min == cam.longitude_min) &&
|
||||||
|
(longitude_max == cam.longitude_max));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Camera::motion_modified(const Camera& cam)
|
bool Camera::motion_modified(const Camera& cam)
|
||||||
|
@@ -53,6 +53,10 @@ public:
|
|||||||
PanoramaType panorama_type;
|
PanoramaType panorama_type;
|
||||||
float fisheye_fov;
|
float fisheye_fov;
|
||||||
float fisheye_lens;
|
float fisheye_lens;
|
||||||
|
float latitude_min;
|
||||||
|
float latitude_max;
|
||||||
|
float longitude_min;
|
||||||
|
float longitude_max;
|
||||||
|
|
||||||
/* anamorphic lens bokeh */
|
/* anamorphic lens bokeh */
|
||||||
float aperture_ratio;
|
float aperture_ratio;
|
||||||
|
@@ -98,6 +98,14 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(ccam, "fisheye_lens", text="Lens")
|
row.prop(ccam, "fisheye_lens", text="Lens")
|
||||||
row.prop(ccam, "fisheye_fov")
|
row.prop(ccam, "fisheye_fov")
|
||||||
|
elif ccam.panorama_type == 'EQUIRECTANGULAR':
|
||||||
|
row = layout.row()
|
||||||
|
sub = row.column(align=True)
|
||||||
|
sub.prop(ccam, "latitude_min");
|
||||||
|
sub.prop(ccam, "latitude_max");
|
||||||
|
sub = row.column(align=True)
|
||||||
|
sub.prop(ccam, "longitude_min");
|
||||||
|
sub.prop(ccam, "longitude_max");
|
||||||
elif engine == 'BLENDER_RENDER':
|
elif engine == 'BLENDER_RENDER':
|
||||||
row = col.row()
|
row = col.row()
|
||||||
if cam.lens_unit == 'MILLIMETERS':
|
if cam.lens_unit == 'MILLIMETERS':
|
||||||
|
Reference in New Issue
Block a user