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/object.cc')
-rw-r--r--source/blender/blenkernel/intern/object.cc55
1 files changed, 52 insertions, 3 deletions
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index a54e2910b79..5ff1f6b950f 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -3087,12 +3087,12 @@ void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4])
static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4])
{
Curve *cu = (Curve *)par->data;
- float vec[4], dir[3], quat[4], radius, ctime;
+ float vec[4], quat[4], radius, ctime;
/* NOTE: Curve cache is supposed to be evaluated here already, however there
* are cases where we can not guarantee that. This includes, for example,
* dependency cycles. We can't correct anything from here, since that would
- * cause a threading conflicts.
+ * cause threading conflicts.
*
* TODO(sergey): Some of the legit looking cases like T56619 need to be
* looked into, and maybe curve cache (and other dependencies) are to be
@@ -3125,7 +3125,7 @@ static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4])
/* vec: 4 items! */
if (BKE_where_on_path(
- par, ctime, vec, dir, (cu->flag & CU_FOLLOW) ? quat : nullptr, &radius, nullptr)) {
+ par, ctime, vec, nullptr, (cu->flag & CU_FOLLOW) ? quat : nullptr, &radius, nullptr)) {
if (cu->flag & CU_FOLLOW) {
quat_apply_track(quat, ob->trackflag, ob->upflag);
normalize_qt(quat);
@@ -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);
+}
+
/** \} */
/* -------------------------------------------------------------------- */