Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/math/basis.cpp
9903 views
1
/**************************************************************************/
2
/* basis.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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
31
#include "basis.h"
32
33
#include "core/math/math_funcs.h"
34
#include "core/string/ustring.h"
35
36
#define cofac(row1, col1, row2, col2) \
37
(rows[row1][col1] * rows[row2][col2] - rows[row1][col2] * rows[row2][col1])
38
39
void Basis::invert() {
40
real_t co[3] = {
41
cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
42
};
43
real_t det = rows[0][0] * co[0] +
44
rows[0][1] * co[1] +
45
rows[0][2] * co[2];
46
#ifdef MATH_CHECKS
47
ERR_FAIL_COND(det == 0);
48
#endif
49
real_t s = 1.0f / det;
50
51
set(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
52
co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
53
co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
54
}
55
56
void Basis::orthonormalize() {
57
// Gram-Schmidt Process
58
59
Vector3 x = get_column(0);
60
Vector3 y = get_column(1);
61
Vector3 z = get_column(2);
62
63
x.normalize();
64
y = (y - x * (x.dot(y)));
65
y.normalize();
66
z = (z - x * (x.dot(z)) - y * (y.dot(z)));
67
z.normalize();
68
69
set_column(0, x);
70
set_column(1, y);
71
set_column(2, z);
72
}
73
74
Basis Basis::orthonormalized() const {
75
Basis c = *this;
76
c.orthonormalize();
77
return c;
78
}
79
80
void Basis::orthogonalize() {
81
Vector3 scl = get_scale();
82
orthonormalize();
83
scale_local(scl);
84
}
85
86
Basis Basis::orthogonalized() const {
87
Basis c = *this;
88
c.orthogonalize();
89
return c;
90
}
91
92
// Returns true if the basis vectors are orthogonal (perpendicular), so it has no skew or shear, and can be decomposed into rotation and scale.
93
// See https://en.wikipedia.org/wiki/Orthogonal_basis
94
bool Basis::is_orthogonal() const {
95
const Vector3 x = get_column(0);
96
const Vector3 y = get_column(1);
97
const Vector3 z = get_column(2);
98
return Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
99
}
100
101
// Returns true if the basis vectors are orthonormal (orthogonal and normalized), so it has no scale, skew, or shear.
102
// See https://en.wikipedia.org/wiki/Orthonormal_basis
103
bool Basis::is_orthonormal() const {
104
const Vector3 x = get_column(0);
105
const Vector3 y = get_column(1);
106
const Vector3 z = get_column(2);
107
return Math::is_equal_approx(x.length_squared(), 1) && Math::is_equal_approx(y.length_squared(), 1) && Math::is_equal_approx(z.length_squared(), 1) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
108
}
109
110
// Returns true if the basis is conformal (orthogonal, uniform scale, preserves angles and distance ratios).
111
// See https://en.wikipedia.org/wiki/Conformal_linear_transformation
112
bool Basis::is_conformal() const {
113
const Vector3 x = get_column(0);
114
const Vector3 y = get_column(1);
115
const Vector3 z = get_column(2);
116
const real_t x_len_sq = x.length_squared();
117
return Math::is_equal_approx(x_len_sq, y.length_squared()) && Math::is_equal_approx(x_len_sq, z.length_squared()) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z));
118
}
119
120
// Returns true if the basis only has diagonal elements, so it may only have scale or flip, but no rotation, skew, or shear.
121
bool Basis::is_diagonal() const {
122
return (
123
Math::is_zero_approx(rows[0][1]) && Math::is_zero_approx(rows[0][2]) &&
124
Math::is_zero_approx(rows[1][0]) && Math::is_zero_approx(rows[1][2]) &&
125
Math::is_zero_approx(rows[2][0]) && Math::is_zero_approx(rows[2][1]));
126
}
127
128
// Returns true if the basis is a pure rotation matrix, so it has no scale, skew, shear, or flip.
129
bool Basis::is_rotation() const {
130
return is_conformal() && Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON);
131
}
132
133
#ifdef MATH_CHECKS
134
// This method is only used once, in diagonalize. If it's desired elsewhere, feel free to remove the #ifdef.
135
bool Basis::is_symmetric() const {
136
if (!Math::is_equal_approx(rows[0][1], rows[1][0])) {
137
return false;
138
}
139
if (!Math::is_equal_approx(rows[0][2], rows[2][0])) {
140
return false;
141
}
142
if (!Math::is_equal_approx(rows[1][2], rows[2][1])) {
143
return false;
144
}
145
146
return true;
147
}
148
#endif
149
150
Basis Basis::diagonalize() {
151
// NOTE: only implemented for symmetric matrices
152
// with the Jacobi iterative method
153
#ifdef MATH_CHECKS
154
ERR_FAIL_COND_V(!is_symmetric(), Basis());
155
#endif
156
const int ite_max = 1024;
157
158
real_t off_matrix_norm_2 = rows[0][1] * rows[0][1] + rows[0][2] * rows[0][2] + rows[1][2] * rows[1][2];
159
160
int ite = 0;
161
Basis acc_rot;
162
while (off_matrix_norm_2 > (real_t)CMP_EPSILON2 && ite++ < ite_max) {
163
real_t el01_2 = rows[0][1] * rows[0][1];
164
real_t el02_2 = rows[0][2] * rows[0][2];
165
real_t el12_2 = rows[1][2] * rows[1][2];
166
// Find the pivot element
167
int i, j;
168
if (el01_2 > el02_2) {
169
if (el12_2 > el01_2) {
170
i = 1;
171
j = 2;
172
} else {
173
i = 0;
174
j = 1;
175
}
176
} else {
177
if (el12_2 > el02_2) {
178
i = 1;
179
j = 2;
180
} else {
181
i = 0;
182
j = 2;
183
}
184
}
185
186
// Compute the rotation angle
187
real_t angle;
188
if (Math::is_equal_approx(rows[j][j], rows[i][i])) {
189
angle = Math::PI / 4;
190
} else {
191
angle = 0.5f * Math::atan(2 * rows[i][j] / (rows[j][j] - rows[i][i]));
192
}
193
194
// Compute the rotation matrix
195
Basis rot;
196
rot.rows[i][i] = rot.rows[j][j] = Math::cos(angle);
197
rot.rows[i][j] = -(rot.rows[j][i] = Math::sin(angle));
198
199
// Update the off matrix norm
200
off_matrix_norm_2 -= rows[i][j] * rows[i][j];
201
202
// Apply the rotation
203
*this = rot * *this * rot.transposed();
204
acc_rot = rot * acc_rot;
205
}
206
207
return acc_rot;
208
}
209
210
Basis Basis::inverse() const {
211
Basis inv = *this;
212
inv.invert();
213
return inv;
214
}
215
216
void Basis::transpose() {
217
SWAP(rows[0][1], rows[1][0]);
218
SWAP(rows[0][2], rows[2][0]);
219
SWAP(rows[1][2], rows[2][1]);
220
}
221
222
Basis Basis::transposed() const {
223
Basis tr = *this;
224
tr.transpose();
225
return tr;
226
}
227
228
Basis Basis::from_scale(const Vector3 &p_scale) {
229
return Basis(p_scale.x, 0, 0, 0, p_scale.y, 0, 0, 0, p_scale.z);
230
}
231
232
// Multiplies the matrix from left by the scaling matrix: M -> S.M
233
// See the comment for Basis::rotated for further explanation.
234
void Basis::scale(const Vector3 &p_scale) {
235
rows[0] *= p_scale.x;
236
rows[1] *= p_scale.y;
237
rows[2] *= p_scale.z;
238
}
239
240
Basis Basis::scaled(const Vector3 &p_scale) const {
241
Basis m = *this;
242
m.scale(p_scale);
243
return m;
244
}
245
246
void Basis::scale_local(const Vector3 &p_scale) {
247
// performs a scaling in object-local coordinate system:
248
// M -> (M.S.Minv).M = M.S.
249
rows[0] *= p_scale;
250
rows[1] *= p_scale;
251
rows[2] *= p_scale;
252
}
253
254
void Basis::scale_orthogonal(const Vector3 &p_scale) {
255
*this = scaled_orthogonal(p_scale);
256
}
257
258
Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const {
259
Basis m = *this;
260
Vector3 s = Vector3(-1, -1, -1) + p_scale;
261
bool sign = std::signbit(s.x + s.y + s.z);
262
Basis b = m.orthonormalized();
263
s = b.xform_inv(s);
264
Vector3 dots;
265
for (int i = 0; i < 3; i++) {
266
for (int j = 0; j < 3; j++) {
267
dots[j] += s[i] * Math::abs(m.get_column(i).normalized().dot(b.get_column(j)));
268
}
269
}
270
if (sign != std::signbit(dots.x + dots.y + dots.z)) {
271
dots = -dots;
272
}
273
m.scale_local(Vector3(1, 1, 1) + dots);
274
return m;
275
}
276
277
real_t Basis::get_uniform_scale() const {
278
return (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f;
279
}
280
281
Basis Basis::scaled_local(const Vector3 &p_scale) const {
282
Basis m = *this;
283
m.scale_local(p_scale);
284
return m;
285
}
286
287
Vector3 Basis::get_scale_abs() const {
288
return Vector3(
289
Vector3(rows[0][0], rows[1][0], rows[2][0]).length(),
290
Vector3(rows[0][1], rows[1][1], rows[2][1]).length(),
291
Vector3(rows[0][2], rows[1][2], rows[2][2]).length());
292
}
293
294
Vector3 Basis::get_scale_global() const {
295
real_t det_sign = SIGN(determinant());
296
return det_sign * Vector3(rows[0].length(), rows[1].length(), rows[2].length());
297
}
298
299
// get_scale works with get_rotation, use get_scale_abs if you need to enforce positive signature.
300
Vector3 Basis::get_scale() const {
301
// FIXME: We are assuming M = R.S (R is rotation and S is scaling), and use polar decomposition to extract R and S.
302
// A polar decomposition is M = O.P, where O is an orthogonal matrix (meaning rotation and reflection) and
303
// P is a positive semi-definite matrix (meaning it contains absolute values of scaling along its diagonal).
304
//
305
// Despite being different from what we want to achieve, we can nevertheless make use of polar decomposition
306
// here as follows. We can split O into a rotation and a reflection as O = R.Q, and obtain M = R.S where
307
// we defined S = Q.P. Now, R is a proper rotation matrix and S is a (signed) scaling matrix,
308
// which can involve negative scalings. However, there is a catch: unlike the polar decomposition of M = O.P,
309
// the decomposition of O into a rotation and reflection matrix as O = R.Q is not unique.
310
// Therefore, we are going to do this decomposition by sticking to a particular convention.
311
// This may lead to confusion for some users though.
312
//
313
// The convention we use here is to absorb the sign flip into the scaling matrix.
314
// The same convention is also used in other similar functions such as get_rotation_axis_angle, get_rotation, ...
315
//
316
// A proper way to get rid of this issue would be to store the scaling values (or at least their signs)
317
// as a part of Basis. However, if we go that path, we need to disable direct (write) access to the
318
// matrix elements.
319
//
320
// The rotation part of this decomposition is returned by get_rotation* functions.
321
real_t det_sign = SIGN(determinant());
322
return det_sign * get_scale_abs();
323
}
324
325
// Decomposes a Basis into a rotation-reflection matrix (an element of the group O(3)) and a positive scaling matrix as B = O.S.
326
// Returns the rotation-reflection matrix via reference argument, and scaling information is returned as a Vector3.
327
// This (internal) function is too specific and named too ugly to expose to users, and probably there's no need to do so.
328
Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const {
329
#ifdef MATH_CHECKS
330
ERR_FAIL_COND_V(determinant() == 0, Vector3());
331
332
Basis m = transposed() * (*this);
333
ERR_FAIL_COND_V(!m.is_diagonal(), Vector3());
334
#endif
335
Vector3 scale = get_scale();
336
Basis inv_scale = Basis().scaled(scale.inverse()); // this will also absorb the sign of scale
337
rotref = (*this) * inv_scale;
338
339
#ifdef MATH_CHECKS
340
ERR_FAIL_COND_V(!rotref.is_orthogonal(), Vector3());
341
#endif
342
return scale.abs();
343
}
344
345
// Multiplies the matrix from left by the rotation matrix: M -> R.M
346
// Note that this does *not* rotate the matrix itself.
347
//
348
// The main use of Basis is as Transform.basis, which is used by the transformation matrix
349
// of 3D object. Rotate here refers to rotation of the object (which is R * (*this)),
350
// not the matrix itself (which is R * (*this) * R.transposed()).
351
Basis Basis::rotated(const Vector3 &p_axis, real_t p_angle) const {
352
return Basis(p_axis, p_angle) * (*this);
353
}
354
355
void Basis::rotate(const Vector3 &p_axis, real_t p_angle) {
356
*this = rotated(p_axis, p_angle);
357
}
358
359
void Basis::rotate_local(const Vector3 &p_axis, real_t p_angle) {
360
// performs a rotation in object-local coordinate system:
361
// M -> (M.R.Minv).M = M.R.
362
*this = rotated_local(p_axis, p_angle);
363
}
364
365
Basis Basis::rotated_local(const Vector3 &p_axis, real_t p_angle) const {
366
return (*this) * Basis(p_axis, p_angle);
367
}
368
369
Basis Basis::rotated(const Vector3 &p_euler, EulerOrder p_order) const {
370
return Basis::from_euler(p_euler, p_order) * (*this);
371
}
372
373
void Basis::rotate(const Vector3 &p_euler, EulerOrder p_order) {
374
*this = rotated(p_euler, p_order);
375
}
376
377
Basis Basis::rotated(const Quaternion &p_quaternion) const {
378
return Basis(p_quaternion) * (*this);
379
}
380
381
void Basis::rotate(const Quaternion &p_quaternion) {
382
*this = rotated(p_quaternion);
383
}
384
385
Vector3 Basis::get_euler_normalized(EulerOrder p_order) const {
386
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
387
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
388
// See the comment in get_scale() for further information.
389
Basis m = orthonormalized();
390
real_t det = m.determinant();
391
if (det < 0) {
392
// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
393
m.scale(Vector3(-1, -1, -1));
394
}
395
396
return m.get_euler(p_order);
397
}
398
399
Quaternion Basis::get_rotation_quaternion() const {
400
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
401
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
402
// See the comment in get_scale() for further information.
403
Basis m = orthonormalized();
404
real_t det = m.determinant();
405
if (det < 0) {
406
// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
407
m.scale(Vector3(-1, -1, -1));
408
}
409
410
return m.get_quaternion();
411
}
412
413
void Basis::rotate_to_align(Vector3 p_start_direction, Vector3 p_end_direction) {
414
// Takes two vectors and rotates the basis from the first vector to the second vector.
415
// Adopted from: https://gist.github.com/kevinmoran/b45980723e53edeb8a5a43c49f134724
416
const Vector3 axis = p_start_direction.cross(p_end_direction).normalized();
417
if (axis.length_squared() != 0) {
418
real_t dot = p_start_direction.dot(p_end_direction);
419
dot = CLAMP(dot, -1.0f, 1.0f);
420
const real_t angle_rads = Math::acos(dot);
421
*this = Basis(axis, angle_rads) * (*this);
422
}
423
}
424
425
void Basis::get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const {
426
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
427
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
428
// See the comment in get_scale() for further information.
429
Basis m = orthonormalized();
430
real_t det = m.determinant();
431
if (det < 0) {
432
// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
433
m.scale(Vector3(-1, -1, -1));
434
}
435
436
m.get_axis_angle(p_axis, p_angle);
437
}
438
439
void Basis::get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const {
440
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
441
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
442
// See the comment in get_scale() for further information.
443
Basis m = transposed();
444
m.orthonormalize();
445
real_t det = m.determinant();
446
if (det < 0) {
447
// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
448
m.scale(Vector3(-1, -1, -1));
449
}
450
451
m.get_axis_angle(p_axis, p_angle);
452
p_angle = -p_angle;
453
}
454
455
Vector3 Basis::get_euler(EulerOrder p_order) const {
456
// This epsilon value results in angles within a +/- 0.04 degree range being simplified/truncated.
457
// Based on testing, this is the largest the epsilon can be without the angle truncation becoming
458
// visually noticeable.
459
const real_t epsilon = 0.00000025;
460
461
switch (p_order) {
462
case EulerOrder::XYZ: {
463
// Euler angles in XYZ convention.
464
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
465
//
466
// rot = cy*cz -cy*sz sy
467
// cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
468
// -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
469
470
Vector3 euler;
471
real_t sy = rows[0][2];
472
if (sy < (1.0f - epsilon)) {
473
if (sy > -(1.0f - epsilon)) {
474
// is this a pure Y rotation?
475
if (rows[1][0] == 0 && rows[0][1] == 0 && rows[1][2] == 0 && rows[2][1] == 0 && rows[1][1] == 1) {
476
// return the simplest form (human friendlier in editor and scripts)
477
euler.x = 0;
478
euler.y = std::atan2(rows[0][2], rows[0][0]);
479
euler.z = 0;
480
} else {
481
euler.x = Math::atan2(-rows[1][2], rows[2][2]);
482
euler.y = Math::asin(sy);
483
euler.z = Math::atan2(-rows[0][1], rows[0][0]);
484
}
485
} else {
486
euler.x = Math::atan2(rows[2][1], rows[1][1]);
487
euler.y = -Math::PI / 2.0f;
488
euler.z = 0.0f;
489
}
490
} else {
491
euler.x = Math::atan2(rows[2][1], rows[1][1]);
492
euler.y = Math::PI / 2.0f;
493
euler.z = 0.0f;
494
}
495
return euler;
496
}
497
case EulerOrder::XZY: {
498
// Euler angles in XZY convention.
499
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
500
//
501
// rot = cz*cy -sz cz*sy
502
// sx*sy+cx*cy*sz cx*cz cx*sz*sy-cy*sx
503
// cy*sx*sz cz*sx cx*cy+sx*sz*sy
504
505
Vector3 euler;
506
real_t sz = rows[0][1];
507
if (sz < (1.0f - epsilon)) {
508
if (sz > -(1.0f - epsilon)) {
509
euler.x = Math::atan2(rows[2][1], rows[1][1]);
510
euler.y = Math::atan2(rows[0][2], rows[0][0]);
511
euler.z = Math::asin(-sz);
512
} else {
513
// It's -1
514
euler.x = -Math::atan2(rows[1][2], rows[2][2]);
515
euler.y = 0.0f;
516
euler.z = Math::PI / 2.0f;
517
}
518
} else {
519
// It's 1
520
euler.x = -Math::atan2(rows[1][2], rows[2][2]);
521
euler.y = 0.0f;
522
euler.z = -Math::PI / 2.0f;
523
}
524
return euler;
525
}
526
case EulerOrder::YXZ: {
527
// Euler angles in YXZ convention.
528
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
529
//
530
// rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
531
// cx*sz cx*cz -sx
532
// cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx
533
534
Vector3 euler;
535
536
real_t m12 = rows[1][2];
537
538
if (m12 < (1 - epsilon)) {
539
if (m12 > -(1 - epsilon)) {
540
// is this a pure X rotation?
541
if (rows[1][0] == 0 && rows[0][1] == 0 && rows[0][2] == 0 && rows[2][0] == 0 && rows[0][0] == 1) {
542
// return the simplest form (human friendlier in editor and scripts)
543
euler.x = std::atan2(-m12, rows[1][1]);
544
euler.y = 0;
545
euler.z = 0;
546
} else {
547
euler.x = std::asin(-m12);
548
euler.y = std::atan2(rows[0][2], rows[2][2]);
549
euler.z = std::atan2(rows[1][0], rows[1][1]);
550
}
551
} else { // m12 == -1
552
euler.x = Math::PI * 0.5f;
553
euler.y = std::atan2(rows[0][1], rows[0][0]);
554
euler.z = 0;
555
}
556
} else { // m12 == 1
557
euler.x = -Math::PI * 0.5f;
558
euler.y = -std::atan2(rows[0][1], rows[0][0]);
559
euler.z = 0;
560
}
561
562
return euler;
563
}
564
case EulerOrder::YZX: {
565
// Euler angles in YZX convention.
566
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
567
//
568
// rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
569
// sz cz*cx -cz*sx
570
// -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
571
572
Vector3 euler;
573
real_t sz = rows[1][0];
574
if (sz < (1.0f - epsilon)) {
575
if (sz > -(1.0f - epsilon)) {
576
euler.x = Math::atan2(-rows[1][2], rows[1][1]);
577
euler.y = Math::atan2(-rows[2][0], rows[0][0]);
578
euler.z = Math::asin(sz);
579
} else {
580
// It's -1
581
euler.x = Math::atan2(rows[2][1], rows[2][2]);
582
euler.y = 0.0f;
583
euler.z = -Math::PI / 2.0f;
584
}
585
} else {
586
// It's 1
587
euler.x = Math::atan2(rows[2][1], rows[2][2]);
588
euler.y = 0.0f;
589
euler.z = Math::PI / 2.0f;
590
}
591
return euler;
592
} break;
593
case EulerOrder::ZXY: {
594
// Euler angles in ZXY convention.
595
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
596
//
597
// rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
598
// cy*sz+cz*sx*sy cz*cx sz*sy-cz*cy*sx
599
// -cx*sy sx cx*cy
600
Vector3 euler;
601
real_t sx = rows[2][1];
602
if (sx < (1.0f - epsilon)) {
603
if (sx > -(1.0f - epsilon)) {
604
euler.x = Math::asin(sx);
605
euler.y = Math::atan2(-rows[2][0], rows[2][2]);
606
euler.z = Math::atan2(-rows[0][1], rows[1][1]);
607
} else {
608
// It's -1
609
euler.x = -Math::PI / 2.0f;
610
euler.y = Math::atan2(rows[0][2], rows[0][0]);
611
euler.z = 0;
612
}
613
} else {
614
// It's 1
615
euler.x = Math::PI / 2.0f;
616
euler.y = Math::atan2(rows[0][2], rows[0][0]);
617
euler.z = 0;
618
}
619
return euler;
620
} break;
621
case EulerOrder::ZYX: {
622
// Euler angles in ZYX convention.
623
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
624
//
625
// rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*cy
626
// cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
627
// -sy cy*sx cy*cx
628
Vector3 euler;
629
real_t sy = rows[2][0];
630
if (sy < (1.0f - epsilon)) {
631
if (sy > -(1.0f - epsilon)) {
632
euler.x = Math::atan2(rows[2][1], rows[2][2]);
633
euler.y = Math::asin(-sy);
634
euler.z = Math::atan2(rows[1][0], rows[0][0]);
635
} else {
636
// It's -1
637
euler.x = 0;
638
euler.y = Math::PI / 2.0f;
639
euler.z = -Math::atan2(rows[0][1], rows[1][1]);
640
}
641
} else {
642
// It's 1
643
euler.x = 0;
644
euler.y = -Math::PI / 2.0f;
645
euler.z = -Math::atan2(rows[0][1], rows[1][1]);
646
}
647
return euler;
648
}
649
default: {
650
ERR_FAIL_V_MSG(Vector3(), "Invalid parameter for get_euler(order)");
651
}
652
}
653
return Vector3();
654
}
655
656
void Basis::set_euler(const Vector3 &p_euler, EulerOrder p_order) {
657
real_t c, s;
658
659
c = Math::cos(p_euler.x);
660
s = Math::sin(p_euler.x);
661
Basis xmat(1, 0, 0, 0, c, -s, 0, s, c);
662
663
c = Math::cos(p_euler.y);
664
s = Math::sin(p_euler.y);
665
Basis ymat(c, 0, s, 0, 1, 0, -s, 0, c);
666
667
c = Math::cos(p_euler.z);
668
s = Math::sin(p_euler.z);
669
Basis zmat(c, -s, 0, s, c, 0, 0, 0, 1);
670
671
switch (p_order) {
672
case EulerOrder::XYZ: {
673
*this = xmat * (ymat * zmat);
674
} break;
675
case EulerOrder::XZY: {
676
*this = xmat * zmat * ymat;
677
} break;
678
case EulerOrder::YXZ: {
679
*this = ymat * xmat * zmat;
680
} break;
681
case EulerOrder::YZX: {
682
*this = ymat * zmat * xmat;
683
} break;
684
case EulerOrder::ZXY: {
685
*this = zmat * xmat * ymat;
686
} break;
687
case EulerOrder::ZYX: {
688
*this = zmat * ymat * xmat;
689
} break;
690
default: {
691
ERR_FAIL_MSG("Invalid Euler order parameter.");
692
}
693
}
694
}
695
696
bool Basis::is_equal_approx(const Basis &p_basis) const {
697
return rows[0].is_equal_approx(p_basis.rows[0]) && rows[1].is_equal_approx(p_basis.rows[1]) && rows[2].is_equal_approx(p_basis.rows[2]);
698
}
699
700
bool Basis::is_same(const Basis &p_basis) const {
701
return rows[0].is_same(p_basis.rows[0]) && rows[1].is_same(p_basis.rows[1]) && rows[2].is_same(p_basis.rows[2]);
702
}
703
704
bool Basis::is_finite() const {
705
return rows[0].is_finite() && rows[1].is_finite() && rows[2].is_finite();
706
}
707
708
Basis::operator String() const {
709
return "[X: " + get_column(0).operator String() +
710
", Y: " + get_column(1).operator String() +
711
", Z: " + get_column(2).operator String() + "]";
712
}
713
714
Quaternion Basis::get_quaternion() const {
715
#ifdef MATH_CHECKS
716
ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis " + operator String() + " must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors.");
717
#endif
718
/* Allow getting a quaternion from an unnormalized transform */
719
Basis m = *this;
720
real_t trace = m.rows[0][0] + m.rows[1][1] + m.rows[2][2];
721
real_t temp[4];
722
723
if (trace > 0.0f) {
724
real_t s = Math::sqrt(trace + 1.0f);
725
temp[3] = (s * 0.5f);
726
s = 0.5f / s;
727
728
temp[0] = ((m.rows[2][1] - m.rows[1][2]) * s);
729
temp[1] = ((m.rows[0][2] - m.rows[2][0]) * s);
730
temp[2] = ((m.rows[1][0] - m.rows[0][1]) * s);
731
} else {
732
int i = m.rows[0][0] < m.rows[1][1]
733
? (m.rows[1][1] < m.rows[2][2] ? 2 : 1)
734
: (m.rows[0][0] < m.rows[2][2] ? 2 : 0);
735
int j = (i + 1) % 3;
736
int k = (i + 2) % 3;
737
738
real_t s = Math::sqrt(m.rows[i][i] - m.rows[j][j] - m.rows[k][k] + 1.0f);
739
temp[i] = s * 0.5f;
740
s = 0.5f / s;
741
742
temp[3] = (m.rows[k][j] - m.rows[j][k]) * s;
743
temp[j] = (m.rows[j][i] + m.rows[i][j]) * s;
744
temp[k] = (m.rows[k][i] + m.rows[i][k]) * s;
745
}
746
747
return Quaternion(temp[0], temp[1], temp[2], temp[3]);
748
}
749
750
void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
751
/* checking this is a bad idea, because obtaining from scaled transform is a valid use case
752
#ifdef MATH_CHECKS
753
ERR_FAIL_COND(!is_rotation());
754
#endif
755
*/
756
757
// https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
758
real_t x, y, z; // Variables for result.
759
if (Math::is_zero_approx(rows[0][1] - rows[1][0]) && Math::is_zero_approx(rows[0][2] - rows[2][0]) && Math::is_zero_approx(rows[1][2] - rows[2][1])) {
760
// Singularity found.
761
// First check for identity matrix which must have +1 for all terms in leading diagonal and zero in other terms.
762
if (is_diagonal() && (Math::abs(rows[0][0] + rows[1][1] + rows[2][2] - 3) < 3 * CMP_EPSILON)) {
763
// This singularity is identity matrix so angle = 0.
764
r_axis = Vector3(0, 1, 0);
765
r_angle = 0;
766
return;
767
}
768
// Otherwise this singularity is angle = 180.
769
real_t xx = (rows[0][0] + 1) / 2;
770
real_t yy = (rows[1][1] + 1) / 2;
771
real_t zz = (rows[2][2] + 1) / 2;
772
real_t xy = (rows[0][1] + rows[1][0]) / 4;
773
real_t xz = (rows[0][2] + rows[2][0]) / 4;
774
real_t yz = (rows[1][2] + rows[2][1]) / 4;
775
776
if ((xx > yy) && (xx > zz)) { // rows[0][0] is the largest diagonal term.
777
if (xx < CMP_EPSILON) {
778
x = 0;
779
y = Math::SQRT12;
780
z = Math::SQRT12;
781
} else {
782
x = Math::sqrt(xx);
783
y = xy / x;
784
z = xz / x;
785
}
786
} else if (yy > zz) { // rows[1][1] is the largest diagonal term.
787
if (yy < CMP_EPSILON) {
788
x = Math::SQRT12;
789
y = 0;
790
z = Math::SQRT12;
791
} else {
792
y = Math::sqrt(yy);
793
x = xy / y;
794
z = yz / y;
795
}
796
} else { // rows[2][2] is the largest diagonal term so base result on this.
797
if (zz < CMP_EPSILON) {
798
x = Math::SQRT12;
799
y = Math::SQRT12;
800
z = 0;
801
} else {
802
z = Math::sqrt(zz);
803
x = xz / z;
804
y = yz / z;
805
}
806
}
807
r_axis = Vector3(x, y, z);
808
r_angle = Math::PI;
809
return;
810
}
811
// As we have reached here there are no singularities so we can handle normally.
812
double s = Math::sqrt((rows[2][1] - rows[1][2]) * (rows[2][1] - rows[1][2]) + (rows[0][2] - rows[2][0]) * (rows[0][2] - rows[2][0]) + (rows[1][0] - rows[0][1]) * (rows[1][0] - rows[0][1])); // Used to normalize.
813
814
if (Math::abs(s) < CMP_EPSILON) {
815
// Prevent divide by zero, should not happen if matrix is orthogonal and should be caught by singularity test above.
816
s = 1;
817
}
818
819
x = (rows[2][1] - rows[1][2]) / s;
820
y = (rows[0][2] - rows[2][0]) / s;
821
z = (rows[1][0] - rows[0][1]) / s;
822
823
r_axis = Vector3(x, y, z);
824
// acos does clamping.
825
r_angle = Math::acos((rows[0][0] + rows[1][1] + rows[2][2] - 1) / 2);
826
}
827
828
void Basis::set_quaternion(const Quaternion &p_quaternion) {
829
real_t d = p_quaternion.length_squared();
830
real_t s = 2.0f / d;
831
real_t xs = p_quaternion.x * s, ys = p_quaternion.y * s, zs = p_quaternion.z * s;
832
real_t wx = p_quaternion.w * xs, wy = p_quaternion.w * ys, wz = p_quaternion.w * zs;
833
real_t xx = p_quaternion.x * xs, xy = p_quaternion.x * ys, xz = p_quaternion.x * zs;
834
real_t yy = p_quaternion.y * ys, yz = p_quaternion.y * zs, zz = p_quaternion.z * zs;
835
set(1.0f - (yy + zz), xy - wz, xz + wy,
836
xy + wz, 1.0f - (xx + zz), yz - wx,
837
xz - wy, yz + wx, 1.0f - (xx + yy));
838
}
839
840
void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_angle) {
841
// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle
842
#ifdef MATH_CHECKS
843
ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized.");
844
#endif
845
Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
846
real_t cosine = Math::cos(p_angle);
847
rows[0][0] = axis_sq.x + cosine * (1.0f - axis_sq.x);
848
rows[1][1] = axis_sq.y + cosine * (1.0f - axis_sq.y);
849
rows[2][2] = axis_sq.z + cosine * (1.0f - axis_sq.z);
850
851
real_t sine = Math::sin(p_angle);
852
real_t t = 1 - cosine;
853
854
real_t xyzt = p_axis.x * p_axis.y * t;
855
real_t zyxs = p_axis.z * sine;
856
rows[0][1] = xyzt - zyxs;
857
rows[1][0] = xyzt + zyxs;
858
859
xyzt = p_axis.x * p_axis.z * t;
860
zyxs = p_axis.y * sine;
861
rows[0][2] = xyzt + zyxs;
862
rows[2][0] = xyzt - zyxs;
863
864
xyzt = p_axis.y * p_axis.z * t;
865
zyxs = p_axis.x * sine;
866
rows[1][2] = xyzt - zyxs;
867
rows[2][1] = xyzt + zyxs;
868
}
869
870
void Basis::set_axis_angle_scale(const Vector3 &p_axis, real_t p_angle, const Vector3 &p_scale) {
871
_set_diagonal(p_scale);
872
rotate(p_axis, p_angle);
873
}
874
875
void Basis::set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale, EulerOrder p_order) {
876
_set_diagonal(p_scale);
877
rotate(p_euler, p_order);
878
}
879
880
void Basis::set_quaternion_scale(const Quaternion &p_quaternion, const Vector3 &p_scale) {
881
_set_diagonal(p_scale);
882
rotate(p_quaternion);
883
}
884
885
// This also sets the non-diagonal elements to 0, which is misleading from the
886
// name, so we want this method to be private. Use `from_scale` externally.
887
void Basis::_set_diagonal(const Vector3 &p_diag) {
888
rows[0][0] = p_diag.x;
889
rows[0][1] = 0;
890
rows[0][2] = 0;
891
892
rows[1][0] = 0;
893
rows[1][1] = p_diag.y;
894
rows[1][2] = 0;
895
896
rows[2][0] = 0;
897
rows[2][1] = 0;
898
rows[2][2] = p_diag.z;
899
}
900
901
Basis Basis::lerp(const Basis &p_to, real_t p_weight) const {
902
Basis b;
903
b.rows[0] = rows[0].lerp(p_to.rows[0], p_weight);
904
b.rows[1] = rows[1].lerp(p_to.rows[1], p_weight);
905
b.rows[2] = rows[2].lerp(p_to.rows[2], p_weight);
906
907
return b;
908
}
909
910
Basis Basis::slerp(const Basis &p_to, real_t p_weight) const {
911
//consider scale
912
Quaternion from(*this);
913
Quaternion to(p_to);
914
915
Basis b(from.slerp(to, p_weight));
916
b.rows[0] *= Math::lerp(rows[0].length(), p_to.rows[0].length(), p_weight);
917
b.rows[1] *= Math::lerp(rows[1].length(), p_to.rows[1].length(), p_weight);
918
b.rows[2] *= Math::lerp(rows[2].length(), p_to.rows[2].length(), p_weight);
919
920
return b;
921
}
922
923
void Basis::rotate_sh(real_t *p_values) {
924
// code by John Hable
925
// http://filmicworlds.com/blog/simple-and-fast-spherical-harmonic-rotation/
926
// this code is Public Domain
927
928
const static real_t s_c3 = 0.94617469575; // (3*sqrt(5))/(4*sqrt(pi))
929
const static real_t s_c4 = -0.31539156525; // (-sqrt(5))/(4*sqrt(pi))
930
const static real_t s_c5 = 0.54627421529; // (sqrt(15))/(4*sqrt(pi))
931
932
const static real_t s_c_scale = 1.0 / 0.91529123286551084;
933
const static real_t s_c_scale_inv = 0.91529123286551084;
934
935
const static real_t s_rc2 = 1.5853309190550713 * s_c_scale;
936
const static real_t s_c4_div_c3 = s_c4 / s_c3;
937
const static real_t s_c4_div_c3_x2 = (s_c4 / s_c3) * 2.0;
938
939
const static real_t s_scale_dst2 = s_c3 * s_c_scale_inv;
940
const static real_t s_scale_dst4 = s_c5 * s_c_scale_inv;
941
942
const real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] };
943
944
real_t m00 = rows[0][0];
945
real_t m01 = rows[0][1];
946
real_t m02 = rows[0][2];
947
real_t m10 = rows[1][0];
948
real_t m11 = rows[1][1];
949
real_t m12 = rows[1][2];
950
real_t m20 = rows[2][0];
951
real_t m21 = rows[2][1];
952
real_t m22 = rows[2][2];
953
954
p_values[0] = src[0];
955
p_values[1] = m11 * src[1] - m12 * src[2] + m10 * src[3];
956
p_values[2] = -m21 * src[1] + m22 * src[2] - m20 * src[3];
957
p_values[3] = m01 * src[1] - m02 * src[2] + m00 * src[3];
958
959
real_t sh0 = src[7] + src[8] + src[8] - src[5];
960
real_t sh1 = src[4] + s_rc2 * src[6] + src[7] + src[8];
961
real_t sh2 = src[4];
962
real_t sh3 = -src[7];
963
real_t sh4 = -src[5];
964
965
// Rotations. R0 and R1 just use the raw matrix columns
966
real_t r2x = m00 + m01;
967
real_t r2y = m10 + m11;
968
real_t r2z = m20 + m21;
969
970
real_t r3x = m00 + m02;
971
real_t r3y = m10 + m12;
972
real_t r3z = m20 + m22;
973
974
real_t r4x = m01 + m02;
975
real_t r4y = m11 + m12;
976
real_t r4z = m21 + m22;
977
978
// dense matrix multiplication one column at a time
979
980
// column 0
981
real_t sh0_x = sh0 * m00;
982
real_t sh0_y = sh0 * m10;
983
real_t d0 = sh0_x * m10;
984
real_t d1 = sh0_y * m20;
985
real_t d2 = sh0 * (m20 * m20 + s_c4_div_c3);
986
real_t d3 = sh0_x * m20;
987
real_t d4 = sh0_x * m00 - sh0_y * m10;
988
989
// column 1
990
real_t sh1_x = sh1 * m02;
991
real_t sh1_y = sh1 * m12;
992
d0 += sh1_x * m12;
993
d1 += sh1_y * m22;
994
d2 += sh1 * (m22 * m22 + s_c4_div_c3);
995
d3 += sh1_x * m22;
996
d4 += sh1_x * m02 - sh1_y * m12;
997
998
// column 2
999
real_t sh2_x = sh2 * r2x;
1000
real_t sh2_y = sh2 * r2y;
1001
d0 += sh2_x * r2y;
1002
d1 += sh2_y * r2z;
1003
d2 += sh2 * (r2z * r2z + s_c4_div_c3_x2);
1004
d3 += sh2_x * r2z;
1005
d4 += sh2_x * r2x - sh2_y * r2y;
1006
1007
// column 3
1008
real_t sh3_x = sh3 * r3x;
1009
real_t sh3_y = sh3 * r3y;
1010
d0 += sh3_x * r3y;
1011
d1 += sh3_y * r3z;
1012
d2 += sh3 * (r3z * r3z + s_c4_div_c3_x2);
1013
d3 += sh3_x * r3z;
1014
d4 += sh3_x * r3x - sh3_y * r3y;
1015
1016
// column 4
1017
real_t sh4_x = sh4 * r4x;
1018
real_t sh4_y = sh4 * r4y;
1019
d0 += sh4_x * r4y;
1020
d1 += sh4_y * r4z;
1021
d2 += sh4 * (r4z * r4z + s_c4_div_c3_x2);
1022
d3 += sh4_x * r4z;
1023
d4 += sh4_x * r4x - sh4_y * r4y;
1024
1025
// extra multipliers
1026
p_values[4] = d0;
1027
p_values[5] = -d1;
1028
p_values[6] = d2 * s_scale_dst2;
1029
p_values[7] = -d3;
1030
p_values[8] = d4 * s_scale_dst4;
1031
}
1032
1033
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
1034
#ifdef MATH_CHECKS
1035
ERR_FAIL_COND_V_MSG(p_target.is_zero_approx(), Basis(), "The target vector can't be zero.");
1036
ERR_FAIL_COND_V_MSG(p_up.is_zero_approx(), Basis(), "The up vector can't be zero.");
1037
#endif
1038
Vector3 v_z = p_target.normalized();
1039
if (!p_use_model_front) {
1040
v_z = -v_z;
1041
}
1042
Vector3 v_x = p_up.cross(v_z);
1043
if (v_x.is_zero_approx()) {
1044
WARN_PRINT("Target and up vectors are colinear. This is not advised as it may cause unwanted rotation around local Z axis.");
1045
v_x = p_up.get_any_perpendicular(); // Vectors are almost parallel.
1046
}
1047
v_x.normalize();
1048
Vector3 v_y = v_z.cross(v_x);
1049
1050
Basis basis;
1051
basis.set_columns(v_x, v_y, v_z);
1052
return basis;
1053
}
1054
1055