Backported improvements to Basis from Godot4. Also bound all eligible methods.

This commit is contained in:
Relintai 2022-08-14 00:18:21 +02:00
parent d9e094ab9a
commit 170a41ca82
12 changed files with 388 additions and 83 deletions

View File

@ -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;
}

View File

@ -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); }

View File

@ -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;

View File

@ -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());

View File

@ -62,7 +62,7 @@
<return type="Vector3" />
<description>
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.
</description>
</method>
<method name="get_orthogonal_index">
@ -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.
</description>
</method>
<method name="get_rotation_quat">
<method name="get_rotation_quaternion">
<return type="Quaternion" />
<description>
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.

View File

@ -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());
}

View File

@ -634,7 +634,7 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> 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<GLTFState> state, Light *p_light
void GLTFDocument::_convert_spatial(Ref<GLTFState> state, Spatial *p_spatial, Ref<GLTFNode> 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, Ref<GLTFSta
joint_node->set_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<GLTFState> 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<Skeleton>(mi->get_node(mi->get_skeleton_path()));

View File

@ -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());
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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) {