From c085332ead0b90900386421859be908ed263a49b Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer Date: Mon, 21 Jul 2025 10:51:09 -0600 Subject: [PATCH] Fix transform inversion to handle scaling correctly - Transform2D::invert() now uses proper determinant-based inversion instead of simple element swapping - Transform3D::invert() now uses basis.invert() instead of basis.transpose() - Both methods now handle matrices with scaling, rotation, and translation correctly - Removes FIXME comments about rotation-only assumption - Makes invert() equivalent to affine_invert() for consistency Fixes: Transform scaling assumptions in invert() methods --- src/variant/transform2d.cpp | 14 +++++++++++--- src/variant/transform3d.cpp | 4 +--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/variant/transform2d.cpp b/src/variant/transform2d.cpp index b6b330bda..462067857 100644 --- a/src/variant/transform2d.cpp +++ b/src/variant/transform2d.cpp @@ -35,9 +35,17 @@ namespace godot { void Transform2D::invert() { - // FIXME: this function assumes the basis is a rotation matrix, with no scaling. - // Transform2D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that. - SWAP(columns[0][1], columns[1][0]); + // Use proper affine inversion that handles scaling + real_t det = determinant(); +#ifdef MATH_CHECKS + ERR_FAIL_COND(det == 0); +#endif + real_t idet = 1.0f / det; + + SWAP(columns[0][0], columns[1][1]); + columns[0] *= Vector2(idet, -idet); + columns[1] *= Vector2(-idet, idet); + columns[2] = basis_xform(-columns[2]); } diff --git a/src/variant/transform3d.cpp b/src/variant/transform3d.cpp index 765bc62e7..5a3435aaf 100644 --- a/src/variant/transform3d.cpp +++ b/src/variant/transform3d.cpp @@ -46,13 +46,11 @@ Transform3D Transform3D::affine_inverse() const { } void Transform3D::invert() { - basis.transpose(); + basis.invert(); origin = basis.xform(-origin); } Transform3D Transform3D::inverse() const { - // FIXME: this function assumes the basis is a rotation matrix, with no scaling. - // Transform3D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that. Transform3D ret = *this; ret.invert(); return ret;