Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/constraint.c')
-rw-r--r--source/blender/blenkernel/intern/constraint.c238
1 files changed, 196 insertions, 42 deletions
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index e1e4d138fd9..d59849695ff 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -62,6 +62,7 @@
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
@@ -1801,25 +1802,47 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
- float loc[3];
- float eul[3], obeul[3];
- float size[3];
+ float loc[3], size[3], oldrot[3][3], newrot[3][3];
+ float eul[3], obeul[3], defeul[3];
- copy_v3_v3(loc, cob->matrix[3]);
- mat4_to_size(size, cob->matrix);
+ mat4_to_loc_rot_size(loc, oldrot, size, cob->matrix);
+
+ /* Select the Euler rotation order, defaulting to the owner. */
+ short rot_order = cob->rotOrder;
+
+ if (data->euler_order != CONSTRAINT_EULER_AUTO) {
+ rot_order = data->euler_order;
+ }
/* To allow compatible rotations, must get both rotations in the order of the owner... */
- mat4_to_eulO(obeul, cob->rotOrder, cob->matrix);
+ mat4_to_eulO(obeul, rot_order, cob->matrix);
/* We must get compatible eulers from the beginning because
* some of them can be modified below (see bug T21875). */
- mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix);
+ mat4_to_compatible_eulO(eul, obeul, rot_order, ct->matrix);
+
+ /* Prepare the copied euler rotation. */
+ bool legacy_offset = false;
+
+ switch (data->mix_mode) {
+ case ROTLIKE_MIX_OFFSET:
+ legacy_offset = true;
+ copy_v3_v3(defeul, obeul);
+ break;
+
+ case ROTLIKE_MIX_REPLACE:
+ copy_v3_v3(defeul, obeul);
+ break;
+
+ default:
+ zero_v3(defeul);
+ }
if ((data->flag & ROTLIKE_X) == 0) {
- eul[0] = obeul[0];
+ eul[0] = defeul[0];
}
else {
- if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'X', obeul[0]);
+ if (legacy_offset) {
+ rotate_eulO(eul, rot_order, 'X', obeul[0]);
}
if (data->flag & ROTLIKE_X_INVERT) {
@@ -1828,11 +1851,11 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
if ((data->flag & ROTLIKE_Y) == 0) {
- eul[1] = obeul[1];
+ eul[1] = defeul[1];
}
else {
- if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'Y', obeul[1]);
+ if (legacy_offset) {
+ rotate_eulO(eul, rot_order, 'Y', obeul[1]);
}
if (data->flag & ROTLIKE_Y_INVERT) {
@@ -1841,11 +1864,11 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
if ((data->flag & ROTLIKE_Z) == 0) {
- eul[2] = obeul[2];
+ eul[2] = defeul[2];
}
else {
- if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'Z', obeul[2]);
+ if (legacy_offset) {
+ rotate_eulO(eul, rot_order, 'Z', obeul[2]);
}
if (data->flag & ROTLIKE_Z_INVERT) {
@@ -1853,10 +1876,36 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
}
+ /* Add the euler components together if needed. */
+ if (data->mix_mode == ROTLIKE_MIX_ADD) {
+ add_v3_v3(eul, obeul);
+ }
+
/* Good to make eulers compatible again,
* since we don't know how much they were changed above. */
compatible_eul(eul, obeul);
- loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
+ eulO_to_mat3(newrot, eul, rot_order);
+
+ /* Mix the rotation matrices: */
+ switch (data->mix_mode) {
+ case ROTLIKE_MIX_REPLACE:
+ case ROTLIKE_MIX_OFFSET:
+ case ROTLIKE_MIX_ADD:
+ break;
+
+ case ROTLIKE_MIX_BEFORE:
+ mul_m3_m3m3(newrot, newrot, oldrot);
+ break;
+
+ case ROTLIKE_MIX_AFTER:
+ mul_m3_m3m3(newrot, oldrot, newrot);
+ break;
+
+ default:
+ BLI_assert(false);
+ }
+
+ loc_rot_size_to_mat4(cob->matrix, loc, newrot, size);
}
}
@@ -1927,9 +1976,39 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
if (VALID_CONS_TARGET(ct)) {
float obsize[3], size[3];
- mat4_to_size(size, ct->matrix);
mat4_to_size(obsize, cob->matrix);
+ /* Compute one uniform scale factor to apply to all three axes. */
+ if (data->flag & SIZELIKE_UNIFORM) {
+ const int all_axes = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z;
+ float total = 1.0f;
+
+ /* If all axes are selected, use the determinant. */
+ if ((data->flag & all_axes) == all_axes) {
+ total = fabsf(mat4_to_volume_scale(ct->matrix));
+ }
+ /* Otherwise multiply individual values. */
+ else {
+ mat4_to_size(size, ct->matrix);
+
+ if (data->flag & SIZELIKE_X) {
+ total *= size[0];
+ }
+ if (data->flag & SIZELIKE_Y) {
+ total *= size[1];
+ }
+ if (data->flag & SIZELIKE_Z) {
+ total *= size[2];
+ }
+ }
+
+ copy_v3_fl(size, cbrt(total));
+ }
+ /* Regular per-axis scaling. */
+ else {
+ mat4_to_size(size, ct->matrix);
+ }
+
for (int i = 0; i < 3; i++) {
size[i] = powf(size[i], data->power);
}
@@ -1948,13 +2027,13 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
}
}
- if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) {
+ if ((data->flag & (SIZELIKE_X | SIZELIKE_UNIFORM)) && (obsize[0] != 0)) {
mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
}
- if ((data->flag & SIZELIKE_Y) && (obsize[1] != 0)) {
+ if ((data->flag & (SIZELIKE_Y | SIZELIKE_UNIFORM)) && (obsize[1] != 0)) {
mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
}
- if ((data->flag & SIZELIKE_Z) && (obsize[2] != 0)) {
+ if ((data->flag & (SIZELIKE_Z | SIZELIKE_UNIFORM)) && (obsize[2] != 0)) {
mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
}
}
@@ -2011,13 +2090,43 @@ static void translike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void translike_evaluate(bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
+static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
+ bTransLikeConstraint *data = con->data;
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
- /* just copy the entire transform matrix of the target */
- copy_m4_m4(cob->matrix, ct->matrix);
+ if (data->mix_mode == TRANSLIKE_MIX_REPLACE) {
+ /* just copy the entire transform matrix of the target */
+ copy_m4_m4(cob->matrix, ct->matrix);
+ }
+ else {
+ float old_loc[3], old_rot[3][3], old_size[3];
+ float new_loc[3], new_rot[3][3], new_size[3];
+
+ /* Separate matrices so they can be combined in a way that avoids shear. */
+ mat4_to_loc_rot_size(old_loc, old_rot, old_size, cob->matrix);
+ mat4_to_loc_rot_size(new_loc, new_rot, new_size, ct->matrix);
+
+ switch (data->mix_mode) {
+ case TRANSLIKE_MIX_BEFORE:
+ mul_v3_m4v3(new_loc, ct->matrix, old_loc);
+ mul_m3_m3m3(new_rot, new_rot, old_rot);
+ mul_v3_v3(new_size, old_size);
+ break;
+
+ case TRANSLIKE_MIX_AFTER:
+ mul_v3_m4v3(new_loc, cob->matrix, new_loc);
+ mul_m3_m3m3(new_rot, old_rot, new_rot);
+ mul_v3_v3(new_size, old_size);
+ break;
+
+ default:
+ BLI_assert(false);
+ }
+
+ loc_rot_size_to_mat4(cob->matrix, new_loc, new_rot, new_size);
+ }
}
}
@@ -2301,9 +2410,9 @@ static void armdef_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
}
static void armdef_accumulate_matrix(float obmat[4][4],
- float iobmat[4][4],
- float basemat[4][4],
- float bonemat[4][4],
+ const float iobmat[4][4],
+ const float basemat[4][4],
+ const float bonemat[4][4],
float weight,
float r_sum_mat[4][4],
DualQuat *r_sum_dq)
@@ -3644,6 +3753,11 @@ static void transform_new_data(void *cdata)
data->map[0] = 0;
data->map[1] = 1;
data->map[2] = 2;
+
+ for (int i = 0; i < 3; i++) {
+ data->from_min_scale[i] = data->from_max_scale[i] = 1.0f;
+ data->to_min_scale[i] = data->to_max_scale[i] = 1.0f;
+ }
}
static void transform_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -3688,8 +3802,10 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
/* only evaluate if there is a target */
if (VALID_CONS_TARGET(ct)) {
float *from_min, *from_max, *to_min, *to_max;
- float loc[3], eul[3], size[3];
- float dvec[3], sval[3];
+ float loc[3], rot[3][3], oldeul[3], size[3];
+ float newloc[3], newrot[3][3], neweul[3], newsize[3];
+ float dbuf[4], sval[3];
+ float *const dvec = dbuf + 1;
int i;
/* obtain target effect */
@@ -3708,7 +3824,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
from_max = data->from_max_scale;
break;
case TRANS_ROTATION:
- mat4_to_eulO(dvec, cob->rotOrder, ct->matrix);
+ BKE_driver_target_matrix_to_rot_channels(
+ ct->matrix, cob->rotOrder, data->from_rotation_mode, -1, true, dbuf);
from_min = data->from_min_rot;
from_max = data->from_max_rot;
break;
@@ -3720,10 +3837,15 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
break;
}
+ /* Select the output Euler rotation order, defaulting to the owner. */
+ short rot_order = cob->rotOrder;
+
+ if (data->to == TRANS_ROTATION && data->to_euler_order != CONSTRAINT_EULER_AUTO) {
+ rot_order = data->to_euler_order;
+ }
+
/* extract components of owner's matrix */
- copy_v3_v3(loc, cob->matrix[3]);
- mat4_to_eulO(eul, cob->rotOrder, cob->matrix);
- mat4_to_size(size, cob->matrix);
+ mat4_to_loc_rot_size(loc, rot, size, cob->matrix);
/* determine where in range current transforms lie */
if (data->expo) {
@@ -3755,18 +3877,42 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
to_min = data->to_min_scale;
to_max = data->to_max_scale;
for (i = 0; i < 3; i++) {
- /* multiply with original scale (so that it can still be scaled) */
- /* size[i] *= to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])); */
- /* Stay absolute, else it breaks existing rigs... sigh. */
- size[i] = to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i]));
+ newsize[i] = to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i]));
+ }
+ switch (data->mix_mode_scale) {
+ case TRANS_MIXSCALE_MULTIPLY:
+ mul_v3_v3(size, newsize);
+ break;
+ case TRANS_MIXSCALE_REPLACE:
+ default:
+ copy_v3_v3(size, newsize);
+ break;
}
break;
case TRANS_ROTATION:
to_min = data->to_min_rot;
to_max = data->to_max_rot;
for (i = 0; i < 3; i++) {
- /* add to original rotation (so that it can still be rotated) */
- eul[i] += to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i]));
+ neweul[i] = to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i]));
+ }
+ switch (data->mix_mode_rot) {
+ case TRANS_MIXROT_REPLACE:
+ eulO_to_mat3(rot, neweul, rot_order);
+ break;
+ case TRANS_MIXROT_BEFORE:
+ eulO_to_mat3(newrot, neweul, rot_order);
+ mul_m3_m3m3(rot, newrot, rot);
+ break;
+ case TRANS_MIXROT_AFTER:
+ eulO_to_mat3(newrot, neweul, rot_order);
+ mul_m3_m3m3(rot, rot, newrot);
+ break;
+ case TRANS_MIXROT_ADD:
+ default:
+ mat3_to_eulO(oldeul, rot_order, rot);
+ add_v3_v3(neweul, oldeul);
+ eulO_to_mat3(rot, neweul, rot_order);
+ break;
}
break;
case TRANS_LOCATION:
@@ -3774,14 +3920,22 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
to_min = data->to_min;
to_max = data->to_max;
for (i = 0; i < 3; i++) {
- /* add to original location (so that it can still be moved) */
- loc[i] += (to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])));
+ newloc[i] = (to_min[i] + (sval[(int)data->map[i]] * (to_max[i] - to_min[i])));
+ }
+ switch (data->mix_mode_loc) {
+ case TRANS_MIXLOC_REPLACE:
+ copy_v3_v3(loc, newloc);
+ break;
+ case TRANS_MIXLOC_ADD:
+ default:
+ add_v3_v3(loc, newloc);
+ break;
}
break;
}
/* apply to matrix */
- loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
+ loc_rot_size_to_mat4(cob->matrix, loc, rot, size);
}
}