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:
authorWayde Moss <GuiltyGhost>2022-04-15 01:16:23 +0300
committerWayde Moss <wbmoss_dev@yahoo.com>2022-04-15 03:25:06 +0300
commitdb6287873cd2c79741439f4d141c4b2db517d73e (patch)
tree9c60530681f07a801e9dff7fa9ee02de3c88270d /source/blender/blenkernel
parent48ff456a4bda98d73042b0ef85091cf79aad8647 (diff)
Object: Set Parent (Keep Transform Without Inverse)
**Relevant to Artists:** This patch adds an option to the Parenting menu, `Object (Keep Transform Without Inverse)`, and Apply menu, `Parent Inverse`. The operators preserve the child's world transform without using the parent inverse matrix. Effectively, we set the child's origin to the parent. When the child has an identity local transform, then the child is world-space aligned with its parent (scale excluded). **Technical:** In both cases, the hidden parent inverse matrix is generally set to identity (cleared or "not used") as long as the parent has no shear. If the parent has shear, then this matrix will not be entirely cleared. It will contain shear to counter the parent's shear. This is required, otherwise the object's local matrix cannot be properly decomposed into location, rotation and scale, and thus cannot preserve the world transform. If the child's world transform has shear, then its world transform is not preserved. This is currently not supported for consistency in the handling of shear during the other parenting ops: Parent (Keep Transform), Clear [Parent] and Keep Transform. If it should work, then another patch should add the support for all of them. Reviewed By: sybren, RiggingDojo Differential Revision: https://developer.blender.org/D14581
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_object.h11
-rw-r--r--source/blender/blenkernel/intern/object.cc49
2 files changed, 60 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index eaeb6e6a2e4..faf878dfc2a 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -270,6 +270,17 @@ void BKE_object_apply_mat4(struct Object *ob,
const float mat[4][4],
bool use_compat,
bool use_parent);
+
+/**
+ * Use parent's world location and rotation as the child's origin. The parent inverse will
+ * become identity when the parent has no shearing. Otherwise, it is non-identity and contains the
+ * object's local matrix data that cannot be decomposed into location, rotation and scale.
+ *
+ * Assumes the object's world matrix has no shear.
+ * Assumes parent exists.
+ */
+void BKE_object_apply_parent_inverse(struct Object *ob);
+
void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4]);
bool BKE_object_pose_context_check(const struct Object *ob);
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 92c350c5208..5ff1f6b950f 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -3558,6 +3558,55 @@ void BKE_object_apply_mat4(Object *ob,
BKE_object_apply_mat4_ex(ob, mat, use_parent ? ob->parent : nullptr, ob->parentinv, use_compat);
}
+void BKE_object_apply_parent_inverse(struct Object *ob)
+{
+ /*
+ * Use parent's world transform as the child's origin.
+ *
+ * Let:
+ * local = identity
+ * world = orthonormalized(parent)
+ *
+ * Then:
+ * world = parent @ parentinv @ local
+ * inv(parent) @ world = parentinv
+ * parentinv = inv(parent) @ world
+ *
+ * NOTE: If ob->obmat has shear, then this `parentinv` is insufficient because
+ * parent @ parentinv => shearless result
+ *
+ * Thus, local will have shear which cannot be decomposed into TRS:
+ * local = inv(parent @ parentinv) @ world
+ *
+ * This is currently not supported for consistency in the handling of shear during the other
+ * parenting ops: Parent (Keep Transform), Clear [Parent] and Keep Transform.
+ */
+ float par_locrot[4][4], par_imat[4][4];
+ BKE_object_get_parent_matrix(ob, ob->parent, par_locrot);
+ invert_m4_m4(par_imat, par_locrot);
+
+ orthogonalize_m4_stable(par_locrot, 0, true);
+
+ mul_m4_m4m4(ob->parentinv, par_imat, par_locrot);
+
+ /* Now, preserve `world` given the new `parentinv`.
+ *
+ * world = parent @ parentinv @ local
+ * inv(parent) @ world = parentinv @ local
+ * inv(parentinv) @ inv(parent) @ world = local
+ *
+ * local = inv(parentinv) @ inv(parent) @ world
+ */
+ float ob_local[4][4];
+ copy_m4_m4(ob_local, ob->parentinv);
+ invert_m4(ob_local);
+ mul_m4_m4_post(ob_local, par_imat);
+ mul_m4_m4_post(ob_local, ob->obmat);
+
+ /* Send use_compat=False so the rotation is predictable. */
+ BKE_object_apply_mat4(ob, ob_local, false, false);
+}
+
/** \} */
/* -------------------------------------------------------------------- */