Compare commits
1 Commits
refactor-m
...
temp-angav
Author | SHA1 | Date | |
---|---|---|---|
f873b85a39 |
@@ -856,95 +856,91 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
|
||||
|
||||
/* only evaluate if there is a target */
|
||||
if (VALID_CONS_TARGET(ct)) {
|
||||
float parmat[4][4];
|
||||
float parmat[4][4], obmat[4][4];
|
||||
|
||||
/* simple matrix parenting */
|
||||
if (data->flag == CHILDOF_ALL) {
|
||||
copy_m4_m4(obmat, cob->matrix);
|
||||
|
||||
/* multiply target (parent matrix) by offset (parent inverse) to get
|
||||
* the effect of the parent that will be exerted on the owner
|
||||
*/
|
||||
mul_m4_m4m4(parmat, ct->matrix, data->invmat);
|
||||
|
||||
/* now multiply the parent matrix by the owner matrix to get the
|
||||
* the effect of this constraint (i.e. owner is 'parented' to parent)
|
||||
*/
|
||||
mul_m4_m4m4(cob->matrix, parmat, cob->matrix);
|
||||
/* Simple matrix parenting. */
|
||||
if ((data->flag & CHILDOF_ALL) == CHILDOF_ALL) {
|
||||
copy_m4_m4(parmat, ct->matrix);
|
||||
}
|
||||
/* Filter the parent matrix by channel. */
|
||||
else {
|
||||
float invmat[4][4], tempmat[4][4];
|
||||
float loc[3], eul[3], size[3];
|
||||
float loco[3], eulo[3], sizo[3];
|
||||
|
||||
/* get offset (parent-inverse) matrix */
|
||||
copy_m4_m4(invmat, data->invmat);
|
||||
|
||||
/* extract components of both matrices */
|
||||
copy_v3_v3(loc, ct->matrix[3]);
|
||||
mat4_to_eulO(eul, ct->rotOrder, ct->matrix);
|
||||
mat4_to_size(size, ct->matrix);
|
||||
|
||||
copy_v3_v3(loco, invmat[3]);
|
||||
mat4_to_eulO(eulo, cob->rotOrder, invmat);
|
||||
mat4_to_size(sizo, invmat);
|
||||
|
||||
/* disable channels not enabled */
|
||||
if (!(data->flag & CHILDOF_LOCX)) {
|
||||
loc[0] = loco[0] = 0.0f;
|
||||
loc[0] = 0.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_LOCY)) {
|
||||
loc[1] = loco[1] = 0.0f;
|
||||
loc[1] = 0.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_LOCZ)) {
|
||||
loc[2] = loco[2] = 0.0f;
|
||||
loc[2] = 0.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_ROTX)) {
|
||||
eul[0] = eulo[0] = 0.0f;
|
||||
eul[0] = 0.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_ROTY)) {
|
||||
eul[1] = eulo[1] = 0.0f;
|
||||
eul[1] = 0.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_ROTZ)) {
|
||||
eul[2] = eulo[2] = 0.0f;
|
||||
eul[2] = 0.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_SIZEX)) {
|
||||
size[0] = sizo[0] = 1.0f;
|
||||
size[0] = 1.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_SIZEY)) {
|
||||
size[1] = sizo[1] = 1.0f;
|
||||
size[1] = 1.0f;
|
||||
}
|
||||
if (!(data->flag & CHILDOF_SIZEZ)) {
|
||||
size[2] = sizo[2] = 1.0f;
|
||||
size[2] = 1.0f;
|
||||
}
|
||||
|
||||
/* make new target mat and offset mat */
|
||||
loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder);
|
||||
loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder);
|
||||
loc_eulO_size_to_mat4(parmat, loc, eul, size, ct->rotOrder);
|
||||
}
|
||||
|
||||
/* multiply target (parent matrix) by offset (parent inverse) to get
|
||||
* the effect of the parent that will be exerted on the owner
|
||||
*/
|
||||
mul_m4_m4m4(parmat, ct->matrix, invmat);
|
||||
/* Compute the inverse matrix if requested. */
|
||||
if (data->flag & CHILDOF_SET_INVERSE) {
|
||||
invert_m4_m4(data->invmat, parmat);
|
||||
|
||||
/* now multiply the parent matrix by the owner matrix to get the
|
||||
* the effect of this constraint (i.e. owner is 'parented' to parent)
|
||||
*/
|
||||
copy_m4_m4(tempmat, cob->matrix);
|
||||
mul_m4_m4m4(cob->matrix, parmat, tempmat);
|
||||
data->flag &= ~CHILDOF_SET_INVERSE;
|
||||
|
||||
/* without this, changes to scale and rotation can change location
|
||||
* of a parentless bone or a disconnected bone. Even though its set
|
||||
* to zero above. */
|
||||
if (!(data->flag & CHILDOF_LOCX)) {
|
||||
cob->matrix[3][0] = tempmat[3][0];
|
||||
}
|
||||
if (!(data->flag & CHILDOF_LOCY)) {
|
||||
cob->matrix[3][1] = tempmat[3][1];
|
||||
}
|
||||
if (!(data->flag & CHILDOF_LOCZ)) {
|
||||
cob->matrix[3][2] = tempmat[3][2];
|
||||
/* Write the computed matrix back to the master copy if in COW evaluation. */
|
||||
bConstraint *orig_con = constraint_find_original_for_update(cob, con);
|
||||
|
||||
if (orig_con != NULL) {
|
||||
bChildOfConstraint *orig_data = orig_con->data;
|
||||
|
||||
copy_m4_m4(orig_data->invmat, data->invmat);
|
||||
orig_data->flag &= ~CHILDOF_SET_INVERSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiply together the target (parent) matrix, parent inverse,
|
||||
* and the owner transform matrixto get the effect of this constraint
|
||||
* (i.e. owner is 'parented' to parent). */
|
||||
|
||||
mul_m4_series(cob->matrix, parmat, data->invmat, obmat);
|
||||
|
||||
/* Without this, changes to scale and rotation can change location
|
||||
* of a parentless bone or a disconnected bone. Even though its set
|
||||
* to zero above. */
|
||||
if (!(data->flag & CHILDOF_LOCX)) {
|
||||
cob->matrix[3][0] = obmat[3][0];
|
||||
}
|
||||
if (!(data->flag & CHILDOF_LOCY)) {
|
||||
cob->matrix[3][1] = obmat[3][1];
|
||||
}
|
||||
if (!(data->flag & CHILDOF_LOCZ)) {
|
||||
cob->matrix[3][2] = obmat[3][2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4891,23 +4887,35 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
|
||||
object = BKE_tracking_object_get_named(tracking, data->object);
|
||||
|
||||
if (object) {
|
||||
float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4];
|
||||
float mat[4][4], obmat[4][4], imat[4][4], parmat[4][4];
|
||||
float ctime = DEG_get_ctime(depsgraph);
|
||||
float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
|
||||
|
||||
BKE_object_where_is_calc_mat4(camob, cammat);
|
||||
|
||||
BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat);
|
||||
|
||||
invert_m4_m4(camimat, cammat);
|
||||
mul_m4_m4m4(parmat, cammat, data->invmat);
|
||||
invert_m4_m4(imat, mat);
|
||||
mul_m4_m4m4(parmat, camob->obmat, imat);
|
||||
|
||||
copy_m4_m4(cammat, camob->obmat);
|
||||
copy_m4_m4(obmat, cob->matrix);
|
||||
|
||||
invert_m4_m4(imat, mat);
|
||||
/* Recalculate the inverse matrix if requested. */
|
||||
if (data->flag & OBJECTSOLVER_SET_INVERSE) {
|
||||
invert_m4_m4(data->invmat, parmat);
|
||||
|
||||
mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat);
|
||||
data->flag &= ~OBJECTSOLVER_SET_INVERSE;
|
||||
|
||||
/* Write the computed matrix back to the master copy if in COW evaluation. */
|
||||
bConstraint *orig_con = constraint_find_original_for_update(cob, con);
|
||||
|
||||
if (orig_con != NULL) {
|
||||
bObjectSolverConstraint *orig_data = orig_con->data;
|
||||
|
||||
copy_m4_m4(orig_data->invmat, data->invmat);
|
||||
orig_data->flag &= ~OBJECTSOLVER_SET_INVERSE;
|
||||
}
|
||||
}
|
||||
|
||||
mul_m4_series(cob->matrix, parmat, data->invmat, obmat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -871,118 +871,13 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
|
||||
|
||||
/* ------------- Child-Of Constraint ------------------ */
|
||||
|
||||
static void child_get_inverse_matrix_owner_bone(
|
||||
Depsgraph *depsgraph, wmOperator *op, Scene *scene, Object *ob, float invmat[4][4])
|
||||
{
|
||||
/* For bone owner we want to do this in evaluated domain.
|
||||
* BKE_pose_where_is / BKE_pose_where_is_bone relies on (re)evaluating parts of the scene
|
||||
* and copying new evaluated stuff back to original.
|
||||
*/
|
||||
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
bConstraint *con_eval = edit_constraint_property_get(op, ob_eval, CONSTRAINT_TYPE_CHILDOF);
|
||||
|
||||
/* nullify inverse matrix first */
|
||||
unit_m4(invmat);
|
||||
|
||||
bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval);
|
||||
|
||||
/* try to find a pose channel - assume that this is the constraint owner */
|
||||
/* TODO: get from context instead? */
|
||||
if (ob_eval && ob_eval->pose && pchan_eval) {
|
||||
bConstraint *con_last;
|
||||
|
||||
/* calculate/set inverse matrix:
|
||||
* We just calculate all transform-stack eval up to but not including this constraint.
|
||||
* This is because inverse should just inverse correct for just the constraint's influence
|
||||
* when it gets applied; that is, at the time of application, we don't know anything about
|
||||
* what follows.
|
||||
*/
|
||||
float imat[4][4], tmat[4][4];
|
||||
float pmat[4][4];
|
||||
|
||||
/* make sure we passed the correct constraint */
|
||||
BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1);
|
||||
|
||||
/* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
|
||||
* to use as baseline ("pmat") to derive delta from. This extra calc saves users
|
||||
* from having pressing "Clear Inverse" first
|
||||
*/
|
||||
BKE_pose_where_is(depsgraph, scene, ob_eval);
|
||||
copy_m4_m4(pmat, pchan_eval->pose_mat);
|
||||
|
||||
/* 2. knock out constraints starting from this one */
|
||||
con_last = pchan_eval->constraints.last;
|
||||
pchan_eval->constraints.last = con_eval->prev;
|
||||
|
||||
if (con_eval->prev) {
|
||||
/* new end must not point to this one, else this chain cutting is useless */
|
||||
con_eval->prev->next = NULL;
|
||||
}
|
||||
else {
|
||||
/* constraint was first */
|
||||
pchan_eval->constraints.first = NULL;
|
||||
}
|
||||
|
||||
/* 3. solve pose without disabled constraints */
|
||||
BKE_pose_where_is(depsgraph, scene, ob_eval);
|
||||
|
||||
/* 4. determine effect of constraint by removing the newly calculated
|
||||
* pchan->pose_mat from the original pchan->pose_mat, thus determining
|
||||
* the effect of the constraint
|
||||
*/
|
||||
invert_m4_m4(imat, pchan_eval->pose_mat);
|
||||
mul_m4_m4m4(tmat, pmat, imat);
|
||||
invert_m4_m4(invmat, tmat);
|
||||
|
||||
/* 5. restore constraints */
|
||||
pchan_eval->constraints.last = con_last;
|
||||
|
||||
if (con_eval->prev) {
|
||||
/* hook up prev to this one again */
|
||||
con_eval->prev->next = con_eval;
|
||||
}
|
||||
else {
|
||||
/* set as first again */
|
||||
pchan_eval->constraints.first = con_eval;
|
||||
}
|
||||
|
||||
/* 6. recalculate pose with new inv-mat applied */
|
||||
/* this one is unnecessary? (DEG seems to update correctly without)
|
||||
+ if we leave this in, we have to click "Set Inverse" twice to see updates...
|
||||
BKE_pose_where_is(depsgraph, scene, ob_eval); */
|
||||
}
|
||||
}
|
||||
|
||||
static void child_get_inverse_matrix_owner_object(
|
||||
Depsgraph *depsgraph, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4])
|
||||
{
|
||||
|
||||
/* nullify inverse matrix first */
|
||||
unit_m4(invmat);
|
||||
|
||||
if (ob) {
|
||||
Object workob;
|
||||
|
||||
/* make sure we passed the correct constraint */
|
||||
BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
|
||||
UNUSED_VARS_NDEBUG(con);
|
||||
|
||||
/* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
|
||||
BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
|
||||
invert_m4_m4(invmat, workob.obmat);
|
||||
}
|
||||
}
|
||||
|
||||
/* ChildOf Constraint - set inverse callback */
|
||||
static int childof_set_inverse_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
|
||||
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
|
||||
const int owner = RNA_enum_get(op->ptr, "owner");
|
||||
|
||||
/* despite 3 layers of checks, we may still not be able to find a constraint */
|
||||
if (data == NULL) {
|
||||
@@ -991,12 +886,8 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
|
||||
child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat);
|
||||
}
|
||||
else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
|
||||
child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat);
|
||||
}
|
||||
/* Set a flag to request recalculation on next update. */
|
||||
data->flag |= CHILDOF_SET_INVERSE;
|
||||
|
||||
ED_object_constraint_update(bmain, ob);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
|
||||
@@ -1231,12 +1122,9 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
|
||||
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *ob = ED_object_active_context(C);
|
||||
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
|
||||
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
|
||||
const int owner = RNA_enum_get(op->ptr, "owner");
|
||||
|
||||
/* despite 3 layers of checks, we may still not be able to find a constraint */
|
||||
if (data == NULL) {
|
||||
@@ -1245,12 +1133,8 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
|
||||
child_get_inverse_matrix_owner_object(depsgraph, scene, ob, con, data->invmat);
|
||||
}
|
||||
else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
|
||||
child_get_inverse_matrix_owner_bone(depsgraph, op, scene, ob, data->invmat);
|
||||
}
|
||||
/* Set a flag to request recalculation on next update. */
|
||||
data->flag |= OBJECTSOLVER_SET_INVERSE;
|
||||
|
||||
ED_object_constraint_update(bmain, ob);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
|
||||
|
@@ -1103,6 +1103,8 @@ typedef enum eChildOf_Flags {
|
||||
CHILDOF_SIZEY = (1 << 7),
|
||||
CHILDOF_SIZEZ = (1 << 8),
|
||||
CHILDOF_ALL = 511,
|
||||
/* Temporary flag used by the Set Inverse operator. */
|
||||
CHILDOF_SET_INVERSE = (1 << 9),
|
||||
} eChildOf_Flags;
|
||||
|
||||
/* Pivot Constraint */
|
||||
@@ -1154,6 +1156,8 @@ typedef enum eCameraSolver_Flags {
|
||||
/* ObjectSolver Constraint -> flag */
|
||||
typedef enum eObjectSolver_Flags {
|
||||
OBJECTSOLVER_ACTIVECLIP = (1 << 0),
|
||||
/* Temporary flag used by the Set Inverse operator. */
|
||||
OBJECTSOLVER_SET_INVERSE = (1 << 1),
|
||||
} eObjectSolver_Flags;
|
||||
|
||||
/* ObjectSolver Constraint -> flag */
|
||||
|
@@ -973,11 +973,18 @@ static void rna_def_constraint_childof(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Scale Z", "Use Z Scale of Parent");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop = RNA_def_property(srna, "set_inverse_pending", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CHILDOF_SET_INVERSE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Set Inverse Pending", "Set to true to request recalculation of the inverse matrix");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop = RNA_def_property(srna, "inverse_matrix", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_float_sdna(prop, NULL, "invmat");
|
||||
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
}
|
||||
|
||||
static void rna_def_constraint_python(BlenderRNA *brna)
|
||||
@@ -3152,6 +3159,12 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Active Clip", "Use active clip defined in scene");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop = RNA_def_property(srna, "set_inverse_pending", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", OBJECTSOLVER_SET_INVERSE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Set Inverse Pending", "Set to true to request recalculation of the inverse matrix");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
/* object */
|
||||
prop = RNA_def_property(srna, "object", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "object");
|
||||
|
Reference in New Issue
Block a user