| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  transform_3d.cpp                                                      */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* 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.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-26 23:26:56 -05:00
										 |  |  | #include "transform_3d.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "core/math/math_funcs.h"
 | 
					
						
							| 
									
										
										
										
											2022-10-06 16:35:54 -05:00
										 |  |  | #include "core/string/ustring.h"
 | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | void Transform3D::affine_invert() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	basis.invert(); | 
					
						
							|  |  |  | 	origin = basis.xform(-origin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D Transform3D::affine_inverse() const { | 
					
						
							|  |  |  | 	Transform3D ret = *this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	ret.affine_invert(); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | void Transform3D::invert() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	basis.transpose(); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 	origin = basis.xform(-origin); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D Transform3D::inverse() const { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:31:39 -06:00
										 |  |  | 	// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 	// Transform3D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
 | 
					
						
							|  |  |  | 	Transform3D ret = *this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	ret.invert(); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-05 13:25:04 +02:00
										 |  |  | void Transform3D::rotate(const Vector3 &p_axis, real_t p_angle) { | 
					
						
							|  |  |  | 	*this = rotated(p_axis, p_angle); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-05 13:25:04 +02:00
										 |  |  | Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_angle) const { | 
					
						
							| 
									
										
										
										
											2022-07-30 12:17:33 +02:00
										 |  |  | 	// Equivalent to left multiplication
 | 
					
						
							|  |  |  | 	Basis p_basis(p_axis, p_angle); | 
					
						
							|  |  |  | 	return Transform3D(p_basis * basis, p_basis.xform(origin)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Transform3D Transform3D::rotated_local(const Vector3 &p_axis, real_t p_angle) const { | 
					
						
							|  |  |  | 	// Equivalent to right multiplication
 | 
					
						
							|  |  |  | 	Basis p_basis(p_axis, p_angle); | 
					
						
							|  |  |  | 	return Transform3D(basis * p_basis, origin); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-05 13:25:04 +02:00
										 |  |  | void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) { | 
					
						
							|  |  |  | 	basis.rotate(p_axis, p_angle); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 10:01:43 +02:00
										 |  |  | Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) const { | 
					
						
							| 
									
										
										
										
											2022-07-24 03:14:53 -05:00
										 |  |  | #ifdef MATH_CHECKS
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal."); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 	Transform3D t = *this; | 
					
						
							| 
									
										
										
										
											2023-04-15 10:01:43 +02:00
										 |  |  | 	t.basis = Basis::looking_at(p_target - origin, p_up, p_use_model_front); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return t; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-15 10:01:43 +02:00
										 |  |  | void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) { | 
					
						
							| 
									
										
										
										
											2022-07-24 03:14:53 -05:00
										 |  |  | #ifdef MATH_CHECKS
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal."); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-04-15 10:01:43 +02:00
										 |  |  | 	basis = Basis::looking_at(p_target - p_eye, p_up, p_use_model_front); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	origin = p_eye; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-31 16:09:29 +09:00
										 |  |  | Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const { | 
					
						
							| 
									
										
										
										
											2021-10-09 19:24:26 +09:00
										 |  |  | 	Transform3D interp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 15:53:25 -04:00
										 |  |  | 	Vector3 src_scale = basis.get_scale(); | 
					
						
							| 
									
										
										
										
											2021-01-20 07:02:02 +00:00
										 |  |  | 	Quaternion src_rot = basis.get_rotation_quaternion(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Vector3 src_loc = origin; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 15:53:25 -04:00
										 |  |  | 	Vector3 dst_scale = p_transform.basis.get_scale(); | 
					
						
							| 
									
										
										
										
											2021-01-20 07:02:02 +00:00
										 |  |  | 	Quaternion dst_rot = p_transform.basis.get_rotation_quaternion(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Vector3 dst_loc = p_transform.origin; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-20 07:02:02 +00:00
										 |  |  | 	interp.basis.set_quaternion_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c)); | 
					
						
							| 
									
										
										
										
											2020-03-16 05:07:33 -04:00
										 |  |  | 	interp.origin = src_loc.lerp(dst_loc, p_c); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-16 20:32:35 -04:00
										 |  |  | 	return interp; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | void Transform3D::scale(const Vector3 &p_scale) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	basis.scale(p_scale); | 
					
						
							|  |  |  | 	origin *= p_scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D Transform3D::scaled(const Vector3 &p_scale) const { | 
					
						
							| 
									
										
										
										
											2022-07-30 12:17:33 +02:00
										 |  |  | 	// Equivalent to left multiplication
 | 
					
						
							|  |  |  | 	return Transform3D(basis.scaled(p_scale), origin * p_scale); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Transform3D Transform3D::scaled_local(const Vector3 &p_scale) const { | 
					
						
							|  |  |  | 	// Equivalent to right multiplication
 | 
					
						
							|  |  |  | 	return Transform3D(basis.scaled_local(p_scale), origin); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | void Transform3D::scale_basis(const Vector3 &p_scale) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	basis.scale(p_scale); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 11:47:54 +02:00
										 |  |  | void Transform3D::translate_local(real_t p_tx, real_t p_ty, real_t p_tz) { | 
					
						
							|  |  |  | 	translate_local(Vector3(p_tx, p_ty, p_tz)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 11:47:54 +02:00
										 |  |  | void Transform3D::translate_local(const Vector3 &p_translation) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	for (int i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 		origin[i] += basis[i].dot(p_translation); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-30 12:17:33 +02:00
										 |  |  | Transform3D Transform3D::translated(const Vector3 &p_translation) const { | 
					
						
							|  |  |  | 	// Equivalent to left multiplication
 | 
					
						
							|  |  |  | 	return Transform3D(basis, origin + p_translation); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 11:47:54 +02:00
										 |  |  | Transform3D Transform3D::translated_local(const Vector3 &p_translation) const { | 
					
						
							| 
									
										
										
										
											2022-07-30 12:17:33 +02:00
										 |  |  | 	// Equivalent to right multiplication
 | 
					
						
							|  |  |  | 	return Transform3D(basis, origin + basis.xform(p_translation)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | void Transform3D::orthonormalize() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	basis.orthonormalize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D Transform3D::orthonormalized() const { | 
					
						
							|  |  |  | 	Transform3D _copy = *this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	_copy.orthonormalize(); | 
					
						
							|  |  |  | 	return _copy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-09 19:24:26 +09:00
										 |  |  | void Transform3D::orthogonalize() { | 
					
						
							|  |  |  | 	basis.orthogonalize(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Transform3D Transform3D::orthogonalized() const { | 
					
						
							|  |  |  | 	Transform3D _copy = *this; | 
					
						
							|  |  |  | 	_copy.orthogonalize(); | 
					
						
							|  |  |  | 	return _copy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | bool Transform3D::is_equal_approx(const Transform3D &p_transform) const { | 
					
						
							| 
									
										
										
										
											2019-10-14 16:33:45 -04:00
										 |  |  | 	return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 16:12:27 +08:00
										 |  |  | bool Transform3D::is_finite() const { | 
					
						
							|  |  |  | 	return basis.is_finite() && origin.is_finite(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | bool Transform3D::operator==(const Transform3D &p_transform) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return (basis == p_transform.basis && origin == p_transform.origin); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | bool Transform3D::operator!=(const Transform3D &p_transform) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return (basis != p_transform.basis || origin != p_transform.origin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | void Transform3D::operator*=(const Transform3D &p_transform) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	origin = xform(p_transform.origin); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 	basis *= p_transform.basis; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D Transform3D::operator*(const Transform3D &p_transform) const { | 
					
						
							|  |  |  | 	Transform3D t = *this; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	t *= p_transform; | 
					
						
							|  |  |  | 	return t; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-15 21:15:38 -04:00
										 |  |  | void Transform3D::operator*=(const real_t p_val) { | 
					
						
							|  |  |  | 	origin *= p_val; | 
					
						
							|  |  |  | 	basis *= p_val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Transform3D Transform3D::operator*(const real_t p_val) const { | 
					
						
							|  |  |  | 	Transform3D ret(*this); | 
					
						
							|  |  |  | 	ret *= p_val; | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D::operator String() const { | 
					
						
							| 
									
										
										
										
											2022-05-03 07:50:35 -05:00
										 |  |  | 	return "[X: " + basis.get_column(0).operator String() + | 
					
						
							|  |  |  | 			", Y: " + basis.get_column(1).operator String() + | 
					
						
							|  |  |  | 			", Z: " + basis.get_column(2).operator String() + | 
					
						
							| 
									
										
										
										
											2021-10-28 15:19:35 +02:00
										 |  |  | 			", O: " + origin.operator String() + "]"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) : | 
					
						
							| 
									
										
										
										
											2017-12-06 21:36:34 +01:00
										 |  |  | 		basis(p_basis), | 
					
						
							|  |  |  | 		origin(p_origin) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-08-08 20:29:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) : | 
					
						
							| 
									
										
										
										
											2020-11-09 17:46:03 +01:00
										 |  |  | 		origin(p_origin) { | 
					
						
							| 
									
										
										
										
											2022-05-03 07:50:35 -05:00
										 |  |  | 	basis.set_column(0, p_x); | 
					
						
							|  |  |  | 	basis.set_column(1, p_y); | 
					
						
							|  |  |  | 	basis.set_column(2, p_z); | 
					
						
							| 
									
										
										
										
											2020-11-09 17:46:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2019-08-08 20:29:45 -07:00
										 |  |  | 	basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz); | 
					
						
							|  |  |  | 	origin = Vector3(ox, oy, oz); | 
					
						
							|  |  |  | } |