Render: camera depth of field support for armature bone targets

This is useful when using an armature as a camera rig, to avoid creating and
targetting an empty object.

Differential Revision: https://developer.blender.org/D7012
This commit is contained in:
Damien Picard 2022-07-15 13:30:57 +02:00 committed by Brecht Van Lommel
parent 5ddbc14bb2
commit 2e70d5cb98
Notes: blender-bot 2023-02-14 02:27:56 +01:00
Referenced by issue #101533, Regression: Stretched image in the viewport when viewed from the lamp object
Referenced by issue #99777, Crash when renaming bones when there is a camera in the scene
Referenced by issue #99742, Crash blender when generate rig with Rigify.
8 changed files with 47 additions and 2 deletions

View File

@ -952,6 +952,8 @@ class CYCLES_CAMERA_PT_dof(CyclesButtonsPanel, Panel):
col = split.column()
col.prop(dof, "focus_object", text="Focus Object")
if dof.focus_object and dof.focus_object.type == 'ARMATURE':
col.prop_search(dof, "focus_subtarget", dof.focus_object.data, "bones", text="Focus Bone")
sub = col.row()
sub.active = dof.focus_object is None

View File

@ -143,11 +143,20 @@ static float blender_camera_focal_distance(BL::RenderEngine &b_engine,
if (!b_dof_object)
return b_camera.dof().focus_distance();
Transform dofmat = get_transform(b_dof_object.matrix_world());
string focus_subtarget = b_camera.dof().focus_subtarget();
if (b_dof_object.pose() && !focus_subtarget.empty()) {
BL::PoseBone b_bone = b_dof_object.pose().bones[focus_subtarget];
if (b_bone) {
dofmat = dofmat * get_transform(b_bone.matrix());
}
}
/* for dof object, return distance along camera Z direction */
BL::Array<float, 16> b_ob_matrix;
b_engine.camera_model_matrix(b_ob, bcam->use_spherical_stereo, b_ob_matrix);
Transform obmat = transform_clear_scale(get_transform(b_ob_matrix));
Transform dofmat = get_transform(b_dof_object.matrix_world());
float3 view_dir = normalize(transform_get_column(&obmat, 2));
float3 dof_dir = transform_get_column(&obmat, 3) - transform_get_column(&dofmat, 3);
return fabsf(dot(view_dir, dof_dir));

View File

@ -218,6 +218,8 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
col = layout.column()
col.prop(dof, "focus_object", text="Focus on Object")
if dof.focus_object and dof.focus_object.type == 'ARMATURE':
col.prop_search(dof, "focus_subtarget", dof.focus_object.data, "bones", text="Focus on Bone")
sub = col.column()
sub.active = (dof.focus_object is None)
sub.prop(dof, "focus_distance", text="Focus Distance")

View File

@ -26,6 +26,7 @@
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
#include "BKE_action.h"
#include "BKE_camera.h"
#include "BKE_idtype.h"
#include "BKE_layer.h"
@ -221,7 +222,15 @@ float BKE_camera_object_dof_distance(const Object *ob)
if (cam->dof.focus_object) {
float view_dir[3], dof_dir[3];
normalize_v3_v3(view_dir, ob->obmat[2]);
sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof.focus_object->obmat[3]);
bPoseChannel *pchan = BKE_pose_channel_find_name(cam->dof.focus_object->pose, cam->dof.focus_subtarget);
if (pchan) {
float posemat[4][4];
mul_m4_m4m4(posemat, cam->dof.focus_object->obmat, pchan->pose_mat);
sub_v3_v3v3(dof_dir, ob->obmat[3], posemat[3]);
}
else {
sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof.focus_object->obmat[3]);
}
return fabsf(dot_v3v3(view_dir, dof_dir));
}
return cam->dof.focus_distance;

View File

@ -2459,6 +2459,10 @@ void DepsgraphRelationBuilder::build_camera(Camera *camera)
ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
ComponentKey dof_ob_key(&camera->dof.focus_object->id, NodeType::TRANSFORM);
add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
if (camera->dof.focus_subtarget[0]) {
OperationKey target_key(&camera->dof.focus_object->id, NodeType::BONE, camera->dof.focus_subtarget, OperationCode::BONE_DONE);
add_relation(target_key, camera_parameters_key, "Camera DOF subtarget");
}
}
}

View File

@ -13,6 +13,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
@ -281,6 +282,17 @@ void ED_armature_bone_rename(Main *bmain,
}
}
/* fix camera focus */
if (ob->type == OB_CAMERA) {
Camera *cam = (Camera *)ob->data;
if (cam->dof.focus_object->data == arm){
if (STREQ(cam->dof.focus_subtarget, oldname)) {
BLI_strncpy(cam->dof.focus_subtarget, newname, MAXBONENAME);
DEG_id_tag_update(&cam->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
/* fix grease pencil modifiers and vertex groups */
if (ob->type == OB_GPENCIL) {

View File

@ -54,6 +54,7 @@ typedef struct CameraBGImage {
typedef struct CameraDOFSettings {
/** Focal distance for depth of field. */
struct Object *focus_object;
char focus_subtarget[64];
float focus_distance;
float aperture_fstop;
float aperture_rotation;

View File

@ -519,6 +519,12 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
prop, "Focus Object", "Use this object to define the depth of field focal point");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update");
prop = RNA_def_property(srna, "focus_subtarget", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "focus_subtarget");
RNA_def_property_ui_text(
prop, "Focus Bone", "Use this armature bone to define the depth of field focal point");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update");
prop = RNA_def_property(srna, "focus_distance", PROP_FLOAT, PROP_DISTANCE);
// RNA_def_property_pointer_sdna(prop, NULL, "focus_distance");
RNA_def_property_range(prop, 0.0f, FLT_MAX);