Camera: Move panoramic projection settings to DNA #111310

Merged
Clément Foucault merged 14 commits from fclem/blender:blender-camear-panoramic-parameters into main 2023-08-22 15:49:40 +02:00
9 changed files with 352 additions and 153 deletions

View File

@ -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)

View File

@ -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();
fclem marked this conversation as resolved Outdated

Don't use default, and let compiler to point out at missing cases, to help in the future to who are adding new panorama types.

Don't use `default`, and let compiler to point out at missing cases, to help in the future to who are adding new panorama types.

What if you are loading a newer file with a non existing panorama type?

What if you are loading a newer file with a non existing panorama type?

Good point.

Then you move the switch to a function like blender_panorama_type_to_cycles, replace assignment with return, and explicitly outside of the switch statement return PANORAMA_EQUIRECTANGULAR with a comment that it is for the forward compatibility.

best of many worlds:

  • Clear explanation why it is needed
  • Single responsibility principle
  • Best guidance from compiler when adding new panorama type
Good point. Then you move the switch to a function like `blender_panorama_type_to_cycles`, replace assignment with `return`, and explicitly outside of the `switch` statement return `PANORAMA_EQUIRECTANGULAR` with a comment that it is for the forward compatibility. best of many worlds: - Clear explanation why it is needed - Single responsibility principle - Best guidance from compiler when adding new panorama type
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) {

View File

@ -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':

View File

@ -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

View File

@ -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);
Review

The write code should not modify the input ID. In fact, the ID should be const-qualified.

One way to achieve this I can think of is to make a shallow copy of the Camera, duplicate the ID properties, set the required properties, write using BLO_write_struct_at_address, and free the copied version of ID properties.

Additionally, such versioning should not happen for undo pushes.

The write code should not modify the input ID. In fact, the ID should be const-qualified. One way to achieve this I can think of is to make a shallow copy of the Camera, duplicate the ID properties, set the required properties, write using `BLO_write_struct_at_address`, and free the copied version of ID properties. Additionally, such versioning should not happen for undo pushes.
Review

@Sergey all IDs are already shallow-duplicated by generic write code, precisely because we do 'modify' these a lot when writing (esp. by setting many runtime data to NULL e.g.).

@Sergey all IDs are already shallow-duplicated by generic write code, precisely because we do 'modify' these a lot when writing (esp. by setting many runtime data to NULL e.g.).
Review

Then no shallow-copy needed, but you still should not add ID properties to the original data-block.

Then no shallow-copy needed, but you still should not add ID properties to the original data-block.
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);
fclem marked this conversation as resolved Outdated

previous blender versions

`previous blender versions`
/* 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;
fclem marked this conversation as resolved Outdated

More of a 'good practice' than strictly required, but would clear both IDPropoerty pointers in data. That way, any potential future access to these would give an obvious 'accessing NULL pointer' error.

More of a 'good practice' than strictly required, but would clear both IDPropoerty pointers in `data`. That way, any potential future access to these would give an obvious 'accessing NULL pointer' error.
}
}
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;
fclem marked this conversation as resolved Outdated

Could be stored as a const bool is_undo variable, instead of calling the function several times.

Could be stored as a `const bool is_undo` variable, instead of calling the function several times.
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)

View File

@ -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(
fclem marked this conversation as resolved Outdated

I think it's not enough to do versioning for ccam. If there is a camera in the scene, but the render engine is not Cycles (as in the default file), then after changing to Cycles all the camera parameters in panoramic type are zero instead of the default values.

I think it's not enough to do versioning for `ccam`. If there is a camera in the scene, but the render engine is not Cycles (as in the default file), then after changing to Cycles all the camera parameters in panoramic type are zero instead of the default values.
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(
fclem marked this conversation as resolved Outdated

Use functional cast: float(M_PI)

More about it https://wiki.blender.org/wiki/Style_Guide/C_Cpp#C.2B.2B_Type_Cast

Use functional cast: `float(M_PI)` More about it https://wiki.blender.org/wiki/Style_Guide/C_Cpp#C.2B.2B_Type_Cast
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);
fclem marked this conversation as resolved Outdated

Why is it in some cases there is explicit cast to float, but not in others?

Why is it in some cases there is explicit cast to float, but not in others?

Because explicit cast is usually to avoid double promotion. Or maybe I'm missing something.

Because explicit cast is usually to avoid `double` promotion. Or maybe I'm missing something.

Ah, it is expression vs. single value as an argument. Makes sense now.

Ah, it is expression vs. single value as an argument. Makes sense now.
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(
fclem marked this conversation as resolved Outdated

Rather than duplicating the info here (and risking future out-of-sync issues), would rather create a temp dummy Camera data, initialize it (calling camera_init_data on it), and then copy the variables' values from it into the real ID. That way you get defaults as defined in DNA.

Rather than duplicating the info here (and risking future out-of-sync issues), would rather create a temp dummy `Camera` data, initialize it (calling `camera_init_data` on it), and then copy the variables' values from it into the real ID. That way you get defaults as defined in DNA.
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. */
}
}

View File

@ -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,\
fclem marked this conversation as resolved Outdated

There should be a f suffix.
The default values in addon/camera.py can be deleted I think. Turns out that the whole addon/camera.py is just for reference and not used. Probably fine to keep the default values there, but maybe refer to the function fisheye_lens_polynomial_from_projective() here to make it more clear where these values come from.

There should be a `f` suffix. ~~The default values in `addon/camera.py` can be deleted I think.~~ Turns out that the whole `addon/camera.py` is just for reference and not used. Probably fine to keep the default values there, but maybe refer to the function `fisheye_lens_polynomial_from_projective()` here to make it more clear where these values come from.
.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, \
\

View File

@ -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),

View File

@ -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");