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