From acd6dd96b7d5eeac533eb7eb1504eed5262fe70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Tue, 22 Aug 2023 15:49:34 +0200 Subject: [PATCH] Camera: Move panoramic projection settings to DNA This is in prevision of EEVEE panoramic projection support. EEVEE-Next is planned to add support for these parameters. Not having these parameters in Blender DNA will make Cycles and EEVEE not share the same parameters and will be confusing for the user. We handle forward compatibility by still writing the parameters as ID properties as previous cycles versions expect. Since this change will break the API compatibility it is crucial to make it for the 4.0 release. Related Task #109639 Pull Request: https://projects.blender.org/blender/blender/pulls/111310 --- intern/cycles/blender/addon/properties.py | 102 ----------------- intern/cycles/blender/camera.cpp | 47 +++++--- .../startup/bl_ui/properties_data_camera.py | 37 +++---- .../blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/camera.cc | 92 ++++++++++++++++ .../blenloader/intern/versioning_400.cc | 79 ++++++++++--- source/blender/makesdna/DNA_camera_defaults.h | 14 +++ source/blender/makesdna/DNA_camera_types.h | 28 ++++- source/blender/makesrna/intern/rna_camera.cc | 104 ++++++++++++++++++ 9 files changed, 352 insertions(+), 153 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index f6443589631..7eb9eb437c7 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -65,17 +65,6 @@ enum_filter_types = ( ('BLACKMAN_HARRIS', "Blackman-Harris", "Blackman-Harris filter"), ) -enum_panorama_types = ( - ('EQUIRECTANGULAR', "Equirectangular", "Spherical camera for environment maps, also known as Lat Long panorama", 0), - ('EQUIANGULAR_CUBEMAP_FACE', "Equiangular Cubemap Face", "Single face of an equiangular cubemap", 5), - ('MIRRORBALL', "Mirror Ball", "Mirror ball mapping for environment maps", 3), - ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions", 1), - ('FISHEYE_EQUISOLID', "Fisheye Equisolid", - "Similar to most fisheye modern lens, takes sensor dimensions into consideration", 2), - ('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial", - "Defines the lens projection as polynomial to allow real world camera lenses to be mimicked", 4), -) - enum_curve_shape = ( ('RIBBONS', "Rounded Ribbons", "Render curves as flat ribbons with rounded normals, for fast rendering"), ('THICK', "3D Curves", "Render curves as circular 3D geometry, for accurate results when viewing closely"), @@ -1014,95 +1003,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): del bpy.types.Scene.cycles -class CyclesCameraSettings(bpy.types.PropertyGroup): - - panorama_type: EnumProperty( - name="Panorama Type", - description="Distortion to use for the calculation", - items=enum_panorama_types, - default='FISHEYE_EQUISOLID', - ) - fisheye_fov: FloatProperty( - name="Field of View", - description="Field of view for the fisheye lens", - min=0.1745, soft_max=2.0 * pi, max=10.0 * pi, - subtype='ANGLE', - default=pi, - ) - fisheye_lens: FloatProperty( - name="Fisheye Lens", - description="Lens focal length (mm)", - min=0.01, soft_max=15.0, max=100.0, - default=10.5, - ) - latitude_min: FloatProperty( - name="Min Latitude", - description="Minimum latitude (vertical angle) for the equirectangular lens", - min=-0.5 * pi, max=0.5 * pi, - subtype='ANGLE', - default=-0.5 * pi, - ) - latitude_max: FloatProperty( - name="Max Latitude", - description="Maximum latitude (vertical angle) for the equirectangular lens", - min=-0.5 * pi, max=0.5 * pi, - subtype='ANGLE', - default=0.5 * pi, - ) - longitude_min: FloatProperty( - name="Min Longitude", - description="Minimum longitude (horizontal angle) for the equirectangular lens", - min=-pi, max=pi, - subtype='ANGLE', - default=-pi, - ) - longitude_max: FloatProperty( - name="Max Longitude", - description="Maximum longitude (horizontal angle) for the equirectangular lens", - min=-pi, max=pi, - subtype='ANGLE', - default=pi, - ) - - fisheye_polynomial_k0: FloatProperty( - name="Fisheye Polynomial K0", - description="Coefficient K0 of the lens polynomial", - default=camera.default_fisheye_polynomial[0], precision=6, step=0.1, subtype='ANGLE', - ) - fisheye_polynomial_k1: FloatProperty( - name="Fisheye Polynomial K1", - description="Coefficient K1 of the lens polynomial", - default=camera.default_fisheye_polynomial[1], precision=6, step=0.1, subtype='ANGLE', - ) - fisheye_polynomial_k2: FloatProperty( - name="Fisheye Polynomial K2", - description="Coefficient K2 of the lens polynomial", - default=camera.default_fisheye_polynomial[2], precision=6, step=0.1, subtype='ANGLE', - ) - fisheye_polynomial_k3: FloatProperty( - name="Fisheye Polynomial K3", - description="Coefficient K3 of the lens polynomial", - default=camera.default_fisheye_polynomial[3], precision=6, step=0.1, subtype='ANGLE', - ) - fisheye_polynomial_k4: FloatProperty( - name="Fisheye Polynomial K4", - description="Coefficient K4 of the lens polynomial", - default=camera.default_fisheye_polynomial[4], precision=6, step=0.1, subtype='ANGLE', - ) - - @classmethod - def register(cls): - bpy.types.Camera.cycles = PointerProperty( - name="Cycles Camera Settings", - description="Cycles camera settings", - type=cls, - ) - - @classmethod - def unregister(cls): - del bpy.types.Camera.cycles - - class CyclesMaterialSettings(bpy.types.PropertyGroup): emission_sampling: EnumProperty( @@ -1837,7 +1737,6 @@ class CyclesView3DShadingSettings(bpy.types.PropertyGroup): def register(): bpy.utils.register_class(CyclesRenderSettings) - bpy.utils.register_class(CyclesCameraSettings) bpy.utils.register_class(CyclesMaterialSettings) bpy.utils.register_class(CyclesLightSettings) bpy.utils.register_class(CyclesWorldSettings) @@ -1858,7 +1757,6 @@ def register(): def unregister(): bpy.utils.unregister_class(CyclesRenderSettings) - bpy.utils.unregister_class(CyclesCameraSettings) bpy.utils.unregister_class(CyclesMaterialSettings) bpy.utils.unregister_class(CyclesLightSettings) bpy.utils.unregister_class(CyclesWorldSettings) diff --git a/intern/cycles/blender/camera.cpp b/intern/cycles/blender/camera.cpp index 053585718a7..5f0e7b39860 100644 --- a/intern/cycles/blender/camera.cpp +++ b/intern/cycles/blender/camera.cpp @@ -164,6 +164,26 @@ static float blender_camera_focal_distance(BL::RenderEngine &b_engine, return fabsf(dot(view_dir, dof_dir)); } +static PanoramaType blender_panorama_type_to_cycles(const BL::Camera::panorama_type_enum type) +{ + switch (type) { + case BL::Camera::panorama_type_EQUIRECTANGULAR: + return PANORAMA_EQUIRECTANGULAR; + case BL::Camera::panorama_type_EQUIANGULAR_CUBEMAP_FACE: + return PANORAMA_EQUIANGULAR_CUBEMAP_FACE; + case BL::Camera::panorama_type_MIRRORBALL: + return PANORAMA_MIRRORBALL; + case BL::Camera::panorama_type_FISHEYE_EQUIDISTANT: + return PANORAMA_FISHEYE_EQUIDISTANT; + case BL::Camera::panorama_type_FISHEYE_EQUISOLID: + return PANORAMA_FISHEYE_EQUISOLID; + case BL::Camera::panorama_type_FISHEYE_LENS_POLYNOMIAL: + return PANORAMA_FISHEYE_LENS_POLYNOMIAL; + } + /* Could happen if loading a newer file that has an unsupported type. */ + return PANORAMA_FISHEYE_EQUISOLID; +} + static void blender_camera_from_object(BlenderCamera *bcam, BL::RenderEngine &b_engine, BL::Object &b_ob, @@ -173,7 +193,6 @@ static void blender_camera_from_object(BlenderCamera *bcam, if (b_ob_data.is_a(&RNA_Camera)) { BL::Camera b_camera(b_ob_data); - PointerRNA ccamera = RNA_pointer_get(&b_camera.ptr, "cycles"); bcam->nearclip = b_camera.clip_start(); bcam->farclip = b_camera.clip_end(); @@ -194,21 +213,19 @@ static void blender_camera_from_object(BlenderCamera *bcam, break; } - bcam->panorama_type = (PanoramaType)get_enum( - ccamera, "panorama_type", PANORAMA_NUM_TYPES, PANORAMA_EQUIRECTANGULAR); + bcam->panorama_type = blender_panorama_type_to_cycles(b_camera.panorama_type()); + bcam->fisheye_fov = b_camera.fisheye_fov(); + bcam->fisheye_lens = b_camera.fisheye_lens(); + bcam->latitude_min = b_camera.latitude_min(); + bcam->latitude_max = b_camera.latitude_max(); + bcam->longitude_min = b_camera.longitude_min(); + bcam->longitude_max = b_camera.longitude_max(); - bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov"); - 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->fisheye_polynomial_k0 = RNA_float_get(&ccamera, "fisheye_polynomial_k0"); - bcam->fisheye_polynomial_k1 = RNA_float_get(&ccamera, "fisheye_polynomial_k1"); - bcam->fisheye_polynomial_k2 = RNA_float_get(&ccamera, "fisheye_polynomial_k2"); - bcam->fisheye_polynomial_k3 = RNA_float_get(&ccamera, "fisheye_polynomial_k3"); - bcam->fisheye_polynomial_k4 = RNA_float_get(&ccamera, "fisheye_polynomial_k4"); + bcam->fisheye_polynomial_k0 = b_camera.fisheye_polynomial_k0(); + bcam->fisheye_polynomial_k1 = b_camera.fisheye_polynomial_k1(); + bcam->fisheye_polynomial_k2 = b_camera.fisheye_polynomial_k2(); + bcam->fisheye_polynomial_k3 = b_camera.fisheye_polynomial_k3(); + bcam->fisheye_polynomial_k4 = b_camera.fisheye_polynomial_k4(); bcam->interocular_distance = b_camera.stereo().interocular_distance(); if (b_camera.stereo().convergence_mode() == BL::CameraStereoData::convergence_mode_PARALLEL) { diff --git a/scripts/startup/bl_ui/properties_data_camera.py b/scripts/startup/bl_ui/properties_data_camera.py index 3a224a07251..d6f3e73e373 100644 --- a/scripts/startup/bl_ui/properties_data_camera.py +++ b/scripts/startup/bl_ui/properties_data_camera.py @@ -103,27 +103,26 @@ class DATA_PT_lens(CameraButtonsPanel, Panel): elif cam.type == 'PANO': engine = context.engine if engine == 'CYCLES': - ccam = cam.cycles - col.prop(ccam, "panorama_type") - if ccam.panorama_type == 'FISHEYE_EQUIDISTANT': - col.prop(ccam, "fisheye_fov") - elif ccam.panorama_type == 'FISHEYE_EQUISOLID': - col.prop(ccam, "fisheye_lens", text="Lens") - col.prop(ccam, "fisheye_fov") - elif ccam.panorama_type == 'EQUIRECTANGULAR': + col.prop(cam, "panorama_type") + if cam.panorama_type == 'FISHEYE_EQUIDISTANT': + col.prop(cam, "fisheye_fov") + elif cam.panorama_type == 'FISHEYE_EQUISOLID': + col.prop(cam, "fisheye_lens", text="Lens") + col.prop(cam, "fisheye_fov") + elif cam.panorama_type == 'EQUIRECTANGULAR': sub = col.column(align=True) - sub.prop(ccam, "latitude_min", text="Latitude Min") - sub.prop(ccam, "latitude_max", text="Max") + sub.prop(cam, "latitude_min", text="Latitude Min") + sub.prop(cam, "latitude_max", text="Max") sub = col.column(align=True) - sub.prop(ccam, "longitude_min", text="Longitude Min") - sub.prop(ccam, "longitude_max", text="Max") - elif ccam.panorama_type == 'FISHEYE_LENS_POLYNOMIAL': - col.prop(ccam, "fisheye_fov") - col.prop(ccam, "fisheye_polynomial_k0", text="K0") - col.prop(ccam, "fisheye_polynomial_k1", text="K1") - col.prop(ccam, "fisheye_polynomial_k2", text="K2") - col.prop(ccam, "fisheye_polynomial_k3", text="K3") - col.prop(ccam, "fisheye_polynomial_k4", text="K4") + sub.prop(cam, "longitude_min", text="Longitude Min") + sub.prop(cam, "longitude_max", text="Max") + elif cam.panorama_type == 'FISHEYE_LENS_POLYNOMIAL': + col.prop(cam, "fisheye_fov") + col.prop(cam, "fisheye_polynomial_k0", text="K0") + col.prop(cam, "fisheye_polynomial_k1", text="K1") + col.prop(cam, "fisheye_polynomial_k2", text="K2") + col.prop(cam, "fisheye_polynomial_k3", text="K3") + col.prop(cam, "fisheye_polynomial_k4", text="K4") elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}: if cam.lens_unit == 'MILLIMETERS': diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index e0ee73b0f06..dc90f595de7 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 16 +#define BLENDER_FILE_SUBVERSION 17 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/intern/camera.cc b/source/blender/blenkernel/intern/camera.cc index 9a133758554..a1af2b7de3d 100644 --- a/source/blender/blenkernel/intern/camera.cc +++ b/source/blender/blenkernel/intern/camera.cc @@ -31,6 +31,7 @@ #include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_camera.h" +#include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -103,10 +104,97 @@ static void camera_foreach_id(ID *id, LibraryForeachIDData *data) } } +struct CameraCyclesCompatibilityData { + IDProperty *idprop_prev = nullptr; + IDProperty *idprop_temp = nullptr; +}; + +static CameraCyclesCompatibilityData camera_write_cycles_compatibility_data_create(ID *id) +{ + auto cycles_data_ensure = [](IDProperty *group) { + IDProperty *prop = IDP_GetPropertyTypeFromGroup(group, "cycles", IDP_GROUP); + if (prop) { + return prop; + } + IDPropertyTemplate val = {0}; + prop = IDP_New(IDP_GROUP, &val, "cycles"); + IDP_AddToGroup(group, prop); + return prop; + }; + + auto cycles_property_int_set = [](IDProperty *idprop, const char *name, int value) { + IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT); + if (prop) { + IDP_Int(prop) = value; + } + else { + IDPropertyTemplate val = {0}; + val.i = value; + IDP_AddToGroup(idprop, IDP_New(IDP_INT, &val, name)); + } + }; + + auto cycles_property_float_set = [](IDProperty *idprop, const char *name, float value) { + IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_FLOAT); + if (prop) { + IDP_Float(prop) = value; + } + else { + IDPropertyTemplate val = {0}; + val.f = value; + IDP_AddToGroup(idprop, IDP_New(IDP_FLOAT, &val, name)); + } + }; + + /* For forward compatibility, still write panoramic properties as ID properties for + * previous blender versions. */ + IDProperty *idprop_prev = IDP_GetProperties(id, false); + /* Make a copy to avoid modifying the original. */ + IDProperty *idprop_temp = idprop_prev ? IDP_CopyProperty(idprop_prev) : + IDP_GetProperties(id, true); + + Camera *cam = (Camera *)id; + IDProperty *cycles_cam = cycles_data_ensure(idprop_temp); + cycles_property_int_set(cycles_cam, "panorama_type", cam->panorama_type); + cycles_property_float_set(cycles_cam, "fisheye_fov", cam->fisheye_fov); + cycles_property_float_set(cycles_cam, "fisheye_lens", cam->fisheye_lens); + cycles_property_float_set(cycles_cam, "latitude_min", cam->latitude_min); + cycles_property_float_set(cycles_cam, "latitude_max", cam->latitude_max); + cycles_property_float_set(cycles_cam, "longitude_min", cam->longitude_min); + cycles_property_float_set(cycles_cam, "longitude_max", cam->longitude_max); + cycles_property_float_set(cycles_cam, "fisheye_polynomial_k0", cam->fisheye_polynomial_k0); + cycles_property_float_set(cycles_cam, "fisheye_polynomial_k1", cam->fisheye_polynomial_k1); + cycles_property_float_set(cycles_cam, "fisheye_polynomial_k2", cam->fisheye_polynomial_k2); + cycles_property_float_set(cycles_cam, "fisheye_polynomial_k3", cam->fisheye_polynomial_k3); + cycles_property_float_set(cycles_cam, "fisheye_polynomial_k4", cam->fisheye_polynomial_k4); + + id->properties = idprop_temp; + + return {idprop_prev, idprop_temp}; +} + +static void camera_write_cycles_compatibility_data_clear(ID *id, + CameraCyclesCompatibilityData &data) +{ + id->properties = data.idprop_prev; + data.idprop_prev = nullptr; + + if (data.idprop_temp) { + IDP_FreeProperty(data.idprop_temp); + data.idprop_temp = nullptr; + } +} + static void camera_blend_write(BlendWriter *writer, ID *id, const void *id_address) { + const bool is_undo = BLO_write_is_undo(writer); Camera *cam = (Camera *)id; + CameraCyclesCompatibilityData cycles_data; + if (!is_undo) { + cycles_data = camera_write_cycles_compatibility_data_create(id); + } + /* write LibData */ BLO_write_id_struct(writer, Camera, id_address, &cam->id); BKE_id_blend_write(writer, &cam->id); @@ -114,6 +202,10 @@ static void camera_blend_write(BlendWriter *writer, ID *id, const void *id_addre LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) { BLO_write_struct(writer, CameraBGImage, bgpic); } + + if (!is_undo) { + camera_write_cycles_compatibility_data_clear(id, cycles_data); + } } static void camera_blend_read_data(BlendDataReader *reader, ID *id) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 7f709336411..e619f5a3df6 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -13,6 +13,7 @@ #include "CLG_log.h" #include "DNA_brush_types.h" +#include "DNA_camera_types.h" #include "DNA_light_types.h" #include "DNA_lightprobe_types.h" #include "DNA_modifier_types.h" @@ -675,19 +676,7 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) FOREACH_NODETREE_END; } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - #do_versions_after_linking_400 in this file. - * - `versioning_userdef.cc`, #blo_do_versions_userdef - * - `versioning_userdef.cc`, #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ - + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 17)) { if (!DNA_struct_find(fd->filesdna, "NodeShaderHairPrincipled")) { FOREACH_NODETREE_BEGIN (bmain, ntree, id) { if (ntree->type == NTREE_SHADER) { @@ -697,6 +686,56 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) FOREACH_NODETREE_END; } + /* Panorama properties shared with Eevee. */ + if (!DNA_struct_elem_find(fd->filesdna, "Camera", "float", "fisheye_fov")) { + Camera default_cam = *DNA_struct_default_get(Camera); + LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) { + IDProperty *ccam = version_cycles_properties_from_ID(&camera->id); + if (ccam) { + camera->panorama_type = version_cycles_property_int( + ccam, "panorama_type", default_cam.panorama_type); + camera->fisheye_fov = version_cycles_property_float( + ccam, "fisheye_fov", default_cam.fisheye_fov); + camera->fisheye_lens = version_cycles_property_float( + ccam, "fisheye_lens", default_cam.fisheye_lens); + camera->latitude_min = version_cycles_property_float( + ccam, "latitude_min", default_cam.latitude_min); + camera->latitude_max = version_cycles_property_float( + ccam, "latitude_max", default_cam.latitude_max); + camera->longitude_min = version_cycles_property_float( + ccam, "longitude_min", default_cam.longitude_min); + camera->longitude_max = version_cycles_property_float( + ccam, "longitude_max", default_cam.longitude_max); + /* Fit to match default projective camera with focal_length 50 and sensor_width 36. */ + camera->fisheye_polynomial_k0 = version_cycles_property_float( + ccam, "fisheye_polynomial_k0", default_cam.fisheye_polynomial_k0); + camera->fisheye_polynomial_k1 = version_cycles_property_float( + ccam, "fisheye_polynomial_k1", default_cam.fisheye_polynomial_k1); + camera->fisheye_polynomial_k2 = version_cycles_property_float( + ccam, "fisheye_polynomial_k2", default_cam.fisheye_polynomial_k2); + camera->fisheye_polynomial_k3 = version_cycles_property_float( + ccam, "fisheye_polynomial_k3", default_cam.fisheye_polynomial_k3); + camera->fisheye_polynomial_k4 = version_cycles_property_float( + ccam, "fisheye_polynomial_k4", default_cam.fisheye_polynomial_k4); + } + else { + camera->panorama_type = default_cam.panorama_type; + camera->fisheye_fov = default_cam.fisheye_fov; + camera->fisheye_lens = default_cam.fisheye_lens; + camera->latitude_min = default_cam.latitude_min; + camera->latitude_max = default_cam.latitude_max; + camera->longitude_min = default_cam.longitude_min; + camera->longitude_max = default_cam.longitude_max; + /* Fit to match default projective camera with focal_length 50 and sensor_width 36. */ + camera->fisheye_polynomial_k0 = default_cam.fisheye_polynomial_k0; + camera->fisheye_polynomial_k1 = default_cam.fisheye_polynomial_k1; + camera->fisheye_polynomial_k2 = default_cam.fisheye_polynomial_k2; + camera->fisheye_polynomial_k3 = default_cam.fisheye_polynomial_k3; + camera->fisheye_polynomial_k4 = default_cam.fisheye_polynomial_k4; + } + } + } + if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "float", "grid_flag")) { LISTBASE_FOREACH (LightProbe *, lightprobe, &bmain->lightprobes) { /* Keep old behavior of baking the whole lighting. */ @@ -711,4 +750,18 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) } } } + + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - #do_versions_after_linking_400 in this file. + * - `versioning_userdef.cc`, #blo_do_versions_userdef + * - `versioning_userdef.cc`, #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ + } } diff --git a/source/blender/makesdna/DNA_camera_defaults.h b/source/blender/makesdna/DNA_camera_defaults.h index f3b01b4082c..c8130ace5da 100644 --- a/source/blender/makesdna/DNA_camera_defaults.h +++ b/source/blender/makesdna/DNA_camera_defaults.h @@ -41,6 +41,20 @@ .ortho_scale = 6.0, \ .flag = CAM_SHOWPASSEPARTOUT, \ .passepartalpha = 0.5f, \ + \ + .panorama_type = CAM_PANORAMA_FISHEYE_EQUISOLID,\ + .fisheye_fov = M_PI,\ + .fisheye_lens = 10.5f,\ + .latitude_min = -0.5f * (float)M_PI,\ + .latitude_max = 0.5f * (float)M_PI,\ + .longitude_min = -M_PI,\ + .longitude_max = M_PI,\ + /* Fit to match default projective camera with focal_length 50 and sensor_width 36. */ \ + .fisheye_polynomial_k0 = -1.1735143712967577e-05f,\ + .fisheye_polynomial_k1 = -0.019988736953434998f,\ + .fisheye_polynomial_k2 = -3.3525322965709175e-06f,\ + .fisheye_polynomial_k3 = 3.099275275886036e-06f,\ + .fisheye_polynomial_k4 = -2.6064646454854524e-08f,\ \ .dof = _DNA_DEFAULT_CameraDOFSettings, \ \ diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h index 67541dd7fb9..680c1c18a95 100644 --- a/source/blender/makesdna/DNA_camera_types.h +++ b/source/blender/makesdna/DNA_camera_types.h @@ -91,6 +91,21 @@ typedef struct Camera { float shiftx, shifty; float dof_distance DNA_DEPRECATED; + char sensor_fit; + char panorama_type; + char _pad[2]; + + /** Fisheye properties. */ + float fisheye_fov; + float fisheye_lens; + float latitude_min, latitude_max; + float longitude_min, longitude_max; + float fisheye_polynomial_k0; + float fisheye_polynomial_k1; + float fisheye_polynomial_k2; + float fisheye_polynomial_k3; + float fisheye_polynomial_k4; + /** Old animation system, deprecated for 2.5. */ struct Ipo *ipo DNA_DEPRECATED; @@ -101,9 +116,6 @@ typedef struct Camera { /* CameraBGImage reference images */ struct ListBase bg_images; - char sensor_fit; - char _pad[7]; - /* Stereo settings */ struct CameraStereoSettings stereo; @@ -120,6 +132,16 @@ enum { CAM_PANO = 2, }; +/* panorama_type */ +enum { + CAM_PANORAMA_EQUIRECTANGULAR = 0, + CAM_PANORAMA_FISHEYE_EQUIDISTANT = 1, + CAM_PANORAMA_FISHEYE_EQUISOLID = 2, + CAM_PANORAMA_MIRRORBALL = 3, + CAM_PANORAMA_FISHEYE_LENS_POLYNOMIAL = 4, + CAM_PANORAMA_EQUIANGULAR_CUBEMAP_FACE = 5, +}; + /* dtx */ enum { CAM_DTX_CENTER = (1 << 0), diff --git a/source/blender/makesrna/intern/rna_camera.cc b/source/blender/makesrna/intern/rna_camera.cc index 7c7a710055a..ecb021a1d41 100644 --- a/source/blender/makesrna/intern/rna_camera.cc +++ b/source/blender/makesrna/intern/rna_camera.cc @@ -593,6 +593,41 @@ void RNA_def_camera(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem panorama_type_items[] = { + {CAM_PANORAMA_EQUIRECTANGULAR, + "EQUIRECTANGULAR", + 0, + "Equirectangular", + "Spherical camera for environment maps, also known as Lat Long panorama"}, + {CAM_PANORAMA_EQUIANGULAR_CUBEMAP_FACE, + "EQUIANGULAR_CUBEMAP_FACE", + 0, + "Equiangular Cubemap Face", + "Single face of an equiangular cubemap"}, + {CAM_PANORAMA_MIRRORBALL, + "MIRRORBALL", + 0, + "Mirror Ball", + "Mirror ball mapping for environment maps"}, + {CAM_PANORAMA_FISHEYE_EQUIDISTANT, + "FISHEYE_EQUIDISTANT", + 0, + "Fisheye Equidistant", + "Ideal for fulldomes, ignore the sensor dimensions"}, + {CAM_PANORAMA_FISHEYE_EQUISOLID, + "FISHEYE_EQUISOLID", + 0, + "Fisheye Equisolid", + "Similar to most fisheye modern lens, takes sensor dimensions into consideration"}, + {CAM_PANORAMA_FISHEYE_LENS_POLYNOMIAL, + "FISHEYE_LENS_POLYNOMIAL", + 0, + "Fisheye Lens Polynomial", + "Defines the lens projection as polynomial to allow real world camera lenses to be " + "mimicked"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + srna = RNA_def_struct(brna, "Camera", "ID"); RNA_def_struct_ui_text(srna, "Camera", "Camera data-block for storing camera settings"); RNA_def_struct_ui_icon(srna, ICON_CAMERA_DATA); @@ -817,6 +852,75 @@ void RNA_def_camera(BlenderRNA *brna) prop, "Harmonious Triangle B", "Display harmony B composition guide inside the camera view"); RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, nullptr); + /* Panoramic settings. */ + prop = RNA_def_property(srna, "panorama_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, panorama_type_items); + RNA_def_property_ui_text(prop, "Panorama Type", "Distortion to use for the calculation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "fisheye_fov", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_range(prop, 0.1745, 10.0 * M_PI); + RNA_def_property_ui_range(prop, 0.1745, 2.0 * M_PI, 3, 2); + RNA_def_property_ui_text(prop, "Field of View", "Field of view for the fisheye lens"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "fisheye_lens", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.01, 100.0); + RNA_def_property_ui_range(prop, 0.01, 15.0, 3, 2); + RNA_def_property_ui_text(prop, "Fisheye Lens", "Lens focal length (mm)"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "latitude_min", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_range(prop, -0.5 * M_PI, 0.5 * M_PI); + RNA_def_property_ui_range(prop, -0.5 * M_PI, 0.5 * M_PI, 3, 2); + RNA_def_property_ui_text( + prop, "Min Latitude", "Minimum latitude (vertical angle) for the equirectangular lens"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "latitude_max", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_range(prop, -0.5 * M_PI, 0.5 * M_PI); + RNA_def_property_ui_range(prop, -0.5 * M_PI, 0.5 * M_PI, 3, 2); + RNA_def_property_ui_text( + prop, "Max Latitude", "Maximum latitude (vertical angle) for the equirectangular lens"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "longitude_min", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_ui_range(prop, -M_PI, M_PI, 3, 2); + RNA_def_property_ui_text( + prop, "Min Longitude", "Minimum longitude (horizontal angle) for the equirectangular lens"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "longitude_max", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_ui_range(prop, -M_PI, M_PI, 3, 2); + RNA_def_property_ui_text( + prop, "Max Longitude", "Maximum longitude (horizontal angle) for the equirectangular lens"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "fisheye_polynomial_k0", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, 6); + RNA_def_property_ui_text(prop, "Fisheye Polynomial K0", "Coefficient K0 of the lens polynomial"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "fisheye_polynomial_k1", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, 6); + RNA_def_property_ui_text(prop, "Fisheye Polynomial K1", "Coefficient K1 of the lens polynomial"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "fisheye_polynomial_k2", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, 6); + RNA_def_property_ui_text(prop, "Fisheye Polynomial K2", "Coefficient K2 of the lens polynomial"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "fisheye_polynomial_k3", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, 6); + RNA_def_property_ui_text(prop, "Fisheye Polynomial K3", "Coefficient K3 of the lens polynomial"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + + prop = RNA_def_property(srna, "fisheye_polynomial_k4", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, 6); + RNA_def_property_ui_text(prop, "Fisheye Polynomial K4", "Coefficient K4 of the lens polynomial"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); + /* pointers */ prop = RNA_def_property(srna, "dof", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "CameraDOFSettings");