Backported some improvements to Transform2D from Godot4. Also bound all eligible methods.

This commit is contained in:
Relintai 2022-08-14 19:19:51 +02:00
parent e4cad690a3
commit e9bb723975
3 changed files with 190 additions and 19 deletions

View File

@ -82,6 +82,16 @@ void Transform2D::set_rotation(real_t p_rot) {
set_scale(scale);
}
real_t Transform2D::get_skew() const {
real_t det = basis_determinant();
return Math::acos(columns[0].normalized().dot(SGN(det) * columns[1].normalized())) - (real_t)Math_PI * 0.5f;
}
void Transform2D::set_skew(const real_t p_angle) {
real_t det = basis_determinant();
columns[1] = SGN(det) * columns[0].rotated(((real_t)Math_PI * 0.5f + p_angle)).normalized() * columns[1].length();
}
Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
real_t cr = Math::cos(p_rot);
real_t sr = Math::sin(p_rot);
@ -92,6 +102,14 @@ Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
columns[2] = p_pos;
}
Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos) {
columns[0][0] = Math::cos(p_rot) * p_scale.x;
columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
columns[0][1] = Math::sin(p_rot) * p_scale.x;
columns[2] = p_pos;
}
Size2 Transform2D::get_scale() const {
real_t det_sign = SGN(basis_determinant());
return Size2(columns[0].length(), det_sign * columns[1].length());
@ -114,6 +132,14 @@ void Transform2D::scale_basis(const Size2 &p_scale) {
columns[1][0] *= p_scale.x;
columns[1][1] *= p_scale.y;
}
void Transform2D::translate(real_t p_tx, real_t p_ty) {
translate(Vector2(p_tx, p_ty));
}
void Transform2D::translate(const Vector2 &p_offset) {
columns[2] += p_offset;
}
void Transform2D::translate_local(real_t p_tx, real_t p_ty) {
translate_local(Vector2(p_tx, p_ty));
}
@ -121,6 +147,20 @@ void Transform2D::translate_local(const Vector2 &p_translation) {
columns[2] += basis_xform(p_translation);
}
void Transform2D::translater(real_t p_tx, real_t p_ty) {
translate(Vector2(p_tx, p_ty));
}
void Transform2D::translatev(const Vector2 &p_offset) {
columns[2] += p_offset;
}
void Transform2D::translate_localr(real_t p_tx, real_t p_ty) {
translate_local(Vector2(p_tx, p_ty));
}
void Transform2D::translate_localv(const Vector2 &p_translation) {
columns[2] += basis_xform(p_translation);
}
void Transform2D::orthonormalize() {
// Gram-Schmidt Process
@ -145,6 +185,13 @@ bool Transform2D::is_equal_approx(const Transform2D &p_transform) const {
return columns[0].is_equal_approx(p_transform.columns[0]) && columns[1].is_equal_approx(p_transform.columns[1]) && columns[2].is_equal_approx(p_transform.columns[2]);
}
Transform2D Transform2D::looking_at(const Vector2 &p_target) const {
Transform2D return_trans = Transform2D(get_rotation(), get_origin());
Vector2 target_position = affine_inverse().xform(p_target);
return_trans.set_rotation(return_trans.get_rotation() + (target_position * get_scale()).angle());
return return_trans;
}
bool Transform2D::operator==(const Transform2D &p_transform) const {
for (int i = 0; i < 3; i++) {
if (columns[i] != p_transform.columns[i]) {
@ -187,10 +234,16 @@ Transform2D Transform2D::operator*(const Transform2D &p_transform) const {
return t;
}
Transform2D Transform2D::scaled(const Size2 &p_scale) const {
Transform2D copy = *this;
copy.scale(p_scale);
return copy;
void Transform2D::operator*=(const real_t p_val) {
columns[0] *= p_val;
columns[1] *= p_val;
columns[2] *= p_val;
}
Transform2D Transform2D::operator*(const real_t p_val) const {
Transform2D ret(*this);
ret *= p_val;
return ret;
}
Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
@ -199,21 +252,42 @@ Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
return copy;
}
Transform2D Transform2D::scaled(const Size2 &p_scale) const {
// Equivalent to left multiplication
Transform2D copy = *this;
copy.scale(p_scale);
return copy;
}
Transform2D Transform2D::scaled_local(const Size2 &p_scale) const {
// Equivalent to right multiplication
return Transform2D(columns[0] * p_scale.x, columns[1] * p_scale.y, columns[2]);
}
Transform2D Transform2D::untranslated() const {
Transform2D copy = *this;
copy.columns[2] = Vector2();
return copy;
}
Transform2D Transform2D::translated(const Vector2 &p_offset) const {
// Equivalent to left multiplication
return Transform2D(columns[0], columns[1], columns[2] + p_offset);
}
Transform2D Transform2D::translated_local(const Vector2 &p_offset) const {
// Equivalent to right multiplication
return Transform2D(columns[0], columns[1], columns[2] + basis_xform(p_offset));
}
Transform2D Transform2D::rotated(real_t p_phi) const {
Transform2D copy = *this;
copy.rotate(p_phi);
return copy;
Transform2D Transform2D::rotated(const real_t p_angle) const {
// Equivalent to left multiplication
return Transform2D(p_angle, Vector2()) * (*this);
}
Transform2D Transform2D::rotated_local(const real_t p_angle) const {
// Equivalent to right multiplication
return (*this) * Transform2D(p_angle, Vector2()); // Could be optimized, because origin transform can be skipped.
}
real_t Transform2D::basis_determinant() const {

View File

@ -63,6 +63,15 @@ struct _NO_DISCARD_CLASS_ Transform2D {
columns[p_axis] = p_vec;
}
_FORCE_INLINE_ Vector2 get_column(int p_colum) const {
ERR_FAIL_INDEX_V(p_colum, 3, Vector2());
return columns[p_colum];
}
_FORCE_INLINE_ void set_column(int p_colum, const Vector2 &p_vec) {
ERR_FAIL_INDEX(p_colum, 3);
columns[p_colum] = p_vec;
}
void invert();
Transform2D inverse() const;
@ -71,14 +80,24 @@ struct _NO_DISCARD_CLASS_ Transform2D {
void set_rotation(real_t p_rot);
real_t get_rotation() const;
real_t get_skew() const;
void set_skew(const real_t p_angle);
_FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale);
_FORCE_INLINE_ void set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew);
void rotate(real_t p_phi);
void scale(const Size2 &p_scale);
void scale_basis(const Size2 &p_scale);
void translate(real_t p_tx, real_t p_ty);
void translate(const Vector2 &p_offset);
void translate_local(real_t p_tx, real_t p_ty);
void translate_local(const Vector2 &p_translation);
void translater(real_t p_tx, real_t p_ty);
void translatev(const Vector2 &p_offset);
void translate_localr(real_t p_tx, real_t p_ty);
void translate_localv(const Vector2 &p_translation);
real_t basis_determinant() const;
Size2 get_scale() const;
@ -87,10 +106,13 @@ struct _NO_DISCARD_CLASS_ Transform2D {
_FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; }
_FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; }
Transform2D scaled(const Size2 &p_scale) const;
Transform2D basis_scaled(const Size2 &p_scale) const;
Transform2D scaled(const Size2 &p_scale) const;
Transform2D scaled_local(const Size2 &p_scale) const;
Transform2D translated(const Vector2 &p_offset) const;
Transform2D translated_local(const Vector2 &p_offset) const;
Transform2D rotated(real_t p_phi) const;
Transform2D rotated(const real_t p_angle) const;
Transform2D rotated_local(const real_t p_angle) const;
Transform2D untranslated() const;
@ -98,11 +120,15 @@ struct _NO_DISCARD_CLASS_ Transform2D {
Transform2D orthonormalized() const;
bool is_equal_approx(const Transform2D &p_transform) const;
Transform2D looking_at(const Vector2 &p_target) const;
bool operator==(const Transform2D &p_transform) const;
bool operator!=(const Transform2D &p_transform) const;
void operator*=(const Transform2D &p_transform);
Transform2D operator*(const Transform2D &p_transform) const;
void operator*=(const real_t p_val);
Transform2D operator*(const real_t p_val) const;
Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const;
@ -142,6 +168,9 @@ struct _NO_DISCARD_CLASS_ Transform2D {
}
Transform2D(real_t p_rot, const Vector2 &p_pos);
Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos);
Transform2D() {
columns[0][0] = 1.0;
columns[1][1] = 1.0;
@ -193,6 +222,13 @@ void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
columns[0][1] = Math::sin(p_rot) * p_scale.x;
}
void Transform2D::set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew) {
columns[0][0] = Math::cos(p_rot) * p_scale.x;
columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
columns[0][1] = Math::sin(p_rot) * p_scale.x;
}
Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const {
Vector2 ends[4] = {
xform_inv(p_rect.position),

View File

@ -1071,17 +1071,47 @@ struct _VariantCall {
//VCALL_PTR0R(AABB, get_end);
VCALL_PTR0R(AABB, get_center);
VCALL_PTR1R(Transform2D, tdotx);
VCALL_PTR1R(Transform2D, tdoty);
VCALL_PTR1R(Transform2D, get_axis);
VCALL_PTR2(Transform2D, set_axis);
VCALL_PTR1R(Transform2D, get_column);
VCALL_PTR2(Transform2D, set_column);
VCALL_PTR0(Transform2D, invert);
VCALL_PTR0(Transform2D, affine_invert);
VCALL_PTR0R(Transform2D, inverse);
VCALL_PTR0R(Transform2D, affine_inverse);
VCALL_PTR1(Transform2D, set_rotation);
VCALL_PTR0R(Transform2D, get_rotation);
VCALL_PTR0R(Transform2D, get_origin);
VCALL_PTR0R(Transform2D, get_skew);
VCALL_PTR1(Transform2D, set_skew);
VCALL_PTR2(Transform2D, set_rotation_and_scale);
VCALL_PTR3(Transform2D, set_rotation_scale_and_skew);
VCALL_PTR1(Transform2D, rotate);
VCALL_PTR1(Transform2D, scale);
VCALL_PTR1(Transform2D, scale_basis);
VCALL_PTR2(Transform2D, translater);
VCALL_PTR1(Transform2D, translatev);
VCALL_PTR2(Transform2D, translate_localr);
VCALL_PTR1(Transform2D, translate_localv);
VCALL_PTR0R(Transform2D, basis_determinant);
VCALL_PTR0R(Transform2D, get_scale);
VCALL_PTR0R(Transform2D, orthonormalized);
VCALL_PTR1R(Transform2D, rotated);
VCALL_PTR1(Transform2D, set_scale);
VCALL_PTR0R(Transform2D, get_origin);
VCALL_PTR1(Transform2D, set_origin);
VCALL_PTR1R(Transform2D, basis_scaled);
VCALL_PTR1R(Transform2D, scaled);
VCALL_PTR1R(Transform2D, scaled_local);
VCALL_PTR1R(Transform2D, translated);
VCALL_PTR1R(Transform2D, translated_local);
VCALL_PTR2R(Transform2D, interpolate_with);
VCALL_PTR1R(Transform2D, rotated);
VCALL_PTR1R(Transform2D, rotated_local);
VCALL_PTR0R(Transform2D, untranslated);
VCALL_PTR0(Transform2D, orthonormalize);
VCALL_PTR0R(Transform2D, orthonormalized);
VCALL_PTR1R(Transform2D, is_equal_approx);
VCALL_PTR1R(Transform2D, looking_at);
VCALL_PTR2R(Transform2D, interpolate_with);
static void _call_Transform2D_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) {
switch (p_args[0]->type) {
@ -2631,21 +2661,52 @@ void register_variant_methods() {
//ADDFUNC0R(AABB, VECTOR3, AABB, get_end, varray());
ADDFUNC0R(AABB, VECTOR3, AABB, get_center, varray());
ADDFUNC1R(TRANSFORM2D, REAL, Transform2D, tdotx, VECTOR2, "v", varray());
ADDFUNC1R(TRANSFORM2D, REAL, Transform2D, tdoty, VECTOR2, "v", varray());
ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, get_axis, INT, "axis", varray());
ADDFUNC2(TRANSFORM2D, NIL, Transform2D, set_axis, INT, "axis", VECTOR2, "vec", varray());
ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, get_column, INT, "colum", varray());
ADDFUNC2(TRANSFORM2D, NIL, Transform2D, set_column, INT, "colum", VECTOR2, "vec", varray());
ADDFUNC0(TRANSFORM2D, NIL, Transform2D, invert, varray());
ADDFUNC0(TRANSFORM2D, NIL, Transform2D, affine_invert, varray());
ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray());
ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, set_column, REAL, "colum", varray());
ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray());
ADDFUNC0R(TRANSFORM2D, REAL, Transform2D, get_rotation, varray());
ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray());
ADDFUNC0R(TRANSFORM2D, REAL, Transform2D, get_skew, varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, set_skew, REAL, "angle", varray());
ADDFUNC2(TRANSFORM2D, NIL, Transform2D, set_rotation_and_scale, REAL, "rot", VECTOR2, "scale", varray());
ADDFUNC3(TRANSFORM2D, NIL, Transform2D, set_rotation_scale_and_skew, REAL, "rot", VECTOR2, "scale", REAL, "skew", varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, rotate, REAL, "phi", varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, scale, VECTOR2, "scale", varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, scale_basis, VECTOR2, "scale", varray());
ADDFUNC2(TRANSFORM2D, NIL, Transform2D, translater, REAL, "tx", REAL, "ty", varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, translatev, VECTOR2, "origin", varray());
ADDFUNC2(TRANSFORM2D, NIL, Transform2D, translate_localr, REAL, "tx", REAL, "ty", varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, translate_localv, VECTOR2, "translation", varray());
ADDFUNC0R(TRANSFORM2D, REAL, Transform2D, basis_determinant, varray());
ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray());
ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, set_scale, REAL, "scale", varray());
ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray());
ADDFUNC1(TRANSFORM2D, NIL, Transform2D, set_origin, REAL, "origin", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_scaled, VECTOR2, "scale", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled_local, VECTOR2, "scale", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, translated_local, VECTOR2, "offset", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "angle", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated_local, REAL, "angle", varray());
ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, untranslated, varray());
ADDFUNC0(TRANSFORM2D, NIL, Transform2D, orthonormalize, varray());
ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray());
ADDFUNC1R(TRANSFORM2D, BOOL, Transform2D, is_equal_approx, TRANSFORM2D, "transform", varray());
ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, looking_at, VECTOR2, "target", varray());
ADDFUNC2R(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray());
ADDFUNC1R(TRANSFORM2D, NIL, Transform2D, xform, NIL, "v", varray());
ADDFUNC1R(TRANSFORM2D, NIL, Transform2D, xform_inv, NIL, "v", varray());
ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, basis_xform, VECTOR2, "v", varray());
ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, basis_xform_inv, VECTOR2, "v", varray());
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());