1 /*************************************************************************/
2 /*  transform.h                                                          */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #ifndef TRANSFORM_H
31 #define TRANSFORM_H
32 
33 #include "aabb.h"
34 #include "matrix3.h"
35 #include "plane.h"
36 /**
37 	@author Juan Linietsky <reduzio@gmail.com>
38 */
39 class Transform {
40 public:
41 	Matrix3 basis;
42 	Vector3 origin;
43 
44 	void invert();
45 	Transform inverse() const;
46 
47 	void affine_invert();
48 	Transform affine_inverse() const;
49 
50 	Transform rotated(const Vector3 &p_axis, real_t p_phi) const;
51 
52 	void rotate(const Vector3 &p_axis, real_t p_phi);
53 	void rotate_basis(const Vector3 &p_axis, real_t p_phi);
54 
55 	void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up);
56 	Transform looking_at(const Vector3 &p_target, const Vector3 &p_up) const;
57 
58 	void scale(const Vector3 &p_scale);
59 	Transform scaled(const Vector3 &p_scale) const;
60 	void scale_basis(const Vector3 &p_scale);
61 	void translate(real_t p_tx, real_t p_ty, real_t p_tz);
62 	void translate(const Vector3 &p_translation);
63 	Transform translated(const Vector3 &p_translation) const;
64 
get_basis()65 	const Matrix3 &get_basis() const { return basis; }
set_basis(const Matrix3 & p_basis)66 	void set_basis(const Matrix3 &p_basis) { basis = p_basis; }
67 
get_origin()68 	const Vector3 &get_origin() const { return origin; }
set_origin(const Vector3 & p_origin)69 	void set_origin(const Vector3 &p_origin) { origin = p_origin; }
70 
71 	void orthonormalize();
72 	Transform orthonormalized() const;
73 
74 	bool operator==(const Transform &p_transform) const;
75 	bool operator!=(const Transform &p_transform) const;
76 
77 	_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
78 	_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const;
79 
80 	_FORCE_INLINE_ Plane xform(const Plane &p_plane) const;
81 	_FORCE_INLINE_ Plane xform_inv(const Plane &p_plane) const;
82 
83 	_FORCE_INLINE_ AABB xform(const AABB &p_aabb) const;
84 	_FORCE_INLINE_ AABB xform_inv(const AABB &p_aabb) const;
85 
86 	void operator*=(const Transform &p_transform);
87 	Transform operator*(const Transform &p_transform) const;
88 
89 	Transform interpolate_with(const Transform &p_transform, float p_c) const;
90 
inverse_xform(const Transform & t)91 	_FORCE_INLINE_ Transform inverse_xform(const Transform &t) const {
92 
93 		Vector3 v = t.origin - origin;
94 		return Transform(basis.transpose_xform(t.basis),
95 				basis.xform(v));
96 	}
97 
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)98 	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) {
99 
100 		basis.elements[0][0] = xx;
101 		basis.elements[0][1] = xy;
102 		basis.elements[0][2] = xz;
103 		basis.elements[1][0] = yx;
104 		basis.elements[1][1] = yy;
105 		basis.elements[1][2] = yz;
106 		basis.elements[2][0] = zx;
107 		basis.elements[2][1] = zy;
108 		basis.elements[2][2] = zz;
109 		origin.x = tx;
110 		origin.y = ty;
111 		origin.z = tz;
112 	}
113 
114 	operator String() const;
115 
116 	Transform(const Matrix3 &p_basis, const Vector3 &p_origin = Vector3());
Transform()117 	Transform() {}
118 };
119 
xform(const Vector3 & p_vector)120 _FORCE_INLINE_ Vector3 Transform::xform(const Vector3 &p_vector) const {
121 
122 	return Vector3(
123 			basis[0].dot(p_vector) + origin.x,
124 			basis[1].dot(p_vector) + origin.y,
125 			basis[2].dot(p_vector) + origin.z);
126 }
xform_inv(const Vector3 & p_vector)127 _FORCE_INLINE_ Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
128 
129 	Vector3 v = p_vector - origin;
130 
131 	return Vector3(
132 			(basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z),
133 			(basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z),
134 			(basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z));
135 }
136 
xform(const Plane & p_plane)137 _FORCE_INLINE_ Plane Transform::xform(const Plane &p_plane) const {
138 
139 	Vector3 point = p_plane.normal * p_plane.d;
140 	Vector3 point_dir = point + p_plane.normal;
141 	point = xform(point);
142 	point_dir = xform(point_dir);
143 
144 	Vector3 normal = point_dir - point;
145 	normal.normalize();
146 	real_t d = normal.dot(point);
147 
148 	return Plane(normal, d);
149 }
xform_inv(const Plane & p_plane)150 _FORCE_INLINE_ Plane Transform::xform_inv(const Plane &p_plane) const {
151 
152 	Vector3 point = p_plane.normal * p_plane.d;
153 	Vector3 point_dir = point + p_plane.normal;
154 	xform_inv(point);
155 	xform_inv(point_dir);
156 
157 	Vector3 normal = point_dir - point;
158 	normal.normalize();
159 	real_t d = normal.dot(point);
160 
161 	return Plane(normal, d);
162 }
163 
xform(const AABB & p_aabb)164 _FORCE_INLINE_ AABB Transform::xform(const AABB &p_aabb) const {
165 /* define vertices */
166 #if 1
167 	Vector3 x = basis.get_axis(0) * p_aabb.size.x;
168 	Vector3 y = basis.get_axis(1) * p_aabb.size.y;
169 	Vector3 z = basis.get_axis(2) * p_aabb.size.z;
170 	Vector3 pos = xform(p_aabb.pos);
171 	//could be even further optimized
172 	AABB new_aabb;
173 	new_aabb.pos = pos;
174 	new_aabb.expand_to(pos + x);
175 	new_aabb.expand_to(pos + y);
176 	new_aabb.expand_to(pos + z);
177 	new_aabb.expand_to(pos + x + y);
178 	new_aabb.expand_to(pos + x + z);
179 	new_aabb.expand_to(pos + y + z);
180 	new_aabb.expand_to(pos + x + y + z);
181 	return new_aabb;
182 #else
183 
184 	Vector3 vertices[8] = {
185 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z + p_aabb.size.z),
186 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z),
187 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z + p_aabb.size.z),
188 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z),
189 		Vector3(p_aabb.pos.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z + p_aabb.size.z),
190 		Vector3(p_aabb.pos.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z),
191 		Vector3(p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z + p_aabb.size.z),
192 		Vector3(p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z)
193 	};
194 
195 	AABB ret;
196 
197 	ret.pos = xform(vertices[0]);
198 
199 	for (int i = 1; i < 8; i++) {
200 
201 		ret.expand_to(xform(vertices[i]));
202 	}
203 
204 	return ret;
205 #endif
206 }
xform_inv(const AABB & p_aabb)207 _FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const {
208 
209 	/* define vertices */
210 	Vector3 vertices[8] = {
211 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z + p_aabb.size.z),
212 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z),
213 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z + p_aabb.size.z),
214 		Vector3(p_aabb.pos.x + p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z),
215 		Vector3(p_aabb.pos.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z + p_aabb.size.z),
216 		Vector3(p_aabb.pos.x, p_aabb.pos.y + p_aabb.size.y, p_aabb.pos.z),
217 		Vector3(p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z + p_aabb.size.z),
218 		Vector3(p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z)
219 	};
220 
221 	AABB ret;
222 
223 	ret.pos = xform_inv(vertices[0]);
224 
225 	for (int i = 1; i < 8; i++) {
226 
227 		ret.expand_to(xform_inv(vertices[i]));
228 	}
229 
230 	return ret;
231 }
232 
233 #ifdef OPTIMIZED_TRANSFORM_IMPL_OVERRIDE
234 
235 #else
236 
237 struct OptimizedTransform {
238 
239 	Transform transform;
240 
invertOptimizedTransform241 	_FORCE_INLINE_ void invert() { transform.invert(); }
affine_invertOptimizedTransform242 	_FORCE_INLINE_ void affine_invert() { transform.affine_invert(); }
xformOptimizedTransform243 	_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec) const { return transform.xform(p_vec); };
xform_invOptimizedTransform244 	_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vec) const { return transform.xform_inv(p_vec); };
245 	_FORCE_INLINE_ OptimizedTransform operator*(const OptimizedTransform &p_ot) const { return OptimizedTransform(transform * p_ot.transform); }
get_transformOptimizedTransform246 	_FORCE_INLINE_ Transform get_transform() const { return transform; }
set_transformOptimizedTransform247 	_FORCE_INLINE_ void set_transform(const Transform &p_transform) { transform = p_transform; }
248 
OptimizedTransformOptimizedTransform249 	OptimizedTransform(const Transform &p_transform) {
250 		transform = p_transform;
251 	}
252 };
253 
254 #endif
255 
256 #endif
257