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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/constraint.c36
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h1
-rw-r--r--source/blender/blenlib/intern/math_matrix.c22
-rw-r--r--source/blender/editors/transform/transform_convert.c5
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h17
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c48
6 files changed, 118 insertions, 11 deletions
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 193b6d82d03..41da728fa5b 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2235,17 +2235,47 @@ static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
+ float target_mat[4][4];
+
+ copy_m4_m4(target_mat, ct->matrix);
+
+ /* Remove the shear of the target matrix if enabled.
+ * Use Y as the axis since it's the natural default for bones. */
+ if (data->flag & TRANSLIKE_REMOVE_TARGET_SHEAR) {
+ orthogonalize_m4_stable(target_mat, 1, false);
+ }
+
+ /* Finally, combine the matrices. */
switch (data->mix_mode) {
case TRANSLIKE_MIX_REPLACE:
- copy_m4_m4(cob->matrix, ct->matrix);
+ copy_m4_m4(cob->matrix, target_mat);
+ break;
+
+ /* Simple matrix multiplication. */
+ case TRANSLIKE_MIX_BEFORE_FULL:
+ mul_m4_m4m4(cob->matrix, target_mat, cob->matrix);
+ break;
+
+ case TRANSLIKE_MIX_AFTER_FULL:
+ mul_m4_m4m4(cob->matrix, cob->matrix, target_mat);
break;
+ /* Aligned Inherit Scale emulation. */
case TRANSLIKE_MIX_BEFORE:
- mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
+ mul_m4_m4m4_aligned_scale(cob->matrix, target_mat, cob->matrix);
break;
case TRANSLIKE_MIX_AFTER:
- mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix);
+ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, target_mat);
+ break;
+
+ /* Fully separate handling of channels. */
+ case TRANSLIKE_MIX_BEFORE_SPLIT:
+ mul_m4_m4m4_split_channels(cob->matrix, target_mat, cob->matrix);
+ break;
+
+ case TRANSLIKE_MIX_AFTER_SPLIT:
+ mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, target_mat);
break;
default:
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 54df88ca541..0c3a184d302 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -211,6 +211,7 @@ void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]);
void mul_m3_v3_double(const float M[3][3], double r[3]);
void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4]);
void mul_m3_fl(float R[3][3], float f);
void mul_m4_fl(float R[4][4], float f);
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 5eb0125062d..88bef854213 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1290,6 +1290,9 @@ bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
* Combines transformations, handling scale separately in a manner equivalent
* to the Aligned Inherit Scale mode, in order to avoid creating shear.
* If A scale is uniform, the result is equivalent to ordinary multiplication.
+ *
+ * Note: this effectively takes output location from simple multiplication,
+ * and uses mul_m4_m4m4_split_channels for rotation and scale.
*/
void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4])
{
@@ -1307,6 +1310,25 @@ void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B
loc_rot_size_to_mat4(R, loc_r, rot_r, size_r);
}
+/**
+ * Separately combines location, rotation and scale of the input matrices.
+ */
+void mul_m4_m4m4_split_channels(float R[4][4], const float A[4][4], const float B[4][4])
+{
+ float loc_a[3], rot_a[3][3], size_a[3];
+ float loc_b[3], rot_b[3][3], size_b[3];
+ float loc_r[3], rot_r[3][3], size_r[3];
+
+ mat4_to_loc_rot_size(loc_a, rot_a, size_a, A);
+ mat4_to_loc_rot_size(loc_b, rot_b, size_b, B);
+
+ add_v3_v3v3(loc_r, loc_a, loc_b);
+ mul_m3_m3m3_uniq(rot_r, rot_a, rot_b);
+ mul_v3_v3v3(size_r, size_a, size_b);
+
+ loc_rot_size_to_mat4(R, loc_r, rot_r, size_r);
+}
+
/****************************** Linear Algebra *******************************/
void transpose_m3(float R[3][3])
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 99368a40225..00fd008151d 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -849,10 +849,13 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list)
/* Copy Transforms constraint only does this in the Before mode. */
bTransLikeConstraint *data = (bTransLikeConstraint *)con->data;
- if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE) &&
+ if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE, TRANSLIKE_MIX_BEFORE_FULL) &&
ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) {
return true;
}
+ if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) {
+ return true;
+ }
}
else if (con->type == CONSTRAINT_TYPE_ACTION) {
/* The Action constraint only does this in the Before mode. */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 1e4fd2a70f2..25f72da2f15 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -316,8 +316,9 @@ typedef struct bSameVolumeConstraint {
/* Copy Transform Constraint */
typedef struct bTransLikeConstraint {
struct Object *tar;
+ int flag;
char mix_mode;
- char _pad[7];
+ char _pad[3];
/** MAX_ID_NAME-2. */
char subtarget[64];
} bTransLikeConstraint;
@@ -810,6 +811,12 @@ typedef enum eCopyScale_Flags {
SIZELIKE_UNIFORM = (1 << 5),
} eCopyScale_Flags;
+/* bTransLikeConstraint.flag */
+typedef enum eCopyTransforms_Flags {
+ /* Remove shear from the target matrix. */
+ TRANSLIKE_REMOVE_TARGET_SHEAR = (1 << 0),
+} eCopyTransforms_Flags;
+
/* bTransLikeConstraint.mix_mode */
typedef enum eCopyTransforms_MixMode {
/* Replace rotation channel values. */
@@ -818,6 +825,14 @@ typedef enum eCopyTransforms_MixMode {
TRANSLIKE_MIX_BEFORE = 1,
/* Multiply the copied transformation on the right, with anti-shear scale handling. */
TRANSLIKE_MIX_AFTER = 2,
+ /* Multiply the copied transformation on the left, handling loc/rot/scale separately. */
+ TRANSLIKE_MIX_BEFORE_SPLIT = 3,
+ /* Multiply the copied transformation on the right, handling loc/rot/scale separately. */
+ TRANSLIKE_MIX_AFTER_SPLIT = 4,
+ /* Multiply the copied transformation on the left, using simple matrix multiplication. */
+ TRANSLIKE_MIX_BEFORE_FULL = 5,
+ /* Multiply the copied transformation on the right, using simple matrix multiplication. */
+ TRANSLIKE_MIX_AFTER_FULL = 6,
} eCopyTransforms_MixMode;
/* bTransformConstraint.to/from */
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index d79f2c4d13f..d34885e1a68 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1624,18 +1624,48 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
0,
"Replace",
"Replace the original transformation with copied"},
+ {0, "", 0, NULL, NULL},
+ {TRANSLIKE_MIX_BEFORE_FULL,
+ "BEFORE_FULL",
+ 0,
+ "Before Original (Full)",
+ "Apply copied transformation before original, using simple matrix multiplication as if "
+ "the constraint target is a parent in Full Inherit Scale mode. "
+ "Will create shear when combining rotation and non-uniform scale"},
{TRANSLIKE_MIX_BEFORE,
"BEFORE",
0,
- "Before Original",
- "Apply copied transformation before original, as if the constraint target is a parent. "
- "Scale is handled specially to avoid creating shear"},
+ "Before Original (Aligned)",
+ "Apply copied transformation before original, as if the constraint target is a parent in "
+ "Aligned Inherit Scale mode. This effectively uses Full for location and Split Channels "
+ "for rotation and scale"},
+ {TRANSLIKE_MIX_BEFORE_SPLIT,
+ "BEFORE_SPLIT",
+ 0,
+ "Before Original (Split Channels)",
+ "Apply copied transformation before original, handling location, rotation and scale "
+ "separately, similar to a sequence of three Copy constraints"},
+ {0, "", 0, NULL, NULL},
+ {TRANSLIKE_MIX_AFTER_FULL,
+ "AFTER_FULL",
+ 0,
+ "After Original (Full)",
+ "Apply copied transformation after original, using simple matrix multiplication as if "
+ "the constraint target is a child in Full Inherit Scale mode. "
+ "Will create shear when combining rotation and non-uniform scale"},
{TRANSLIKE_MIX_AFTER,
"AFTER",
0,
- "After Original",
- "Apply copied transformation after original, as if the constraint target is a child. "
- "Scale is handled specially to avoid creating shear"},
+ "After Original (Aligned)",
+ "Apply copied transformation after original, as if the constraint target is a child in "
+ "Aligned Inherit Scale mode. This effectively uses Full for location and Split Channels "
+ "for rotation and scale"},
+ {TRANSLIKE_MIX_AFTER_SPLIT,
+ "AFTER_SPLIT",
+ 0,
+ "After Original (Split Channels)",
+ "Apply copied transformation after original, handling location, rotation and scale "
+ "separately, similar to a sequence of three Copy constraints"},
{0, NULL, 0, NULL, NULL},
};
@@ -1653,6 +1683,12 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
RNA_define_lib_overridable(true);
+ prop = RNA_def_property(srna, "remove_target_shear", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", TRANSLIKE_REMOVE_TARGET_SHEAR);
+ RNA_def_property_ui_text(
+ prop, "Remove Target Shear", "Remove shear from the target transformation before combining");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mix_mode");
RNA_def_property_enum_items(prop, mix_mode_items);