From a3c29ed899b7d99d5ca6ed41d55e8a60a5c33343 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Fri, 26 Feb 2021 23:26:56 -0500 Subject: Rename files and the exposed name for Transform3D --- core/math/camera_matrix.h | 2 +- core/math/face3.h | 2 +- core/math/transform.cpp | 212 ----------- core/math/transform.h | 232 ------------ core/math/transform_3d.cpp | 212 +++++++++++ core/math/transform_3d.h | 232 ++++++++++++ core/variant/variant.h | 2 +- modules/bullet/bullet_types_converter.h | 2 +- modules/bullet/collision_object_bullet.h | 2 +- modules/csg/csg.h | 2 +- modules/fbx/data/pivot_transform.h | 2 +- modules/fbx/fbx_parser/FBXDeformer.cpp | 2 +- modules/fbx/fbx_parser/FBXDocument.h | 2 +- modules/fbx/fbx_parser/FBXParser.cpp | 2 +- modules/fbx/fbx_parser/FBXParser.h | 2 +- modules/gdnative/gdnative/transform.cpp | 4 +- modules/gdnative/include/gdnative/transform.h | 2 +- modules/mono/editor/bindings_generator.cpp | 4 +- .../glue/GodotSharp/GodotSharp/Core/Transform.cs | 412 --------------------- .../glue/GodotSharp/GodotSharp/Core/Transform3D.cs | 412 +++++++++++++++++++++ .../glue/GodotSharp/GodotSharp/GodotSharp.csproj | 2 +- scene/3d/skeleton_ik_3d.h | 2 +- servers/navigation_server_2d.cpp | 2 +- servers/physics_3d/joints/jacobian_entry_3d_sw.h | 2 +- tests/test_math.cpp | 2 +- 25 files changed, 877 insertions(+), 877 deletions(-) delete mode 100644 core/math/transform.cpp delete mode 100644 core/math/transform.h create mode 100644 core/math/transform_3d.cpp create mode 100644 core/math/transform_3d.h delete mode 100644 modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs create mode 100644 modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index 7576f90224..786d46055a 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -32,7 +32,7 @@ #define CAMERA_MATRIX_H #include "core/math/rect2.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" struct CameraMatrix { enum Planes { diff --git a/core/math/face3.h b/core/math/face3.h index 7335e6eff8..5091b338ef 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -33,7 +33,7 @@ #include "core/math/aabb.h" #include "core/math/plane.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/math/vector3.h" class Face3 { diff --git a/core/math/transform.cpp b/core/math/transform.cpp deleted file mode 100644 index d5a78a7749..0000000000 --- a/core/math/transform.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/*************************************************************************/ -/* transform.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "transform.h" - -#include "core/math/math_funcs.h" -#include "core/string/print_string.h" - -void Transform3D::affine_invert() { - basis.invert(); - origin = basis.xform(-origin); -} - -Transform3D Transform3D::affine_inverse() const { - Transform3D ret = *this; - ret.affine_invert(); - return ret; -} - -void Transform3D::invert() { - basis.transpose(); - 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; -} - -void Transform3D::rotate(const Vector3 &p_axis, real_t p_phi) { - *this = rotated(p_axis, p_phi); -} - -Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_phi) const { - return Transform3D(Basis(p_axis, p_phi), Vector3()) * (*this); -} - -void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_phi) { - basis.rotate(p_axis, p_phi); -} - -Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const { - Transform3D t = *this; - t.set_look_at(origin, p_target, p_up); - return t; -} - -void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) { -#ifdef MATH_CHECKS - ERR_FAIL_COND(p_eye == p_target); - ERR_FAIL_COND(p_up.length() == 0); -#endif - // Reference: MESA source code - Vector3 v_x, v_y, v_z; - - /* Make rotation matrix */ - - /* Z vector */ - v_z = p_eye - p_target; - - v_z.normalize(); - - v_y = p_up; - - v_x = v_y.cross(v_z); -#ifdef MATH_CHECKS - ERR_FAIL_COND(v_x.length() == 0); -#endif - - /* Recompute Y = Z cross X */ - v_y = v_z.cross(v_x); - - v_x.normalize(); - v_y.normalize(); - - basis.set(v_x, v_y, v_z); - - origin = p_eye; -} - -Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { - /* not sure if very "efficient" but good enough? */ - - Vector3 src_scale = basis.get_scale(); - Quat src_rot = basis.get_rotation_quat(); - Vector3 src_loc = origin; - - Vector3 dst_scale = p_transform.basis.get_scale(); - Quat dst_rot = p_transform.basis.get_rotation_quat(); - Vector3 dst_loc = p_transform.origin; - - Transform3D interp; - interp.basis.set_quat_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c)); - interp.origin = src_loc.lerp(dst_loc, p_c); - - return interp; -} - -void Transform3D::scale(const Vector3 &p_scale) { - basis.scale(p_scale); - origin *= p_scale; -} - -Transform3D Transform3D::scaled(const Vector3 &p_scale) const { - Transform3D t = *this; - t.scale(p_scale); - return t; -} - -void Transform3D::scale_basis(const Vector3 &p_scale) { - basis.scale(p_scale); -} - -void Transform3D::translate(real_t p_tx, real_t p_ty, real_t p_tz) { - translate(Vector3(p_tx, p_ty, p_tz)); -} - -void Transform3D::translate(const Vector3 &p_translation) { - for (int i = 0; i < 3; i++) { - origin[i] += basis[i].dot(p_translation); - } -} - -Transform3D Transform3D::translated(const Vector3 &p_translation) const { - Transform3D t = *this; - t.translate(p_translation); - return t; -} - -void Transform3D::orthonormalize() { - basis.orthonormalize(); -} - -Transform3D Transform3D::orthonormalized() const { - Transform3D _copy = *this; - _copy.orthonormalize(); - return _copy; -} - -bool Transform3D::is_equal_approx(const Transform3D &p_transform) const { - return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin); -} - -bool Transform3D::operator==(const Transform3D &p_transform) const { - return (basis == p_transform.basis && origin == p_transform.origin); -} - -bool Transform3D::operator!=(const Transform3D &p_transform) const { - return (basis != p_transform.basis || origin != p_transform.origin); -} - -void Transform3D::operator*=(const Transform3D &p_transform) { - origin = xform(p_transform.origin); - basis *= p_transform.basis; -} - -Transform3D Transform3D::operator*(const Transform3D &p_transform) const { - Transform3D t = *this; - t *= p_transform; - return t; -} - -Transform3D::operator String() const { - return basis.operator String() + " - " + origin.operator String(); -} - -Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) : - basis(p_basis), - origin(p_origin) { -} - -Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) : - origin(p_origin) { - basis.set_axis(0, p_x); - basis.set_axis(1, p_y); - basis.set_axis(2, p_z); -} - -Transform3D::Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) { - basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz); - origin = Vector3(ox, oy, oz); -} diff --git a/core/math/transform.h b/core/math/transform.h deleted file mode 100644 index 5db7069a04..0000000000 --- a/core/math/transform.h +++ /dev/null @@ -1,232 +0,0 @@ -/*************************************************************************/ -/* transform.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef TRANSFORM_H -#define TRANSFORM_H - -#include "core/math/aabb.h" -#include "core/math/basis.h" -#include "core/math/plane.h" - -class Transform3D { -public: - Basis basis; - Vector3 origin; - - void invert(); - Transform3D inverse() const; - - void affine_invert(); - Transform3D affine_inverse() const; - - Transform3D rotated(const Vector3 &p_axis, real_t p_phi) const; - - void rotate(const Vector3 &p_axis, real_t p_phi); - void rotate_basis(const Vector3 &p_axis, real_t p_phi); - - void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); - Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const; - - void scale(const Vector3 &p_scale); - Transform3D scaled(const Vector3 &p_scale) const; - void scale_basis(const Vector3 &p_scale); - void translate(real_t p_tx, real_t p_ty, real_t p_tz); - void translate(const Vector3 &p_translation); - Transform3D translated(const Vector3 &p_translation) const; - - const Basis &get_basis() const { return basis; } - void set_basis(const Basis &p_basis) { basis = p_basis; } - - const Vector3 &get_origin() const { return origin; } - void set_origin(const Vector3 &p_origin) { origin = p_origin; } - - void orthonormalize(); - Transform3D orthonormalized() const; - bool is_equal_approx(const Transform3D &p_transform) const; - - bool operator==(const Transform3D &p_transform) const; - bool operator!=(const Transform3D &p_transform) const; - - _FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const; - _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const; - - _FORCE_INLINE_ Plane xform(const Plane &p_plane) const; - _FORCE_INLINE_ Plane xform_inv(const Plane &p_plane) const; - - _FORCE_INLINE_ AABB xform(const AABB &p_aabb) const; - _FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const; - - _FORCE_INLINE_ Vector xform(const Vector &p_array) const; - _FORCE_INLINE_ Vector xform_inv(const Vector &p_array) const; - - void operator*=(const Transform3D &p_transform); - Transform3D operator*(const Transform3D &p_transform) const; - - Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; - - _FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const { - Vector3 v = t.origin - origin; - return Transform3D(basis.transpose_xform(t.basis), - basis.xform(v)); - } - - void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) { - basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz); - origin.x = tx; - origin.y = ty; - origin.z = tz; - } - - operator String() const; - - Transform3D() {} - Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3()); - Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin); - Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz); -}; - -_FORCE_INLINE_ Vector3 Transform3D::xform(const Vector3 &p_vector) const { - return Vector3( - basis[0].dot(p_vector) + origin.x, - basis[1].dot(p_vector) + origin.y, - basis[2].dot(p_vector) + origin.z); -} - -_FORCE_INLINE_ Vector3 Transform3D::xform_inv(const Vector3 &p_vector) const { - Vector3 v = p_vector - origin; - - return Vector3( - (basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z), - (basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z), - (basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z)); -} - -_FORCE_INLINE_ Plane Transform3D::xform(const Plane &p_plane) const { - Vector3 point = p_plane.normal * p_plane.d; - Vector3 point_dir = point + p_plane.normal; - point = xform(point); - point_dir = xform(point_dir); - - Vector3 normal = point_dir - point; - normal.normalize(); - real_t d = normal.dot(point); - - return Plane(normal, d); -} - -_FORCE_INLINE_ Plane Transform3D::xform_inv(const Plane &p_plane) const { - Vector3 point = p_plane.normal * p_plane.d; - Vector3 point_dir = point + p_plane.normal; - point = xform_inv(point); - point_dir = xform_inv(point_dir); - - Vector3 normal = point_dir - point; - normal.normalize(); - real_t d = normal.dot(point); - - return Plane(normal, d); -} - -_FORCE_INLINE_ AABB Transform3D::xform(const AABB &p_aabb) const { - /* http://dev.theomader.com/transform-bounding-boxes/ */ - Vector3 min = p_aabb.position; - Vector3 max = p_aabb.position + p_aabb.size; - Vector3 tmin, tmax; - for (int i = 0; i < 3; i++) { - tmin[i] = tmax[i] = origin[i]; - for (int j = 0; j < 3; j++) { - real_t e = basis[i][j] * min[j]; - real_t f = basis[i][j] * max[j]; - if (e < f) { - tmin[i] += e; - tmax[i] += f; - } else { - tmin[i] += f; - tmax[i] += e; - } - } - } - AABB r_aabb; - r_aabb.position = tmin; - r_aabb.size = tmax - tmin; - return r_aabb; -} - -_FORCE_INLINE_ AABB Transform3D::xform_inv(const AABB &p_aabb) const { - /* define vertices */ - Vector3 vertices[8] = { - Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z), - Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z), - Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z), - Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z), - Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z), - Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z), - Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z), - Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z) - }; - - AABB ret; - - ret.position = xform_inv(vertices[0]); - - for (int i = 1; i < 8; i++) { - ret.expand_to(xform_inv(vertices[i])); - } - - return ret; -} - -Vector Transform3D::xform(const Vector &p_array) const { - Vector array; - array.resize(p_array.size()); - - const Vector3 *r = p_array.ptr(); - Vector3 *w = array.ptrw(); - - for (int i = 0; i < p_array.size(); ++i) { - w[i] = xform(r[i]); - } - return array; -} - -Vector Transform3D::xform_inv(const Vector &p_array) const { - Vector array; - array.resize(p_array.size()); - - const Vector3 *r = p_array.ptr(); - Vector3 *w = array.ptrw(); - - for (int i = 0; i < p_array.size(); ++i) { - w[i] = xform_inv(r[i]); - } - return array; -} - -#endif // TRANSFORM_H diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp new file mode 100644 index 0000000000..2611d6accf --- /dev/null +++ b/core/math/transform_3d.cpp @@ -0,0 +1,212 @@ +/*************************************************************************/ +/* transform_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "transform_3d.h" + +#include "core/math/math_funcs.h" +#include "core/string/print_string.h" + +void Transform3D::affine_invert() { + basis.invert(); + origin = basis.xform(-origin); +} + +Transform3D Transform3D::affine_inverse() const { + Transform3D ret = *this; + ret.affine_invert(); + return ret; +} + +void Transform3D::invert() { + basis.transpose(); + 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; +} + +void Transform3D::rotate(const Vector3 &p_axis, real_t p_phi) { + *this = rotated(p_axis, p_phi); +} + +Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_phi) const { + return Transform3D(Basis(p_axis, p_phi), Vector3()) * (*this); +} + +void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_phi) { + basis.rotate(p_axis, p_phi); +} + +Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const { + Transform3D t = *this; + t.set_look_at(origin, p_target, p_up); + return t; +} + +void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) { +#ifdef MATH_CHECKS + ERR_FAIL_COND(p_eye == p_target); + ERR_FAIL_COND(p_up.length() == 0); +#endif + // Reference: MESA source code + Vector3 v_x, v_y, v_z; + + /* Make rotation matrix */ + + /* Z vector */ + v_z = p_eye - p_target; + + v_z.normalize(); + + v_y = p_up; + + v_x = v_y.cross(v_z); +#ifdef MATH_CHECKS + ERR_FAIL_COND(v_x.length() == 0); +#endif + + /* Recompute Y = Z cross X */ + v_y = v_z.cross(v_x); + + v_x.normalize(); + v_y.normalize(); + + basis.set(v_x, v_y, v_z); + + origin = p_eye; +} + +Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { + /* not sure if very "efficient" but good enough? */ + + Vector3 src_scale = basis.get_scale(); + Quat src_rot = basis.get_rotation_quat(); + Vector3 src_loc = origin; + + Vector3 dst_scale = p_transform.basis.get_scale(); + Quat dst_rot = p_transform.basis.get_rotation_quat(); + Vector3 dst_loc = p_transform.origin; + + Transform3D interp; + interp.basis.set_quat_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c)); + interp.origin = src_loc.lerp(dst_loc, p_c); + + return interp; +} + +void Transform3D::scale(const Vector3 &p_scale) { + basis.scale(p_scale); + origin *= p_scale; +} + +Transform3D Transform3D::scaled(const Vector3 &p_scale) const { + Transform3D t = *this; + t.scale(p_scale); + return t; +} + +void Transform3D::scale_basis(const Vector3 &p_scale) { + basis.scale(p_scale); +} + +void Transform3D::translate(real_t p_tx, real_t p_ty, real_t p_tz) { + translate(Vector3(p_tx, p_ty, p_tz)); +} + +void Transform3D::translate(const Vector3 &p_translation) { + for (int i = 0; i < 3; i++) { + origin[i] += basis[i].dot(p_translation); + } +} + +Transform3D Transform3D::translated(const Vector3 &p_translation) const { + Transform3D t = *this; + t.translate(p_translation); + return t; +} + +void Transform3D::orthonormalize() { + basis.orthonormalize(); +} + +Transform3D Transform3D::orthonormalized() const { + Transform3D _copy = *this; + _copy.orthonormalize(); + return _copy; +} + +bool Transform3D::is_equal_approx(const Transform3D &p_transform) const { + return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin); +} + +bool Transform3D::operator==(const Transform3D &p_transform) const { + return (basis == p_transform.basis && origin == p_transform.origin); +} + +bool Transform3D::operator!=(const Transform3D &p_transform) const { + return (basis != p_transform.basis || origin != p_transform.origin); +} + +void Transform3D::operator*=(const Transform3D &p_transform) { + origin = xform(p_transform.origin); + basis *= p_transform.basis; +} + +Transform3D Transform3D::operator*(const Transform3D &p_transform) const { + Transform3D t = *this; + t *= p_transform; + return t; +} + +Transform3D::operator String() const { + return basis.operator String() + " - " + origin.operator String(); +} + +Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) : + basis(p_basis), + origin(p_origin) { +} + +Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) : + origin(p_origin) { + basis.set_axis(0, p_x); + basis.set_axis(1, p_y); + basis.set_axis(2, p_z); +} + +Transform3D::Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) { + basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz); + origin = Vector3(ox, oy, oz); +} diff --git a/core/math/transform_3d.h b/core/math/transform_3d.h new file mode 100644 index 0000000000..078a2ca11a --- /dev/null +++ b/core/math/transform_3d.h @@ -0,0 +1,232 @@ +/*************************************************************************/ +/* transform_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TRANSFORM_H +#define TRANSFORM_H + +#include "core/math/aabb.h" +#include "core/math/basis.h" +#include "core/math/plane.h" + +class Transform3D { +public: + Basis basis; + Vector3 origin; + + void invert(); + Transform3D inverse() const; + + void affine_invert(); + Transform3D affine_inverse() const; + + Transform3D rotated(const Vector3 &p_axis, real_t p_phi) const; + + void rotate(const Vector3 &p_axis, real_t p_phi); + void rotate_basis(const Vector3 &p_axis, real_t p_phi); + + void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); + Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const; + + void scale(const Vector3 &p_scale); + Transform3D scaled(const Vector3 &p_scale) const; + void scale_basis(const Vector3 &p_scale); + void translate(real_t p_tx, real_t p_ty, real_t p_tz); + void translate(const Vector3 &p_translation); + Transform3D translated(const Vector3 &p_translation) const; + + const Basis &get_basis() const { return basis; } + void set_basis(const Basis &p_basis) { basis = p_basis; } + + const Vector3 &get_origin() const { return origin; } + void set_origin(const Vector3 &p_origin) { origin = p_origin; } + + void orthonormalize(); + Transform3D orthonormalized() const; + bool is_equal_approx(const Transform3D &p_transform) const; + + bool operator==(const Transform3D &p_transform) const; + bool operator!=(const Transform3D &p_transform) const; + + _FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const; + _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const; + + _FORCE_INLINE_ Plane xform(const Plane &p_plane) const; + _FORCE_INLINE_ Plane xform_inv(const Plane &p_plane) const; + + _FORCE_INLINE_ AABB xform(const AABB &p_aabb) const; + _FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const; + + _FORCE_INLINE_ Vector xform(const Vector &p_array) const; + _FORCE_INLINE_ Vector xform_inv(const Vector &p_array) const; + + void operator*=(const Transform3D &p_transform); + Transform3D operator*(const Transform3D &p_transform) const; + + Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; + + _FORCE_INLINE_ Transform3D inverse_xform(const Transform3D &t) const { + Vector3 v = t.origin - origin; + return Transform3D(basis.transpose_xform(t.basis), + basis.xform(v)); + } + + void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) { + basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz); + origin.x = tx; + origin.y = ty; + origin.z = tz; + } + + operator String() const; + + Transform3D() {} + Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3()); + Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin); + Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz); +}; + +_FORCE_INLINE_ Vector3 Transform3D::xform(const Vector3 &p_vector) const { + return Vector3( + basis[0].dot(p_vector) + origin.x, + basis[1].dot(p_vector) + origin.y, + basis[2].dot(p_vector) + origin.z); +} + +_FORCE_INLINE_ Vector3 Transform3D::xform_inv(const Vector3 &p_vector) const { + Vector3 v = p_vector - origin; + + return Vector3( + (basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z), + (basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z), + (basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z)); +} + +_FORCE_INLINE_ Plane Transform3D::xform(const Plane &p_plane) const { + Vector3 point = p_plane.normal * p_plane.d; + Vector3 point_dir = point + p_plane.normal; + point = xform(point); + point_dir = xform(point_dir); + + Vector3 normal = point_dir - point; + normal.normalize(); + real_t d = normal.dot(point); + + return Plane(normal, d); +} + +_FORCE_INLINE_ Plane Transform3D::xform_inv(const Plane &p_plane) const { + Vector3 point = p_plane.normal * p_plane.d; + Vector3 point_dir = point + p_plane.normal; + point = xform_inv(point); + point_dir = xform_inv(point_dir); + + Vector3 normal = point_dir - point; + normal.normalize(); + real_t d = normal.dot(point); + + return Plane(normal, d); +} + +_FORCE_INLINE_ AABB Transform3D::xform(const AABB &p_aabb) const { + /* http://dev.theomader.com/transform-bounding-boxes/ */ + Vector3 min = p_aabb.position; + Vector3 max = p_aabb.position + p_aabb.size; + Vector3 tmin, tmax; + for (int i = 0; i < 3; i++) { + tmin[i] = tmax[i] = origin[i]; + for (int j = 0; j < 3; j++) { + real_t e = basis[i][j] * min[j]; + real_t f = basis[i][j] * max[j]; + if (e < f) { + tmin[i] += e; + tmax[i] += f; + } else { + tmin[i] += f; + tmax[i] += e; + } + } + } + AABB r_aabb; + r_aabb.position = tmin; + r_aabb.size = tmax - tmin; + return r_aabb; +} + +_FORCE_INLINE_ AABB Transform3D::xform_inv(const AABB &p_aabb) const { + /* define vertices */ + Vector3 vertices[8] = { + Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z), + Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z), + Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z), + Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z), + Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z), + Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z), + Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z), + Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z) + }; + + AABB ret; + + ret.position = xform_inv(vertices[0]); + + for (int i = 1; i < 8; i++) { + ret.expand_to(xform_inv(vertices[i])); + } + + return ret; +} + +Vector Transform3D::xform(const Vector &p_array) const { + Vector array; + array.resize(p_array.size()); + + const Vector3 *r = p_array.ptr(); + Vector3 *w = array.ptrw(); + + for (int i = 0; i < p_array.size(); ++i) { + w[i] = xform(r[i]); + } + return array; +} + +Vector Transform3D::xform_inv(const Vector &p_array) const { + Vector array; + array.resize(p_array.size()); + + const Vector3 *r = p_array.ptr(); + Vector3 *w = array.ptrw(); + + for (int i = 0; i < p_array.size(); ++i) { + w[i] = xform_inv(r[i]); + } + return array; +} + +#endif // TRANSFORM_H diff --git a/core/variant/variant.h b/core/variant/variant.h index 2b41ab5402..4945e967eb 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -38,8 +38,8 @@ #include "core/math/face3.h" #include "core/math/plane.h" #include "core/math/quat.h" -#include "core/math/transform.h" #include "core/math/transform_2d.h" +#include "core/math/transform_3d.h" #include "core/math/vector3.h" #include "core/math/vector3i.h" #include "core/object/object_id.h" diff --git a/modules/bullet/bullet_types_converter.h b/modules/bullet/bullet_types_converter.h index 74cdabd717..e184fe1769 100644 --- a/modules/bullet/bullet_types_converter.h +++ b/modules/bullet/bullet_types_converter.h @@ -32,7 +32,7 @@ #define BULLET_TYPES_CONVERTER_H #include "core/math/basis.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/math/vector3.h" #include "core/typedefs.h" diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index 67be2fd6da..944ab89b87 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -31,7 +31,7 @@ #ifndef COLLISION_OBJECT_BULLET_H #define COLLISION_OBJECT_BULLET_H -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/math/vector3.h" #include "core/object/class_db.h" #include "core/templates/vset.h" diff --git a/modules/csg/csg.h b/modules/csg/csg.h index 37a11eea90..4bd79e15a9 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -33,7 +33,7 @@ #include "core/math/aabb.h" #include "core/math/plane.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/math/vector2.h" #include "core/math/vector3.h" #include "core/object/reference.h" diff --git a/modules/fbx/data/pivot_transform.h b/modules/fbx/data/pivot_transform.h index c3b6accd5b..8ed8358b70 100644 --- a/modules/fbx/data/pivot_transform.h +++ b/modules/fbx/data/pivot_transform.h @@ -31,7 +31,7 @@ #ifndef PIVOT_TRANSFORM_H #define PIVOT_TRANSFORM_H -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/object/reference.h" #include "model_abstraction.h" diff --git a/modules/fbx/fbx_parser/FBXDeformer.cpp b/modules/fbx/fbx_parser/FBXDeformer.cpp index 039718ae15..4220ba62a7 100644 --- a/modules/fbx/fbx_parser/FBXDeformer.cpp +++ b/modules/fbx/fbx_parser/FBXDeformer.cpp @@ -78,7 +78,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXMeshGeometry.h" #include "FBXParser.h" #include "core/math/math_funcs.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include diff --git a/modules/fbx/fbx_parser/FBXDocument.h b/modules/fbx/fbx_parser/FBXDocument.h index 8aa4cdf479..885ff8fca4 100644 --- a/modules/fbx/fbx_parser/FBXDocument.h +++ b/modules/fbx/fbx_parser/FBXDocument.h @@ -37,7 +37,7 @@ #include "FBXCommon.h" #include "FBXParser.h" #include "FBXProperties.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/math/vector2.h" #include "core/math/vector3.h" #include "core/string/print_string.h" diff --git a/modules/fbx/fbx_parser/FBXParser.cpp b/modules/fbx/fbx_parser/FBXParser.cpp index 2d8b190779..163518d18f 100644 --- a/modules/fbx/fbx_parser/FBXParser.cpp +++ b/modules/fbx/fbx_parser/FBXParser.cpp @@ -82,7 +82,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXParser.h" #include "FBXTokenizer.h" #include "core/math/math_defs.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/math/vector3.h" #include "core/string/print_string.h" diff --git a/modules/fbx/fbx_parser/FBXParser.h b/modules/fbx/fbx_parser/FBXParser.h index d1f1f93d5f..93836c2205 100644 --- a/modules/fbx/fbx_parser/FBXParser.h +++ b/modules/fbx/fbx_parser/FBXParser.h @@ -81,7 +81,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "core/math/color.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/math/vector2.h" #include "core/math/vector3.h" diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp index 1a6be4b521..de47b2fe0a 100644 --- a/modules/gdnative/gdnative/transform.cpp +++ b/modules/gdnative/gdnative/transform.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* transform.cpp */ +/* transform_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,7 +30,7 @@ #include "gdnative/transform.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" static_assert(sizeof(godot_transform) == sizeof(Transform3D), "Transform3D size mismatch"); diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h index 3861b5683a..f9acb52377 100644 --- a/modules/gdnative/include/gdnative/transform.h +++ b/modules/gdnative/include/gdnative/transform.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* transform.h */ +/* transform_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 72e26070e1..c2707e46d9 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -3126,10 +3126,10 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar case Variant::TRANSFORM3D: { Transform3D transform = p_val.operator Transform3D(); if (transform == Transform3D()) { - r_iarg.default_argument = "Transform.Identity"; + r_iarg.default_argument = "Transform3D.Identity"; } else { Basis basis = transform.basis; - r_iarg.default_argument = "new Transform(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")"; + r_iarg.default_argument = "new Transform3D(new Vector3" + basis.get_column(0).operator String() + ", new Vector3" + basis.get_column(1).operator String() + ", new Vector3" + basis.get_column(2).operator String() + ", new Vector3" + transform.origin.operator String() + ")"; } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs deleted file mode 100644 index 9e5ff2b315..0000000000 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs +++ /dev/null @@ -1,412 +0,0 @@ -using System; -using System.Runtime.InteropServices; -#if REAL_T_IS_DOUBLE -using real_t = System.Double; -#else -using real_t = System.Single; -#endif - -namespace Godot -{ - /// - /// 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations. - /// It can represent transformations such as translation, rotation, or scaling. - /// It consists of a (first 3 columns) and a - /// for the origin (last column). - /// - /// For more information, read this documentation article: - /// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html - /// - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public struct Transform3D : IEquatable - { - /// - /// The of this transform. Contains the X, Y, and Z basis - /// vectors (columns 0 to 2) and is responsible for rotation and scale. - /// - public Basis basis; - - /// - /// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`. - /// - public Vector3 origin; - - /// - /// Access whole columns in the form of Vector3. The fourth column is the origin vector. - /// - /// Which column vector. - public Vector3 this[int column] - { - get - { - switch (column) - { - case 0: - return basis.Column0; - case 1: - return basis.Column1; - case 2: - return basis.Column2; - case 3: - return origin; - default: - throw new IndexOutOfRangeException(); - } - } - set - { - switch (column) - { - case 0: - basis.Column0 = value; - return; - case 1: - basis.Column1 = value; - return; - case 2: - basis.Column2 = value; - return; - case 3: - origin = value; - return; - default: - throw new IndexOutOfRangeException(); - } - } - } - - /// - /// Access matrix elements in column-major order. The fourth column is the origin vector. - /// - /// Which column, the matrix horizontal position. - /// Which row, the matrix vertical position. - public real_t this[int column, int row] - { - get - { - if (column == 3) - { - return origin[row]; - } - return basis[column, row]; - } - set - { - if (column == 3) - { - origin[row] = value; - return; - } - basis[column, row] = value; - } - } - - /// - /// Returns the inverse of the transform, under the assumption that - /// the transformation is composed of rotation, scaling, and translation. - /// - /// The inverse transformation matrix. - public Transform3D AffineInverse() - { - Basis basisInv = basis.Inverse(); - return new Transform3D(basisInv, basisInv.Xform(-origin)); - } - - /// - /// Interpolates this transform to the other `transform` by `weight`. - /// - /// The other transform. - /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. - /// The interpolated transform. - public Transform3D InterpolateWith(Transform3D transform, real_t weight) - { - /* not sure if very "efficient" but good enough? */ - - Vector3 sourceScale = basis.Scale; - Quat sourceRotation = basis.RotationQuat(); - Vector3 sourceLocation = origin; - - Vector3 destinationScale = transform.basis.Scale; - Quat destinationRotation = transform.basis.RotationQuat(); - Vector3 destinationLocation = transform.origin; - - var interpolated = new Transform3D(); - interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.Lerp(destinationScale, weight)); - interpolated.origin = sourceLocation.Lerp(destinationLocation, weight); - - return interpolated; - } - - /// - /// Returns the inverse of the transform, under the assumption that - /// the transformation is composed of rotation and translation - /// (no scaling, use for transforms with scaling). - /// - /// The inverse matrix. - public Transform3D Inverse() - { - Basis basisTr = basis.Transposed(); - return new Transform3D(basisTr, basisTr.Xform(-origin)); - } - - /// - /// Returns a copy of the transform rotated such that its - /// -Z axis (forward) points towards the target position. - /// - /// The transform will first be rotated around the given up vector, - /// and then fully aligned to the target by a further rotation around - /// an axis perpendicular to both the target and up vectors. - /// - /// Operations take place in global space. - /// - /// The object to look at. - /// The relative up direction - /// The resulting transform. - public Transform3D LookingAt(Vector3 target, Vector3 up) - { - var t = this; - t.SetLookAt(origin, target, up); - return t; - } - - /// - /// Returns the transform with the basis orthogonal (90 degrees), - /// and normalized axis vectors (scale of 1 or -1). - /// - /// The orthonormalized transform. - public Transform3D Orthonormalized() - { - return new Transform3D(basis.Orthonormalized(), origin); - } - - /// - /// Rotates the transform around the given `axis` by `phi` (in radians), - /// using matrix multiplication. The axis must be a normalized vector. - /// - /// The axis to rotate around. Must be normalized. - /// The angle to rotate, in radians. - /// The rotated transformation matrix. - public Transform3D Rotated(Vector3 axis, real_t phi) - { - return new Transform3D(new Basis(axis, phi), new Vector3()) * this; - } - - /// - /// Scales the transform by the given 3D scaling factor, using matrix multiplication. - /// - /// The scale to introduce. - /// The scaled transformation matrix. - public Transform3D Scaled(Vector3 scale) - { - return new Transform3D(basis.Scaled(scale), origin * scale); - } - - private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up) - { - // Make rotation matrix - // Z vector - Vector3 column2 = eye - target; - - column2.Normalize(); - - Vector3 column1 = up; - - Vector3 column0 = column1.Cross(column2); - - // Recompute Y = Z cross X - column1 = column2.Cross(column0); - - column0.Normalize(); - column1.Normalize(); - - basis = new Basis(column0, column1, column2); - - origin = eye; - } - - /// - /// Translates the transform by the given `offset`, - /// relative to the transform's basis vectors. - /// - /// Unlike and , - /// this does not use matrix multiplication. - /// - /// The offset to translate by. - /// The translated matrix. - public Transform3D Translated(Vector3 offset) - { - return new Transform3D(basis, new Vector3 - ( - origin[0] += basis.Row0.Dot(offset), - origin[1] += basis.Row1.Dot(offset), - origin[2] += basis.Row2.Dot(offset) - )); - } - - /// - /// Returns a vector transformed (multiplied) by this transformation matrix. - /// - /// A vector to transform. - /// The transformed vector. - public Vector3 Xform(Vector3 v) - { - return new Vector3 - ( - basis.Row0.Dot(v) + origin.x, - basis.Row1.Dot(v) + origin.y, - basis.Row2.Dot(v) + origin.z - ); - } - - /// - /// Returns a vector transformed (multiplied) by the transposed transformation matrix. - /// - /// Note: This results in a multiplication by the inverse of the - /// transformation matrix only if it represents a rotation-reflection. - /// - /// A vector to inversely transform. - /// The inversely transformed vector. - public Vector3 XformInv(Vector3 v) - { - Vector3 vInv = v - origin; - - return new Vector3 - ( - basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z, - basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z, - basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z - ); - } - - // Constants - private static readonly Transform3D _identity = new Transform3D(Basis.Identity, Vector3.Zero); - private static readonly Transform3D _flipX = new Transform3D(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero); - private static readonly Transform3D _flipY = new Transform3D(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero); - private static readonly Transform3D _flipZ = new Transform3D(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero); - - /// - /// The identity transform, with no translation, rotation, or scaling applied. - /// This is used as a replacement for `Transform()` in GDScript. - /// Do not use `new Transform()` with no arguments in C#, because it sets all values to zero. - /// - /// Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)`. - public static Transform3D Identity { get { return _identity; } } - /// - /// The transform that will flip something along the X axis. - /// - /// Equivalent to `new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)`. - public static Transform3D FlipX { get { return _flipX; } } - /// - /// The transform that will flip something along the Y axis. - /// - /// Equivalent to `new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)`. - public static Transform3D FlipY { get { return _flipY; } } - /// - /// The transform that will flip something along the Z axis. - /// - /// Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)`. - public static Transform3D FlipZ { get { return _flipZ; } } - - /// - /// Constructs a transformation matrix from 4 vectors (matrix columns). - /// - /// The X vector, or column index 0. - /// The Y vector, or column index 1. - /// The Z vector, or column index 2. - /// The origin vector, or column index 3. - public Transform3D(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin) - { - basis = new Basis(column0, column1, column2); - this.origin = origin; - } - - /// - /// Constructs a transformation matrix from the given quaternion and origin vector. - /// - /// The to create the basis from. - /// The origin vector, or column index 3. - public Transform3D(Quat quat, Vector3 origin) - { - basis = new Basis(quat); - this.origin = origin; - } - - /// - /// Constructs a transformation matrix from the given basis and origin vector. - /// - /// The to create the basis from. - /// The origin vector, or column index 3. - public Transform3D(Basis basis, Vector3 origin) - { - this.basis = basis; - this.origin = origin; - } - - public static Transform3D operator *(Transform3D left, Transform3D right) - { - left.origin = left.Xform(right.origin); - left.basis *= right.basis; - return left; - } - - public static bool operator ==(Transform3D left, Transform3D right) - { - return left.Equals(right); - } - - public static bool operator !=(Transform3D left, Transform3D right) - { - return !left.Equals(right); - } - - public override bool Equals(object obj) - { - if (obj is Transform3D) - { - return Equals((Transform3D)obj); - } - - return false; - } - - public bool Equals(Transform3D other) - { - return basis.Equals(other.basis) && origin.Equals(other.origin); - } - - /// - /// Returns true if this transform and `other` are approximately equal, by running - /// on each component. - /// - /// The other transform to compare. - /// Whether or not the matrices are approximately equal. - public bool IsEqualApprox(Transform3D other) - { - return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin); - } - - public override int GetHashCode() - { - return basis.GetHashCode() ^ origin.GetHashCode(); - } - - public override string ToString() - { - return String.Format("{0} - {1}", new object[] - { - basis.ToString(), - origin.ToString() - }); - } - - public string ToString(string format) - { - return String.Format("{0} - {1}", new object[] - { - basis.ToString(format), - origin.ToString(format) - }); - } - } -} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs new file mode 100644 index 0000000000..9e5ff2b315 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -0,0 +1,412 @@ +using System; +using System.Runtime.InteropServices; +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif + +namespace Godot +{ + /// + /// 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations. + /// It can represent transformations such as translation, rotation, or scaling. + /// It consists of a (first 3 columns) and a + /// for the origin (last column). + /// + /// For more information, read this documentation article: + /// https://docs.godotengine.org/en/latest/tutorials/math/matrices_and_transforms.html + /// + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Transform3D : IEquatable + { + /// + /// The of this transform. Contains the X, Y, and Z basis + /// vectors (columns 0 to 2) and is responsible for rotation and scale. + /// + public Basis basis; + + /// + /// The origin vector (column 3, the fourth column). Equivalent to array index `[3]`. + /// + public Vector3 origin; + + /// + /// Access whole columns in the form of Vector3. The fourth column is the origin vector. + /// + /// Which column vector. + public Vector3 this[int column] + { + get + { + switch (column) + { + case 0: + return basis.Column0; + case 1: + return basis.Column1; + case 2: + return basis.Column2; + case 3: + return origin; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (column) + { + case 0: + basis.Column0 = value; + return; + case 1: + basis.Column1 = value; + return; + case 2: + basis.Column2 = value; + return; + case 3: + origin = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + /// + /// Access matrix elements in column-major order. The fourth column is the origin vector. + /// + /// Which column, the matrix horizontal position. + /// Which row, the matrix vertical position. + public real_t this[int column, int row] + { + get + { + if (column == 3) + { + return origin[row]; + } + return basis[column, row]; + } + set + { + if (column == 3) + { + origin[row] = value; + return; + } + basis[column, row] = value; + } + } + + /// + /// Returns the inverse of the transform, under the assumption that + /// the transformation is composed of rotation, scaling, and translation. + /// + /// The inverse transformation matrix. + public Transform3D AffineInverse() + { + Basis basisInv = basis.Inverse(); + return new Transform3D(basisInv, basisInv.Xform(-origin)); + } + + /// + /// Interpolates this transform to the other `transform` by `weight`. + /// + /// The other transform. + /// A value on the range of 0.0 to 1.0, representing the amount of interpolation. + /// The interpolated transform. + public Transform3D InterpolateWith(Transform3D transform, real_t weight) + { + /* not sure if very "efficient" but good enough? */ + + Vector3 sourceScale = basis.Scale; + Quat sourceRotation = basis.RotationQuat(); + Vector3 sourceLocation = origin; + + Vector3 destinationScale = transform.basis.Scale; + Quat destinationRotation = transform.basis.RotationQuat(); + Vector3 destinationLocation = transform.origin; + + var interpolated = new Transform3D(); + interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, weight).Normalized(), sourceScale.Lerp(destinationScale, weight)); + interpolated.origin = sourceLocation.Lerp(destinationLocation, weight); + + return interpolated; + } + + /// + /// Returns the inverse of the transform, under the assumption that + /// the transformation is composed of rotation and translation + /// (no scaling, use for transforms with scaling). + /// + /// The inverse matrix. + public Transform3D Inverse() + { + Basis basisTr = basis.Transposed(); + return new Transform3D(basisTr, basisTr.Xform(-origin)); + } + + /// + /// Returns a copy of the transform rotated such that its + /// -Z axis (forward) points towards the target position. + /// + /// The transform will first be rotated around the given up vector, + /// and then fully aligned to the target by a further rotation around + /// an axis perpendicular to both the target and up vectors. + /// + /// Operations take place in global space. + /// + /// The object to look at. + /// The relative up direction + /// The resulting transform. + public Transform3D LookingAt(Vector3 target, Vector3 up) + { + var t = this; + t.SetLookAt(origin, target, up); + return t; + } + + /// + /// Returns the transform with the basis orthogonal (90 degrees), + /// and normalized axis vectors (scale of 1 or -1). + /// + /// The orthonormalized transform. + public Transform3D Orthonormalized() + { + return new Transform3D(basis.Orthonormalized(), origin); + } + + /// + /// Rotates the transform around the given `axis` by `phi` (in radians), + /// using matrix multiplication. The axis must be a normalized vector. + /// + /// The axis to rotate around. Must be normalized. + /// The angle to rotate, in radians. + /// The rotated transformation matrix. + public Transform3D Rotated(Vector3 axis, real_t phi) + { + return new Transform3D(new Basis(axis, phi), new Vector3()) * this; + } + + /// + /// Scales the transform by the given 3D scaling factor, using matrix multiplication. + /// + /// The scale to introduce. + /// The scaled transformation matrix. + public Transform3D Scaled(Vector3 scale) + { + return new Transform3D(basis.Scaled(scale), origin * scale); + } + + private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up) + { + // Make rotation matrix + // Z vector + Vector3 column2 = eye - target; + + column2.Normalize(); + + Vector3 column1 = up; + + Vector3 column0 = column1.Cross(column2); + + // Recompute Y = Z cross X + column1 = column2.Cross(column0); + + column0.Normalize(); + column1.Normalize(); + + basis = new Basis(column0, column1, column2); + + origin = eye; + } + + /// + /// Translates the transform by the given `offset`, + /// relative to the transform's basis vectors. + /// + /// Unlike and , + /// this does not use matrix multiplication. + /// + /// The offset to translate by. + /// The translated matrix. + public Transform3D Translated(Vector3 offset) + { + return new Transform3D(basis, new Vector3 + ( + origin[0] += basis.Row0.Dot(offset), + origin[1] += basis.Row1.Dot(offset), + origin[2] += basis.Row2.Dot(offset) + )); + } + + /// + /// Returns a vector transformed (multiplied) by this transformation matrix. + /// + /// A vector to transform. + /// The transformed vector. + public Vector3 Xform(Vector3 v) + { + return new Vector3 + ( + basis.Row0.Dot(v) + origin.x, + basis.Row1.Dot(v) + origin.y, + basis.Row2.Dot(v) + origin.z + ); + } + + /// + /// Returns a vector transformed (multiplied) by the transposed transformation matrix. + /// + /// Note: This results in a multiplication by the inverse of the + /// transformation matrix only if it represents a rotation-reflection. + /// + /// A vector to inversely transform. + /// The inversely transformed vector. + public Vector3 XformInv(Vector3 v) + { + Vector3 vInv = v - origin; + + return new Vector3 + ( + basis.Row0[0] * vInv.x + basis.Row1[0] * vInv.y + basis.Row2[0] * vInv.z, + basis.Row0[1] * vInv.x + basis.Row1[1] * vInv.y + basis.Row2[1] * vInv.z, + basis.Row0[2] * vInv.x + basis.Row1[2] * vInv.y + basis.Row2[2] * vInv.z + ); + } + + // Constants + private static readonly Transform3D _identity = new Transform3D(Basis.Identity, Vector3.Zero); + private static readonly Transform3D _flipX = new Transform3D(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero); + private static readonly Transform3D _flipY = new Transform3D(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero); + private static readonly Transform3D _flipZ = new Transform3D(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero); + + /// + /// The identity transform, with no translation, rotation, or scaling applied. + /// This is used as a replacement for `Transform()` in GDScript. + /// Do not use `new Transform()` with no arguments in C#, because it sets all values to zero. + /// + /// Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Back, Vector3.Zero)`. + public static Transform3D Identity { get { return _identity; } } + /// + /// The transform that will flip something along the X axis. + /// + /// Equivalent to `new Transform(Vector3.Left, Vector3.Up, Vector3.Back, Vector3.Zero)`. + public static Transform3D FlipX { get { return _flipX; } } + /// + /// The transform that will flip something along the Y axis. + /// + /// Equivalent to `new Transform(Vector3.Right, Vector3.Down, Vector3.Back, Vector3.Zero)`. + public static Transform3D FlipY { get { return _flipY; } } + /// + /// The transform that will flip something along the Z axis. + /// + /// Equivalent to `new Transform(Vector3.Right, Vector3.Up, Vector3.Forward, Vector3.Zero)`. + public static Transform3D FlipZ { get { return _flipZ; } } + + /// + /// Constructs a transformation matrix from 4 vectors (matrix columns). + /// + /// The X vector, or column index 0. + /// The Y vector, or column index 1. + /// The Z vector, or column index 2. + /// The origin vector, or column index 3. + public Transform3D(Vector3 column0, Vector3 column1, Vector3 column2, Vector3 origin) + { + basis = new Basis(column0, column1, column2); + this.origin = origin; + } + + /// + /// Constructs a transformation matrix from the given quaternion and origin vector. + /// + /// The to create the basis from. + /// The origin vector, or column index 3. + public Transform3D(Quat quat, Vector3 origin) + { + basis = new Basis(quat); + this.origin = origin; + } + + /// + /// Constructs a transformation matrix from the given basis and origin vector. + /// + /// The to create the basis from. + /// The origin vector, or column index 3. + public Transform3D(Basis basis, Vector3 origin) + { + this.basis = basis; + this.origin = origin; + } + + public static Transform3D operator *(Transform3D left, Transform3D right) + { + left.origin = left.Xform(right.origin); + left.basis *= right.basis; + return left; + } + + public static bool operator ==(Transform3D left, Transform3D right) + { + return left.Equals(right); + } + + public static bool operator !=(Transform3D left, Transform3D right) + { + return !left.Equals(right); + } + + public override bool Equals(object obj) + { + if (obj is Transform3D) + { + return Equals((Transform3D)obj); + } + + return false; + } + + public bool Equals(Transform3D other) + { + return basis.Equals(other.basis) && origin.Equals(other.origin); + } + + /// + /// Returns true if this transform and `other` are approximately equal, by running + /// on each component. + /// + /// The other transform to compare. + /// Whether or not the matrices are approximately equal. + public bool IsEqualApprox(Transform3D other) + { + return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin); + } + + public override int GetHashCode() + { + return basis.GetHashCode() ^ origin.GetHashCode(); + } + + public override string ToString() + { + return String.Format("{0} - {1}", new object[] + { + basis.ToString(), + origin.ToString() + }); + } + + public string ToString(string format) + { + return String.Format("{0} - {1}", new object[] + { + basis.ToString(format), + origin.ToString(format) + }); + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 54aaaf1f92..c3dd13d84b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -58,8 +58,8 @@ - + diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h index 80f4ac32bd..81dfe675c3 100644 --- a/scene/3d/skeleton_ik_3d.h +++ b/scene/3d/skeleton_ik_3d.h @@ -37,7 +37,7 @@ * @author AndreaCatania */ -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "scene/3d/skeleton_3d.h" class FabrikInverseKinematic { diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index f1131db15b..ef2635c188 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "servers/navigation_server_2d.h" -#include "core/math/transform.h" #include "core/math/transform_2d.h" +#include "core/math/transform_3d.h" #include "servers/navigation_server_3d.h" /** diff --git a/servers/physics_3d/joints/jacobian_entry_3d_sw.h b/servers/physics_3d/joints/jacobian_entry_3d_sw.h index 2829a5caf7..6afa70c816 100644 --- a/servers/physics_3d/joints/jacobian_entry_3d_sw.h +++ b/servers/physics_3d/joints/jacobian_entry_3d_sw.h @@ -50,7 +50,7 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#include "core/math/transform.h" +#include "core/math/transform_3d.h" class JacobianEntry3DSW { public: diff --git a/tests/test_math.cpp b/tests/test_math.cpp index 88c32713ed..aae8ce08e8 100644 --- a/tests/test_math.cpp +++ b/tests/test_math.cpp @@ -35,7 +35,7 @@ #include "core/math/delaunay_3d.h" #include "core/math/geometry_2d.h" #include "core/math/math_funcs.h" -#include "core/math/transform.h" +#include "core/math/transform_3d.h" #include "core/os/file_access.h" #include "core/os/keyboard.h" #include "core/os/os.h" -- cgit v1.2.3