From 170a41ca8254b195ef06b9043038763f6769f819 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 14 Aug 2022 00:18:21 +0200 Subject: [PATCH] Backported improvements to Basis from Godot4. Also bound all eligible methods. --- core/math/basis.cpp | 195 ++++++++++++++++-- core/math/basis.h | 87 +++++--- core/math/transform.cpp | 6 +- core/variant_call.cpp | 151 ++++++++++++-- doc/classes/Basis.xml | 4 +- editor/inspector_dock.cpp | 2 +- modules/gltf/gltf_document.cpp | 10 +- .../skeleton_editor_plugin.cpp | 6 +- scene/3d/skeleton.cpp | 2 +- scene/3d/skeleton.h | 2 +- scene/animation/animation_player.cpp | 2 +- scene/animation/animation_tree.cpp | 4 +- 12 files changed, 388 insertions(+), 83 deletions(-) diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 96329ab92..e76815b87 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -73,9 +73,9 @@ void Basis::invert() { void Basis::orthonormalize() { // Gram-Schmidt Process - Vector3 x = get_axis(0); - Vector3 y = get_axis(1); - Vector3 z = get_axis(2); + Vector3 x = get_column(0); + Vector3 y = get_column(1); + Vector3 z = get_column(2); x.normalize(); y = (y - x * (x.dot(y))); @@ -83,9 +83,9 @@ void Basis::orthonormalize() { z = (z - x * (x.dot(z)) - y * (y.dot(z))); z.normalize(); - set_axis(0, x); - set_axis(1, y); - set_axis(2, z); + set_column(0, x); + set_column(1, y); + set_column(2, z); } Basis Basis::orthonormalized() const { @@ -101,6 +101,18 @@ bool Basis::is_orthogonal() const { return m.is_equal_approx(identity); } +void Basis::orthogonalize() { + Vector3 scl = get_scale(); + orthonormalize(); + scale_local(scl); +} + +Basis Basis::orthogonalized() const { + Basis c = *this; + c.orthogonalize(); + return c; +} + bool Basis::is_diagonal() const { return ( Math::is_zero_approx(rows[0][1]) && Math::is_zero_approx(rows[0][2]) && @@ -237,6 +249,36 @@ Basis Basis::scaled_local(const Vector3 &p_scale) const { return (*this) * b; } +void Basis::scale_orthogonal(const Vector3 &p_scale) { + *this = scaled_orthogonal(p_scale); +} + +Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { + Basis m = *this; + Vector3 s = Vector3(-1, -1, -1) + p_scale; + Vector3 dots; + Basis b; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + dots[j] += s[i] * abs(m.get_column(i).normalized().dot(b.get_column(j))); + } + } + m.scale_local(Vector3(1, 1, 1) + dots); + return m; +} + +float Basis::get_uniform_scale() const { + return (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f; +} + +void Basis::make_scale_uniform() { + float l = (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f; + for (int i = 0; i < 3; i++) { + rows[i].normalize(); + rows[i] *= l; + } +} + Vector3 Basis::get_scale_abs() const { return Vector3( Vector3(rows[0][0], rows[1][0], rows[2][0]).length(), @@ -348,7 +390,7 @@ Vector3 Basis::get_rotation_euler() const { return m.get_euler(); } -Quaternion Basis::get_rotation_quat() const { +Quaternion Basis::get_rotation_quaternion() const { // Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S, // and returns the Euler angles corresponding to the rotation part, complementing get_scale(). // See the comment in get_scale() for further information. @@ -359,7 +401,7 @@ Quaternion Basis::get_rotation_quat() const { m.scale(Vector3(-1, -1, -1)); } - return m.get_quat(); + return m.get_quaternion(); } void Basis::rotate_to_align(Vector3 p_start_direction, Vector3 p_end_direction) { @@ -775,9 +817,9 @@ Basis::operator String() const { return mtx; } -Quaternion Basis::get_quat() const { +Quaternion Basis::get_quaternion() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternionernion. Use get_rotation_quat() or call orthonormalized() if the Basis contains linearly independent vectors."); + ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternionernion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors."); #endif /* Allow getting a quaternion from an unnormalized transform */ Basis m = *this; @@ -949,7 +991,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { r_angle = angle; } -void Basis::set_quat(const Quaternion &p_quat) { +void Basis::set_quaternion(const Quaternion &p_quat) { real_t d = p_quat.length_squared(); real_t s = 2 / d; real_t xs = p_quat.x * s, ys = p_quat.y * s, zs = p_quat.z * s; @@ -1001,7 +1043,7 @@ void Basis::set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale) { rotate(p_euler); } -void Basis::set_quat_scale(const Quaternion &p_quat, const Vector3 &p_scale) { +void Basis::set_quaternion_scale(const Quaternion &p_quat, const Vector3 &p_scale) { set_diagonal(p_scale); rotate(p_quat); } @@ -1032,3 +1074,132 @@ Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const { return b; } + +void Basis::rotate_sh(real_t *p_values) { + // code by John Hable + // http://filmicworlds.com/blog/simple-and-fast-spherical-harmonic-rotation/ + // this code is Public Domain + + const static real_t s_c3 = 0.94617469575; // (3*sqrt(5))/(4*sqrt(pi)) + const static real_t s_c4 = -0.31539156525; // (-sqrt(5))/(4*sqrt(pi)) + const static real_t s_c5 = 0.54627421529; // (sqrt(15))/(4*sqrt(pi)) + + const static real_t s_c_scale = 1.0 / 0.91529123286551084; + const static real_t s_c_scale_inv = 0.91529123286551084; + + const static real_t s_rc2 = 1.5853309190550713 * s_c_scale; + const static real_t s_c4_div_c3 = s_c4 / s_c3; + const static real_t s_c4_div_c3_x2 = (s_c4 / s_c3) * 2.0; + + const static real_t s_scale_dst2 = s_c3 * s_c_scale_inv; + const static real_t s_scale_dst4 = s_c5 * s_c_scale_inv; + + const real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] }; + + real_t m00 = rows[0][0]; + real_t m01 = rows[0][1]; + real_t m02 = rows[0][2]; + real_t m10 = rows[1][0]; + real_t m11 = rows[1][1]; + real_t m12 = rows[1][2]; + real_t m20 = rows[2][0]; + real_t m21 = rows[2][1]; + real_t m22 = rows[2][2]; + + p_values[0] = src[0]; + p_values[1] = m11 * src[1] - m12 * src[2] + m10 * src[3]; + p_values[2] = -m21 * src[1] + m22 * src[2] - m20 * src[3]; + p_values[3] = m01 * src[1] - m02 * src[2] + m00 * src[3]; + + real_t sh0 = src[7] + src[8] + src[8] - src[5]; + real_t sh1 = src[4] + s_rc2 * src[6] + src[7] + src[8]; + real_t sh2 = src[4]; + real_t sh3 = -src[7]; + real_t sh4 = -src[5]; + + // Rotations. R0 and R1 just use the raw matrix columns + real_t r2x = m00 + m01; + real_t r2y = m10 + m11; + real_t r2z = m20 + m21; + + real_t r3x = m00 + m02; + real_t r3y = m10 + m12; + real_t r3z = m20 + m22; + + real_t r4x = m01 + m02; + real_t r4y = m11 + m12; + real_t r4z = m21 + m22; + + // dense matrix multiplication one column at a time + + // column 0 + real_t sh0_x = sh0 * m00; + real_t sh0_y = sh0 * m10; + real_t d0 = sh0_x * m10; + real_t d1 = sh0_y * m20; + real_t d2 = sh0 * (m20 * m20 + s_c4_div_c3); + real_t d3 = sh0_x * m20; + real_t d4 = sh0_x * m00 - sh0_y * m10; + + // column 1 + real_t sh1_x = sh1 * m02; + real_t sh1_y = sh1 * m12; + d0 += sh1_x * m12; + d1 += sh1_y * m22; + d2 += sh1 * (m22 * m22 + s_c4_div_c3); + d3 += sh1_x * m22; + d4 += sh1_x * m02 - sh1_y * m12; + + // column 2 + real_t sh2_x = sh2 * r2x; + real_t sh2_y = sh2 * r2y; + d0 += sh2_x * r2y; + d1 += sh2_y * r2z; + d2 += sh2 * (r2z * r2z + s_c4_div_c3_x2); + d3 += sh2_x * r2z; + d4 += sh2_x * r2x - sh2_y * r2y; + + // column 3 + real_t sh3_x = sh3 * r3x; + real_t sh3_y = sh3 * r3y; + d0 += sh3_x * r3y; + d1 += sh3_y * r3z; + d2 += sh3 * (r3z * r3z + s_c4_div_c3_x2); + d3 += sh3_x * r3z; + d4 += sh3_x * r3x - sh3_y * r3y; + + // column 4 + real_t sh4_x = sh4 * r4x; + real_t sh4_y = sh4 * r4y; + d0 += sh4_x * r4y; + d1 += sh4_y * r4z; + d2 += sh4 * (r4z * r4z + s_c4_div_c3_x2); + d3 += sh4_x * r4z; + d4 += sh4_x * r4x - sh4_y * r4y; + + // extra multipliers + p_values[4] = d0; + p_values[5] = -d1; + p_values[6] = d2 * s_scale_dst2; + p_values[7] = -d3; + p_values[8] = d4 * s_scale_dst4; +} + +Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) { +#ifdef MATH_CHECKS + ERR_FAIL_COND_V_MSG(p_target.is_equal_approx(Vector3()), Basis(), "The target vector can't be zero."); + ERR_FAIL_COND_V_MSG(p_up.is_equal_approx(Vector3()), Basis(), "The up vector can't be zero."); +#endif + Vector3 v_z = -p_target.normalized(); + Vector3 v_x = p_up.cross(v_z); +#ifdef MATH_CHECKS + ERR_FAIL_COND_V_MSG(v_x.is_equal_approx(Vector3()), Basis(), "The target vector and up vector can't be parallel to each other."); +#endif + v_x.normalize(); + Vector3 v_y = v_z.cross(v_x); + + Basis basis; + basis.set_columns(v_x, v_y, v_z); + return basis; +} + diff --git a/core/math/basis.h b/core/math/basis.h index 871199cce..25c375181 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -42,11 +42,11 @@ public: Vector3(0, 0, 1) }; - _FORCE_INLINE_ const Vector3 &operator[](int axis) const { - return rows[axis]; + _FORCE_INLINE_ const Vector3 &operator[](int p_row) const { + return rows[p_row]; } - _FORCE_INLINE_ Vector3 &operator[](int axis) { - return rows[axis]; + _FORCE_INLINE_ Vector3 &operator[](int p_row) { + return rows[p_row]; } void invert(); @@ -59,17 +59,6 @@ public: void from_z(const Vector3 &p_z); - _FORCE_INLINE_ Vector3 get_axis(int p_axis) const { - // get actual basis axis (rows is transposed for performance) - return Vector3(rows[0][p_axis], rows[1][p_axis], rows[2][p_axis]); - } - _FORCE_INLINE_ void set_axis(int p_axis, const Vector3 &p_value) { - // get actual basis axis (rows is transposed for performance) - rows[0][p_axis] = p_value.x; - rows[1][p_axis] = p_value.y; - rows[2][p_axis] = p_value.z; - } - void rotate(const Vector3 &p_axis, real_t p_phi); Basis rotated(const Vector3 &p_axis, real_t p_phi) const; @@ -82,10 +71,15 @@ public: void rotate(const Quaternion &p_quat); Basis rotated(const Quaternion &p_quat) const; + _FORCE_INLINE_ void rotatev(const Vector3 &p_euler) { rotate(p_euler); } + _FORCE_INLINE_ Basis rotatedv(const Vector3 &p_euler) const { return rotated(p_euler); } + _FORCE_INLINE_ void rotateq(const Quaternion &p_quat) { rotate(p_quat); } + _FORCE_INLINE_ Basis rotatedq(const Quaternion &p_quat) const { return rotated(p_quat); } + Vector3 get_rotation_euler() const; void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const; void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const; - Quaternion get_rotation_quat() const; + Quaternion get_rotation_quaternion() const; Vector3 get_rotation() const { return get_rotation_euler(); }; void rotate_to_align(Vector3 p_start_direction, Vector3 p_end_direction); @@ -110,12 +104,12 @@ public: Vector3 get_euler_zyx() const; void set_euler_zyx(const Vector3 &p_euler); - Quaternion get_quat() const; - void set_quat(const Quaternion &p_quat); - Vector3 get_euler() const { return get_euler_yxz(); } void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); } + Quaternion get_quaternion() const; + void set_quaternion(const Quaternion &p_quat); + void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const; void set_axis_angle(const Vector3 &p_axis, real_t p_phi); @@ -125,13 +119,19 @@ public: void scale_local(const Vector3 &p_scale); Basis scaled_local(const Vector3 &p_scale) const; + void scale_orthogonal(const Vector3 &p_scale); + Basis scaled_orthogonal(const Vector3 &p_scale) const; + + void make_scale_uniform(); + float get_uniform_scale() const; + Vector3 get_scale() const; Vector3 get_scale_abs() const; Vector3 get_scale_local() const; void set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale); void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale); - void set_quat_scale(const Quaternion &p_quat, const Vector3 &p_scale); + void set_quaternion_scale(const Quaternion &p_quat, const Vector3 &p_scale); // transposed dot products _FORCE_INLINE_ real_t tdotx(const Vector3 &v) const { @@ -145,8 +145,6 @@ public: } bool is_equal_approx(const Basis &p_basis) const; - // For complicated reasons, the second argument is always discarded. See #45062. - bool is_equal_approx(const Basis &a, const Basis &b) const { return is_equal_approx(a); } bool is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon = UNIT_EPSILON) const; bool operator==(const Basis &p_matrix) const; @@ -178,6 +176,7 @@ public: Basis slerp(const Basis &p_to, const real_t &p_weight) const; _FORCE_INLINE_ Basis lerp(const Basis &p_to, const real_t &p_weight) const; + void rotate_sh(real_t *p_values); operator String() const; @@ -195,10 +194,11 @@ public: rows[2][2] = zz; } _FORCE_INLINE_ void set(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) { - set_axis(0, p_x); - set_axis(1, p_y); - set_axis(2, p_z); + set_column(0, p_x); + set_column(1, p_y); + set_column(2, p_z); } + _FORCE_INLINE_ Vector3 get_column(int i) const { return Vector3(rows[0][i], rows[1][i], rows[2][i]); } @@ -210,19 +210,36 @@ public: rows[2][p_index] = p_value.z; } + _FORCE_INLINE_ void set_columns(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) { + set_column(0, p_x); + set_column(1, p_y); + set_column(2, p_z); + } + _FORCE_INLINE_ Vector3 get_row(int i) const { return Vector3(rows[i][0], rows[i][1], rows[i][2]); } - _FORCE_INLINE_ Vector3 get_main_diagonal() const { - return Vector3(rows[0][0], rows[1][1], rows[2][2]); - } - _FORCE_INLINE_ void set_row(int i, const Vector3 &p_row) { rows[i][0] = p_row.x; rows[i][1] = p_row.y; rows[i][2] = p_row.z; } + _FORCE_INLINE_ Vector3 get_axis(int i) const { + return Vector3(rows[0][i], rows[1][i], rows[2][i]); + } + + _FORCE_INLINE_ void set_axis(int p_index, const Vector3 &p_value) { + // Set actual basis axis column (we store transposed as rows for performance). + rows[0][p_index] = p_value.x; + rows[1][p_index] = p_value.y; + rows[2][p_index] = p_value.z; + } + + _FORCE_INLINE_ Vector3 get_main_diagonal() const { + return Vector3(rows[0][0], rows[1][1], rows[2][2]); + } + _FORCE_INLINE_ void set_zero() { rows[0].zero(); rows[1].zero(); @@ -248,6 +265,9 @@ public: void orthonormalize(); Basis orthonormalized() const; + void orthogonalize(); + Basis orthogonalized() const; + bool is_symmetric() const; Basis diagonalize(); @@ -265,10 +285,13 @@ public: // only be used in cases of single normals, or when the basis changes each time. Vector3 xform_normal(const Vector3 &p_vector) const { return get_normal_xform_basis().xform_normal_fast(p_vector); } - operator Quaternion() const { return get_quat(); } + static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); + static Basis from_scale(const Vector3 &p_scale); - Basis(const Quaternion &p_quat) { set_quat(p_quat); } - Basis(const Quaternion &p_quat, const Vector3 &p_scale) { set_quat_scale(p_quat, p_scale); } + operator Quaternion() const { return get_quaternion(); } + + Basis(const Quaternion &p_quat) { set_quaternion(p_quat); } + Basis(const Quaternion &p_quat, const Vector3 &p_scale) { set_quaternion_scale(p_quat, p_scale); } Basis(const Vector3 &p_euler) { set_euler(p_euler); } Basis(const Vector3 &p_euler, const Vector3 &p_scale) { set_euler_scale(p_euler, p_scale); } diff --git a/core/math/transform.cpp b/core/math/transform.cpp index f79a599f1..3a36847a3 100644 --- a/core/math/transform.cpp +++ b/core/math/transform.cpp @@ -112,15 +112,15 @@ Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) /* not sure if very "efficient" but good enough? */ Vector3 src_scale = basis.get_scale(); - Quaternion src_rot = basis.get_rotation_quat(); + Quaternion src_rot = basis.get_rotation_quaternion(); Vector3 src_loc = origin; Vector3 dst_scale = p_transform.basis.get_scale(); - Quaternion dst_rot = p_transform.basis.get_rotation_quat(); + Quaternion dst_rot = p_transform.basis.get_rotation_quaternion(); Vector3 dst_loc = p_transform.origin; Transform interp; - interp.basis.set_quat_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.linear_interpolate(dst_scale, p_c)); + interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.linear_interpolate(dst_scale, p_c)); interp.origin = src_loc.linear_interpolate(dst_loc, p_c); return interp; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 39d45bfff..785d2867c 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1109,13 +1109,24 @@ struct _VariantCall { } } + VCALL_PTR0(Basis, invert); VCALL_PTR0R(Basis, inverse); + VCALL_PTR0(Basis, transpose); VCALL_PTR0R(Basis, transposed); VCALL_PTR0R(Basis, determinant); + VCALL_PTR1(Basis, from_z); + VCALL_PTR2(Basis, rotate); VCALL_PTR2R(Basis, rotated); - VCALL_PTR1R(Basis, scaled); - VCALL_PTR0R(Basis, get_scale); - VCALL_PTR0R(Basis, get_euler); + VCALL_PTR2(Basis, rotate_local); + VCALL_PTR2R(Basis, rotated_local); + VCALL_PTR1(Basis, rotatev); + VCALL_PTR1R(Basis, rotatedv); + VCALL_PTR1(Basis, rotateq); + VCALL_PTR1R(Basis, rotatedq); + VCALL_PTR0R(Basis, get_rotation_euler); + VCALL_PTR0R(Basis, get_rotation_quaternion); + VCALL_PTR0R(Basis, get_rotation); + VCALL_PTR2(Basis, rotate_to_align); VCALL_PTR0R(Basis, get_euler_xyz); VCALL_PTR1(Basis, set_euler_xyz); VCALL_PTR0R(Basis, get_euler_xzy); @@ -1128,14 +1139,53 @@ struct _VariantCall { VCALL_PTR1(Basis, set_euler_zxy); VCALL_PTR0R(Basis, get_euler_zyx); VCALL_PTR1(Basis, set_euler_zyx); + VCALL_PTR0R(Basis, get_euler); + VCALL_PTR1(Basis, set_euler); + VCALL_PTR0R(Basis, get_quaternion); + VCALL_PTR1(Basis, set_quaternion); + VCALL_PTR1(Basis, scale); + VCALL_PTR1R(Basis, scaled); + VCALL_PTR1(Basis, scale_local); + VCALL_PTR1R(Basis, scaled_local); + VCALL_PTR1(Basis, scale_orthogonal); + VCALL_PTR1R(Basis, scaled_orthogonal); + VCALL_PTR0(Basis, make_scale_uniform); + VCALL_PTR0R(Basis, get_uniform_scale); + VCALL_PTR0R(Basis, get_scale); + VCALL_PTR0R(Basis, get_scale_abs); + VCALL_PTR0R(Basis, get_scale_local); + VCALL_PTR3(Basis, set_axis_angle_scale); + VCALL_PTR2(Basis, set_euler_scale); + VCALL_PTR2(Basis, set_quaternion_scale); VCALL_PTR1R(Basis, tdotx); VCALL_PTR1R(Basis, tdoty); VCALL_PTR1R(Basis, tdotz); + VCALL_PTR1R(Basis, is_equal_approx); + VCALL_PTR3R(Basis, is_equal_approx_ratio); VCALL_PTR0R(Basis, get_orthogonal_index); - VCALL_PTR0R(Basis, orthonormalized); + VCALL_PTR1(Basis, set_orthogonal_index); + VCALL_PTR1(Basis, set_diagonal); + VCALL_PTR0(Basis, is_orthogonal); + VCALL_PTR0(Basis, is_diagonal); + VCALL_PTR0(Basis, is_rotation); VCALL_PTR2R(Basis, slerp); - VCALL_PTR2R(Basis, is_equal_approx); - VCALL_PTR0R(Basis, get_rotation_quat); + VCALL_PTR2R(Basis, lerp); + VCALL_PTR1R(Basis, get_column); + VCALL_PTR2(Basis, set_column); + VCALL_PTR3(Basis, set_columns); + VCALL_PTR1R(Basis, get_row); + VCALL_PTR2(Basis, set_row); + VCALL_PTR1R(Basis, get_axis); + VCALL_PTR2(Basis, set_axis); + VCALL_PTR0R(Basis, get_main_diagonal); + VCALL_PTR0(Basis, set_zero); + VCALL_PTR1R(Basis, transpose_xform); + VCALL_PTR0(Basis, orthonormalize); + VCALL_PTR0R(Basis, orthonormalized); + VCALL_PTR0(Basis, orthogonalize); + VCALL_PTR0R(Basis, orthogonalized); + VCALL_PTR0R(Basis, is_symmetric); + VCALL_PTR0R(Basis, diagonalize); static void _call_Basis_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { switch (p_args[0]->type) { @@ -1338,9 +1388,9 @@ struct _VariantCall { static void Basis_init1(Variant &r_ret, const Variant **p_args) { Basis m; - m.set_axis(0, *p_args[0]); - m.set_axis(1, *p_args[1]); - m.set_axis(2, *p_args[2]); + m.set_column(0, *p_args[0]); + m.set_column(1, *p_args[1]); + m.set_column(2, *p_args[2]); r_ret = m; } @@ -1350,9 +1400,9 @@ struct _VariantCall { static void Transform_init1(Variant &r_ret, const Variant **p_args) { Transform t; - t.basis.set_axis(0, *p_args[0]); - t.basis.set_axis(1, *p_args[1]); - t.basis.set_axis(2, *p_args[2]); + t.basis.set_column(0, *p_args[0]); + t.basis.set_column(1, *p_args[1]); + t.basis.set_column(2, *p_args[2]); t.origin = *p_args[3]; r_ret = t; } @@ -2543,24 +2593,85 @@ void register_variant_methods() { ADDFUNC2R(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray()); ADDFUNC1R(TRANSFORM2D, BOOL, Transform2D, is_equal_approx, TRANSFORM2D, "transform", varray()); + ADDFUNC0(BASIS, NIL, Basis, invert, varray()); ADDFUNC0R(BASIS, BASIS, Basis, inverse, varray()); + ADDFUNC0(BASIS, NIL, Basis, transpose, varray()); ADDFUNC0R(BASIS, BASIS, Basis, transposed, varray()); - ADDFUNC0R(BASIS, BASIS, Basis, orthonormalized, varray()); ADDFUNC0R(BASIS, REAL, Basis, determinant, varray()); + ADDFUNC1(BASIS, NIL, Basis, from_z, VECTOR3, "z", varray()); + ADDFUNC2(BASIS, NIL, Basis, rotate, VECTOR3, "axis", REAL, "phi", varray()); ADDFUNC2R(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray()); - ADDFUNC1R(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray()); - ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale, varray()); + ADDFUNC2(BASIS, NIL, Basis, rotate_local, VECTOR3, "axis", REAL, "phi", varray()); + ADDFUNC2R(BASIS, BASIS, Basis, rotate_local, VECTOR3, "axis", REAL, "phi", varray()); + ADDFUNC1(BASIS, NIL, Basis, rotatev, VECTOR3, "euler", varray()); + ADDFUNC1R(BASIS, BASIS, Basis, rotatedv, VECTOR3, "euler", varray()); + ADDFUNC1(BASIS, NIL, Basis, rotateq, QUATERNION, "quat", varray()); + ADDFUNC1R(BASIS, BASIS, Basis, rotatedq, QUATERNION, "quat", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_rotation_euler, varray()); + ADDFUNC0R(BASIS, QUATERNION, Basis, get_rotation_quaternion, varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_rotation, varray()); + ADDFUNC2(BASIS, NIL, Basis, rotate_to_align, VECTOR3, "direction", VECTOR3, "end_direction", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler_xyz, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_euler_xyz, VECTOR3, "euler", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler_xzy, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_euler_xzy, VECTOR3, "euler", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler_xyz, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_euler_xyz, VECTOR3, "euler", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler_yxz, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_euler_yxz, VECTOR3, "euler", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler_zxy, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_euler_zxy, VECTOR3, "euler", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler_zyx, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_euler_zyx, VECTOR3, "euler", varray()); ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_euler, VECTOR3, "euler", varray()); + ADDFUNC0R(BASIS, QUATERNION, Basis, get_quaternion, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_quaternion, QUATERNION, "quaternion", varray()); + ADDFUNC1(BASIS, NIL, Basis, scale, VECTOR3, "scale", varray()); + ADDFUNC1R(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray()); + ADDFUNC1(BASIS, NIL, Basis, scale_local, VECTOR3, "scale", varray()); + ADDFUNC1R(BASIS, BASIS, Basis, scaled_local, VECTOR3, "scale", varray()); + ADDFUNC1(BASIS, NIL, Basis, scale_orthogonal, VECTOR3, "scale", varray()); + ADDFUNC1R(BASIS, BASIS, Basis, scaled_orthogonal, VECTOR3, "scale", varray()); + ADDFUNC0(BASIS, NIL, Basis, make_scale_uniform, varray()); + ADDFUNC0R(BASIS, REAL, Basis, get_uniform_scale, varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale, varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale_abs, varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale_local, varray()); + ADDFUNC3(BASIS, NIL, Basis, set_axis_angle_scale, VECTOR3, "axis", REAL, "phi", VECTOR3, "scale", varray()); + ADDFUNC2(BASIS, NIL, Basis, set_euler_scale, VECTOR3, "euler", VECTOR3, "scale", varray()); + ADDFUNC2(BASIS, NIL, Basis, set_quaternion_scale, QUATERNION, "quat", VECTOR3, "scale", varray()); ADDFUNC1R(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray()); ADDFUNC1R(BASIS, REAL, Basis, tdoty, VECTOR3, "with", varray()); ADDFUNC1R(BASIS, REAL, Basis, tdotz, VECTOR3, "with", varray()); - ADDFUNC1R(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray()); - ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray()); + ADDFUNC1R(BASIS, BOOL, Basis, is_equal_approx, BASIS, "b", varray()); + ADDFUNC2R(BASIS, BOOL, Basis, is_equal_approx_ratio, BASIS, "b", REAL, "epsilon", varray(CMP_EPSILON)); ADDFUNC0R(BASIS, INT, Basis, get_orthogonal_index, varray()); + ADDFUNC1(BASIS, NIL, Basis, set_orthogonal_index, INT, "index", varray()); + ADDFUNC1(BASIS, NIL, Basis, set_diagonal, VECTOR3, "diag", varray()); + ADDFUNC0R(BASIS, BOOL, Basis, is_orthogonal, varray()); + ADDFUNC0R(BASIS, BOOL, Basis, is_diagonal, varray()); + ADDFUNC0R(BASIS, BOOL, Basis, is_rotation, varray()); ADDFUNC2R(BASIS, BASIS, Basis, slerp, BASIS, "to", REAL, "weight", varray()); - // For complicated reasons, the epsilon argument is always discarded. See #45062. - ADDFUNC2R(BASIS, BOOL, Basis, is_equal_approx, BASIS, "b", REAL, "epsilon", varray(CMP_EPSILON)); - ADDFUNC0R(BASIS, QUATERNION, Basis, get_rotation_quat, varray()); + ADDFUNC2R(BASIS, BASIS, Basis, lerp, BASIS, "to", REAL, "weight", varray()); + ADDFUNC1(BASIS, VECTOR3, Basis, get_column, INT, "i", varray()); + ADDFUNC2(BASIS, NIL, Basis, set_column, INT, "index", VECTOR3, "value", varray()); + ADDFUNC3(BASIS, NIL, Basis, set_columns, VECTOR3, "x", VECTOR3, "y", VECTOR3, "z", varray()); + ADDFUNC1(BASIS, VECTOR3, Basis, get_row, INT, "i", varray()); + ADDFUNC2(BASIS, NIL, Basis, set_row, INT, "i", VECTOR3, "axis", varray()); + ADDFUNC1(BASIS, VECTOR3, Basis, get_axis, INT, "i", varray()); + ADDFUNC2(BASIS, NIL, Basis, set_axis, INT, "i", VECTOR3, "axis", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_main_diagonal, varray()); + ADDFUNC0(BASIS, NIL, Basis, set_zero, varray()); + ADDFUNC1R(BASIS, BASIS, Basis, transpose_xform, BASIS, "m", varray()); + ADDFUNC0(BASIS, NIL, Basis, orthonormalize, varray()); + ADDFUNC0R(BASIS, BASIS, Basis, orthonormalized, varray()); + ADDFUNC0(BASIS, NIL, Basis, orthogonalize, varray()); + ADDFUNC0R(BASIS, BASIS, Basis, orthogonalized, varray()); + ADDFUNC0R(BASIS, BOOL, Basis, is_symmetric, varray()); + ADDFUNC0R(BASIS, BASIS, Basis, diagonalize, varray()); + ADDFUNC1R(BASIS, VECTOR3, Basis, xform, NIL, "v3_or_v3i", varray()); + ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, NIL, "v3_or_v3i", varray()); ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, inverse, varray()); ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray()); diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml index 5f2566b79..d9c64e603 100644 --- a/doc/classes/Basis.xml +++ b/doc/classes/Basis.xml @@ -62,7 +62,7 @@ Returns the basis's rotation in the form of Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last). The returned vector contains the rotation angles in the format (X angle, Y angle, Z angle). - Consider using the [method get_rotation_quat] method instead, which returns a [Quaternion] quaternion instead of Euler angles. + Consider using the [method get_rotation_quaternion] method instead, which returns a [Quaternion] quaternion instead of Euler angles. @@ -71,7 +71,7 @@ This function considers a discretization of rotations into 24 points on unit sphere, lying along the vectors (x,y,z) with each component being either -1, 0, or 1, and returns the index of the point best representing the orientation of the object. It is mainly used by the [GridMap] editor. For further details, refer to the Godot source code. - + Returns the basis's rotation in the form of a quaternion. See [method get_euler] if you need Euler angles, but keep in mind quaternions should generally be preferred to Euler angles. diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index fd5a3584e..496b9d45b 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -358,7 +358,7 @@ void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Tran } AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_POSITION_3D, p_key.origin); - AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_ROTATION_3D, p_key.basis.get_rotation_quat()); + AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_ROTATION_3D, p_key.basis.get_rotation_quaternion()); AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_SCALE_3D, p_key.basis.get_scale()); } diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index f08353ef7..4daf824c2 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -634,7 +634,7 @@ Error GLTFDocument::_parse_nodes(Ref state) { node->scale = _arr_to_vec3(n["scale"]); } - node->xform.basis.set_quat_scale(node->rotation, node->scale); + node->xform.basis.set_quaternion_scale(node->rotation, node->scale); node->xform.origin = node->translation; } @@ -5277,7 +5277,7 @@ GLTFLightIndex GLTFDocument::_convert_light(Ref state, Light *p_light void GLTFDocument::_convert_spatial(Ref state, Spatial *p_spatial, Ref p_node) { Transform xform = p_spatial->get_transform(); p_node->scale = xform.basis.get_scale(); - p_node->rotation = xform.basis.get_rotation_quat(); + p_node->rotation = xform.basis.get_rotation_quaternion(); p_node->translation = xform.origin; } @@ -5402,7 +5402,7 @@ void GLTFDocument::_convert_mult_mesh_instance_to_gltf(MultiMeshInstance *p_mult real_t rotation = xform_2d.get_rotation(); Quaternion quat(Vector3(0, 1, 0), rotation); Size2 scale = xform_2d.get_scale(); - transform.basis.set_quat_scale(quat, + transform.basis.set_quaternion_scale(quat, Vector3(scale.x, 0, scale.y)); transform = p_multi_mesh_instance->get_transform() * transform; @@ -5453,7 +5453,7 @@ void GLTFDocument::_convert_skeleton_to_gltf(Skeleton *p_skeleton3d, Refset_name(_gen_unique_name(state, skeleton->get_bone_name(bone_i))); Transform xform = skeleton->get_bone_pose(bone_i); joint_node->scale = xform.basis.get_scale(); - joint_node->rotation = xform.basis.get_rotation_quat(); + joint_node->rotation = xform.basis.get_rotation_quaternion(); joint_node->translation = xform.origin; joint_node->joint = true; GLTFNodeIndex current_node_i = state->nodes.size(); @@ -6032,7 +6032,7 @@ void GLTFDocument::_convert_mesh_instances(Ref state) { ERR_CONTINUE(!mi); Transform mi_xform = mi->get_transform(); node->scale = mi_xform.basis.get_scale(); - node->rotation = mi_xform.basis.get_rotation_quat(); + node->rotation = mi_xform.basis.get_rotation_quaternion(); node->translation = mi_xform.origin; Skeleton *skeleton = Object::cast_to(mi->get_node(mi->get_skeleton_path())); diff --git a/modules/skeleton_editor/skeleton_editor_plugin.cpp b/modules/skeleton_editor/skeleton_editor_plugin.cpp index 4983923ea..5b49be1c9 100644 --- a/modules/skeleton_editor/skeleton_editor_plugin.cpp +++ b/modules/skeleton_editor/skeleton_editor_plugin.cpp @@ -330,7 +330,7 @@ void SkeletonEditor::init_pose(const bool p_all_bones) { for (int i = 0; i < bone_len; i++) { Transform rest = skeleton->get_bone_rest(i); ur->add_do_method(skeleton, "set_bone_pose_position", i, rest.origin); - ur->add_do_method(skeleton, "set_bone_pose_rotation", i, rest.basis.get_rotation_quat()); + ur->add_do_method(skeleton, "set_bone_pose_rotation", i, rest.basis.get_rotation_quaternion()); ur->add_do_method(skeleton, "set_bone_pose_scale", i, rest.basis.get_scale()); ur->add_undo_method(skeleton, "set_bone_pose_position", i, skeleton->get_bone_pose_position(i)); ur->add_undo_method(skeleton, "set_bone_pose_rotation", i, skeleton->get_bone_pose_rotation(i)); @@ -344,7 +344,7 @@ void SkeletonEditor::init_pose(const bool p_all_bones) { } Transform rest = skeleton->get_bone_rest(selected_bone); ur->add_do_method(skeleton, "set_bone_pose_position", selected_bone, rest.origin); - ur->add_do_method(skeleton, "set_bone_pose_rotation", selected_bone, rest.basis.get_rotation_quat()); + ur->add_do_method(skeleton, "set_bone_pose_rotation", selected_bone, rest.basis.get_rotation_quaternion()); ur->add_do_method(skeleton, "set_bone_pose_scale", selected_bone, rest.basis.get_scale()); ur->add_undo_method(skeleton, "set_bone_pose_position", selected_bone, skeleton->get_bone_pose_position(selected_bone)); ur->add_undo_method(skeleton, "set_bone_pose_rotation", selected_bone, skeleton->get_bone_pose_rotation(selected_bone)); @@ -1488,7 +1488,7 @@ void SkeletonGizmoPlugin::set_subgizmo_transform(const EditorSpatialGizmo *p_giz // Apply transform. skeleton->set_bone_pose_position(p_id, t.origin); - skeleton->set_bone_pose_rotation(p_id, t.basis.get_rotation_quat()); + skeleton->set_bone_pose_rotation(p_id, t.basis.get_rotation_quaternion()); skeleton->set_bone_pose_scale(p_id, t.basis.get_scale()); } diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 3004ddc3d..b9028221a 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -734,7 +734,7 @@ void Skeleton::set_bone_pose(int p_bone, const Transform &p_pose) { ERR_FAIL_INDEX(p_bone, bone_size); bones.write[p_bone].pose_position = p_pose.origin; - bones.write[p_bone].pose_rotation = p_pose.basis.get_rotation_quat(); + bones.write[p_bone].pose_rotation = p_pose.basis.get_rotation_quaternion(); bones.write[p_bone].pose_scale = p_pose.basis.get_scale(); bones.write[p_bone].pose_cache_dirty = true; diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index db006028d..cac67186e 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -88,7 +88,7 @@ private: _FORCE_INLINE_ void update_pose_cache() { if (pose_cache_dirty) { - pose_cache.basis.set_quat_scale(pose_rotation, pose_scale); + pose_cache.basis.set_quaternion_scale(pose_rotation, pose_scale); pose_cache.origin = pose_position; pose_cache_dirty = false; } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 37c12c518..bebc10d5f 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -325,7 +325,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov } Transform rest = node_cache->skeleton->get_bone_rest(bone_idx); node_cache->init_loc = rest.origin; - node_cache->init_rot = rest.basis.get_rotation_quat(); + node_cache->init_rot = rest.basis.get_rotation_quaternion(); node_cache->init_scale = rest.basis.get_scale(); } else { // no property, just use spatialnode diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 019c0d4fd..c04dac777 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -639,7 +639,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_xform->bone_idx = bone_idx; Transform rest = sk->get_bone_rest(bone_idx); track_xform->init_loc = rest.origin; - track_xform->ref_rot = rest.basis.get_rotation_quat(); + track_xform->ref_rot = rest.basis.get_rotation_quaternion(); track_xform->init_rot = track_xform->ref_rot.log(); track_xform->init_scale = rest.basis.get_scale(); } @@ -1477,7 +1477,7 @@ void AnimationTree::_process_graph(float p_delta) { if (t->root_motion) { Transform xform; xform.origin = t->loc; - xform.basis.set_quat_scale(t->rot, t->scale); + xform.basis.set_quaternion_scale(t->rot, t->scale); root_motion_transform = xform; } else if (t->skeleton && t->bone_idx >= 0) {