@lakuna/umath 1.3.9 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/algorithms/approx.d.ts +9 -0
- package/dist/algorithms/approx.d.ts.map +1 -0
- package/dist/algorithms/approx.js +12 -0
- package/dist/algorithms/approx.js.map +1 -0
- package/dist/algorithms/approxRelative.d.ts +9 -0
- package/dist/algorithms/approxRelative.d.ts.map +1 -0
- package/dist/algorithms/approxRelative.js +12 -0
- package/dist/algorithms/approxRelative.js.map +1 -0
- package/dist/algorithms/combinations.d.ts +2 -1
- package/dist/algorithms/combinations.d.ts.map +1 -1
- package/dist/algorithms/combinations.js +2 -1
- package/dist/algorithms/combinations.js.map +1 -1
- package/dist/algorithms/degreesToRadians.d.ts +3 -2
- package/dist/algorithms/degreesToRadians.d.ts.map +1 -1
- package/dist/algorithms/degreesToRadians.js +5 -3
- package/dist/algorithms/degreesToRadians.js.map +1 -1
- package/dist/algorithms/factorial.d.ts +2 -1
- package/dist/algorithms/factorial.d.ts.map +1 -1
- package/dist/algorithms/factorial.js +2 -1
- package/dist/algorithms/factorial.js.map +1 -1
- package/dist/algorithms/fibonacci.d.ts +2 -1
- package/dist/algorithms/fibonacci.d.ts.map +1 -1
- package/dist/algorithms/fibonacci.js +6 -2
- package/dist/algorithms/fibonacci.js.map +1 -1
- package/dist/algorithms/greatestCommonDivisor.d.ts +4 -2
- package/dist/algorithms/greatestCommonDivisor.d.ts.map +1 -1
- package/dist/algorithms/greatestCommonDivisor.js +5 -2
- package/dist/algorithms/greatestCommonDivisor.js.map +1 -1
- package/dist/algorithms/hypergeometricPmf.d.ts +3 -2
- package/dist/algorithms/hypergeometricPmf.d.ts.map +1 -1
- package/dist/algorithms/hypergeometricPmf.js +3 -2
- package/dist/algorithms/hypergeometricPmf.js.map +1 -1
- package/dist/algorithms/isPrime.d.ts +2 -1
- package/dist/algorithms/isPrime.d.ts.map +1 -1
- package/dist/algorithms/isPrime.js +2 -1
- package/dist/algorithms/isPrime.js.map +1 -1
- package/dist/algorithms/permutations.d.ts +2 -1
- package/dist/algorithms/permutations.d.ts.map +1 -1
- package/dist/algorithms/permutations.js +2 -1
- package/dist/algorithms/permutations.js.map +1 -1
- package/dist/algorithms/primeFactorization.d.ts +2 -1
- package/dist/algorithms/primeFactorization.d.ts.map +1 -1
- package/dist/algorithms/primeFactorization.js +2 -1
- package/dist/algorithms/primeFactorization.js.map +1 -1
- package/dist/algorithms/radiansToDegrees.d.ts +3 -2
- package/dist/algorithms/radiansToDegrees.d.ts.map +1 -1
- package/dist/algorithms/radiansToDegrees.js +5 -3
- package/dist/algorithms/radiansToDegrees.js.map +1 -1
- package/dist/algorithms/summation.d.ts +2 -1
- package/dist/algorithms/summation.d.ts.map +1 -1
- package/dist/algorithms/summation.js +2 -1
- package/dist/algorithms/summation.js.map +1 -1
- package/dist/linalg/DualQuaternion.d.ts +102 -32
- package/dist/linalg/DualQuaternion.d.ts.map +1 -1
- package/dist/linalg/DualQuaternion.js +243 -272
- package/dist/linalg/DualQuaternion.js.map +1 -1
- package/dist/linalg/Matrix.d.ts +14 -10
- package/dist/linalg/Matrix.d.ts.map +1 -1
- package/dist/linalg/Matrix2.d.ts +74 -51
- package/dist/linalg/Matrix2.d.ts.map +1 -1
- package/dist/linalg/Matrix2.js +95 -171
- package/dist/linalg/Matrix2.js.map +1 -1
- package/dist/linalg/Matrix3.d.ts +122 -72
- package/dist/linalg/Matrix3.d.ts.map +1 -1
- package/dist/linalg/Matrix3.js +186 -355
- package/dist/linalg/Matrix3.js.map +1 -1
- package/dist/linalg/Matrix4.d.ts +266 -149
- package/dist/linalg/Matrix4.d.ts.map +1 -1
- package/dist/linalg/Matrix4.js +512 -852
- package/dist/linalg/Matrix4.js.map +1 -1
- package/dist/linalg/Quaternion.d.ts +252 -34
- package/dist/linalg/Quaternion.d.ts.map +1 -1
- package/dist/linalg/Quaternion.js +436 -166
- package/dist/linalg/Quaternion.js.map +1 -1
- package/dist/linalg/SlowMatrix.d.ts +10 -9
- package/dist/linalg/SlowMatrix.d.ts.map +1 -1
- package/dist/linalg/SlowMatrix.js +10 -9
- package/dist/linalg/SlowMatrix.js.map +1 -1
- package/dist/linalg/SlowSquareMatrix.d.ts +10 -9
- package/dist/linalg/SlowSquareMatrix.d.ts.map +1 -1
- package/dist/linalg/SlowSquareMatrix.js +10 -9
- package/dist/linalg/SlowSquareMatrix.js.map +1 -1
- package/dist/linalg/SquareMatrix.d.ts +6 -5
- package/dist/linalg/SquareMatrix.d.ts.map +1 -1
- package/dist/linalg/Vector.d.ts +8 -4
- package/dist/linalg/Vector.d.ts.map +1 -1
- package/dist/linalg/Vector2.d.ts +82 -31
- package/dist/linalg/Vector2.d.ts.map +1 -1
- package/dist/linalg/Vector2.js +112 -154
- package/dist/linalg/Vector2.js.map +1 -1
- package/dist/linalg/Vector3.d.ts +93 -41
- package/dist/linalg/Vector3.d.ts.map +1 -1
- package/dist/linalg/Vector3.js +171 -282
- package/dist/linalg/Vector3.js.map +1 -1
- package/dist/linalg/Vector4.d.ts +71 -21
- package/dist/linalg/Vector4.d.ts.map +1 -1
- package/dist/linalg/Vector4.js +121 -195
- package/dist/linalg/Vector4.js.map +1 -1
- package/dist/types/AxisAngle.d.ts +4 -1
- package/dist/types/AxisAngle.d.ts.map +1 -1
- package/dist/types/FieldOfView.d.ts +4 -1
- package/dist/types/FieldOfView.d.ts.map +1 -1
- package/dist/utility/BigNumber.d.ts +4 -1
- package/dist/utility/BigNumber.d.ts.map +1 -1
- package/dist/utility/BigNumber.js +4 -1
- package/dist/utility/BigNumber.js.map +1 -1
- package/dist/utility/MagnitudeError.d.ts +4 -1
- package/dist/utility/MagnitudeError.d.ts.map +1 -1
- package/dist/utility/MagnitudeError.js +4 -1
- package/dist/utility/MagnitudeError.js.map +1 -1
- package/dist/utility/MatrixSizeError.d.ts +4 -1
- package/dist/utility/MatrixSizeError.d.ts.map +1 -1
- package/dist/utility/MatrixSizeError.js +4 -1
- package/dist/utility/MatrixSizeError.js.map +1 -1
- package/dist/utility/PartialMatrixError.d.ts +4 -1
- package/dist/utility/PartialMatrixError.d.ts.map +1 -1
- package/dist/utility/PartialMatrixError.js +4 -1
- package/dist/utility/PartialMatrixError.js.map +1 -1
- package/dist/utility/SingularMatrixError.d.ts +2 -1
- package/dist/utility/SingularMatrixError.d.ts.map +1 -1
- package/dist/utility/SingularMatrixError.js +2 -1
- package/dist/utility/SingularMatrixError.js.map +1 -1
- package/dist/utility/epsilon.d.ts +4 -1
- package/dist/utility/epsilon.d.ts.map +1 -1
- package/dist/utility/epsilon.js +4 -1
- package/dist/utility/epsilon.js.map +1 -1
- package/package.json +11 -11
- package/src/algorithms/approx.ts +12 -0
- package/src/algorithms/approxRelative.ts +12 -0
- package/src/algorithms/combinations.ts +2 -1
- package/src/algorithms/degreesToRadians.ts +6 -3
- package/src/algorithms/factorial.ts +3 -1
- package/src/algorithms/fibonacci.ts +7 -2
- package/src/algorithms/greatestCommonDivisor.ts +9 -4
- package/src/algorithms/hypergeometricPmf.ts +3 -2
- package/src/algorithms/isPrime.ts +2 -1
- package/src/algorithms/permutations.ts +2 -1
- package/src/algorithms/primeFactorization.ts +2 -1
- package/src/algorithms/radiansToDegrees.ts +6 -3
- package/src/algorithms/summation.ts +2 -1
- package/src/linalg/DualQuaternion.ts +424 -289
- package/src/linalg/Matrix.ts +14 -10
- package/src/linalg/Matrix2.ts +141 -188
- package/src/linalg/Matrix3.ts +400 -375
- package/src/linalg/Matrix4.ts +1083 -905
- package/src/linalg/Quaternion.ts +706 -188
- package/src/linalg/SlowMatrix.ts +10 -9
- package/src/linalg/SlowSquareMatrix.ts +10 -9
- package/src/linalg/SquareMatrix.ts +6 -5
- package/src/linalg/Vector.ts +8 -4
- package/src/linalg/Vector2.ts +146 -173
- package/src/linalg/Vector3.ts +293 -326
- package/src/linalg/Vector4.ts +227 -215
- package/src/types/AxisAngle.ts +4 -1
- package/src/types/FieldOfView.ts +4 -1
- package/src/utility/BigNumber.ts +6 -3
- package/src/utility/MagnitudeError.ts +4 -1
- package/src/utility/MatrixSizeError.ts +4 -1
- package/src/utility/PartialMatrixError.ts +4 -1
- package/src/utility/SingularMatrixError.ts +2 -1
- package/src/utility/epsilon.ts +4 -1
package/src/linalg/Quaternion.ts
CHANGED
|
@@ -1,22 +1,38 @@
|
|
|
1
|
-
import { type Matrix3Like, createMatrix3Like } from "./Matrix3.js";
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
type Matrix3Like,
|
|
3
|
+
createMatrix3Like,
|
|
4
|
+
fromValues as matrix3FromValues
|
|
5
|
+
} from "./Matrix3.js";
|
|
6
|
+
import Vector3, {
|
|
7
|
+
type Vector3Like,
|
|
8
|
+
createVector3Like,
|
|
9
|
+
cross as vector3Cross,
|
|
10
|
+
dot as vector3Dot,
|
|
11
|
+
fromValues as vector3FromValues,
|
|
12
|
+
getMagnitude as vector3GetMagnitude,
|
|
13
|
+
normalize as vector3Normalize
|
|
14
|
+
} from "./Vector3.js";
|
|
15
|
+
import {
|
|
16
|
+
add as vector4Add,
|
|
17
|
+
copy as vector4Copy,
|
|
18
|
+
dot as vector4Dot,
|
|
19
|
+
exactEquals as vector4ExactEquals,
|
|
20
|
+
fromValues as vector4FromValues,
|
|
21
|
+
getMagnitude as vector4GetMagnitude,
|
|
22
|
+
getSquaredMagnitude as vector4GetSquaredMagnitude,
|
|
23
|
+
lerp as vector4Lerp,
|
|
24
|
+
normalize as vector4Normalize,
|
|
25
|
+
scale as vector4Scale
|
|
14
26
|
} from "./Vector4.js";
|
|
15
27
|
import type AxisAngle from "../types/AxisAngle.js";
|
|
16
|
-
import type { Vector3Like } from "./Vector3.js";
|
|
17
28
|
import epsilon from "../utility/epsilon.js";
|
|
29
|
+
import radiansToDegrees from "../algorithms/radiansToDegrees.js";
|
|
18
30
|
|
|
19
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* A complex number that is commonly used to describe rotations.
|
|
33
|
+
* @see {@link https://en.wikipedia.org/wiki/Quaternion | Quaternion}
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
20
36
|
export interface QuaternionLike extends Record<number, number> {
|
|
21
37
|
/** The first component of this quaternion. */
|
|
22
38
|
0: number;
|
|
@@ -34,26 +50,167 @@ export interface QuaternionLike extends Record<number, number> {
|
|
|
34
50
|
/**
|
|
35
51
|
* Create a quaternion-like object.
|
|
36
52
|
* @returns A quaternion-like object.
|
|
53
|
+
* @public
|
|
37
54
|
*/
|
|
38
|
-
export const createQuaternionLike = () => {
|
|
55
|
+
export const createQuaternionLike = (): Float32Array & QuaternionLike => {
|
|
39
56
|
return new Float32Array(4) as Float32Array & QuaternionLike;
|
|
40
57
|
};
|
|
41
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Create a quaternion with the given values.
|
|
61
|
+
* @param x - The first component.
|
|
62
|
+
* @param y - The second component.
|
|
63
|
+
* @param z - The third component.
|
|
64
|
+
* @param w - The fourth component.
|
|
65
|
+
* @param out - The quaternion to store the result in.
|
|
66
|
+
* @returns A new quaternion.
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export const fromValues: <T extends QuaternionLike>(
|
|
70
|
+
x: number,
|
|
71
|
+
y: number,
|
|
72
|
+
z: number,
|
|
73
|
+
w: number,
|
|
74
|
+
out: T
|
|
75
|
+
) => T = vector4FromValues;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Add two quaternions.
|
|
79
|
+
* @param a - The first quaternion
|
|
80
|
+
* @param b - The second quaternion.
|
|
81
|
+
* @param out - The quaternion to store the result in.
|
|
82
|
+
* @returns The sum of the quaternions.
|
|
83
|
+
* @public
|
|
84
|
+
*/
|
|
85
|
+
export const add: <T extends QuaternionLike>(
|
|
86
|
+
a: QuaternionLike,
|
|
87
|
+
b: QuaternionLike,
|
|
88
|
+
out: T
|
|
89
|
+
) => T = vector4Add;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Copy the values from one quaternion to another.
|
|
93
|
+
* @param quaternion - The quaternion to copy.
|
|
94
|
+
* @param out - The quaternion to store the result in.
|
|
95
|
+
* @returns The copy.
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
export const copy: <T extends QuaternionLike>(
|
|
99
|
+
quaternion: QuaternionLike,
|
|
100
|
+
out: T
|
|
101
|
+
) => T = vector4Copy;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Calculate the dot product of two quaternions.
|
|
105
|
+
* @param a - The first quaternion
|
|
106
|
+
* @param b - The second quaternion.
|
|
107
|
+
* @returns The dot product.
|
|
108
|
+
* @public
|
|
109
|
+
*/
|
|
110
|
+
export const dot: (a: QuaternionLike, b: QuaternionLike) => number = vector4Dot;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Determine whether or not two unit quaternions point in roughly the same direction.
|
|
114
|
+
* @param a - The first unit quaternion.
|
|
115
|
+
* @param b - The second unit quaternion.
|
|
116
|
+
* @returns Whether or not the unit quaternions point in the same direction.
|
|
117
|
+
* @public
|
|
118
|
+
*/
|
|
119
|
+
export const equals = (a: QuaternionLike, b: QuaternionLike): boolean =>
|
|
120
|
+
Math.abs(dot(a, b)) >= 1 - epsilon;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Determine whether or not two quaternions are exactly equivalent.
|
|
124
|
+
* @param a - The first quaternion.
|
|
125
|
+
* @param b - The second quaternion.
|
|
126
|
+
* @returns Whether or not the quaternions are equivalent.
|
|
127
|
+
* @public
|
|
128
|
+
*/
|
|
129
|
+
export const exactEquals: (a: QuaternionLike, b: QuaternionLike) => boolean =
|
|
130
|
+
vector4ExactEquals;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Calculate the magnitude (length) of a quaternion.
|
|
134
|
+
* @param quaternion - The quaternion.
|
|
135
|
+
* @returns The magnitude.
|
|
136
|
+
* @public
|
|
137
|
+
*/
|
|
138
|
+
export const getMagnitude: (quaternion: QuaternionLike) => number =
|
|
139
|
+
vector4GetMagnitude;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Calculate the squared magnitude (length) of a quaternion.
|
|
143
|
+
* @param quaternion - The quaternion.
|
|
144
|
+
* @returns The squared magnitude.
|
|
145
|
+
* @public
|
|
146
|
+
*/
|
|
147
|
+
export const getSquaredMagnitude: (quaternion: QuaternionLike) => number =
|
|
148
|
+
vector4GetSquaredMagnitude;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Perform a linear interpolation between two quaternions.
|
|
152
|
+
* @param a - The first quaternion.
|
|
153
|
+
* @param b - The second quaternion.
|
|
154
|
+
* @param t - The interpolation amount (in `[0,1]`).
|
|
155
|
+
* @param out - The quaternion to store the result in.
|
|
156
|
+
* @returns The interpolated quaternion.
|
|
157
|
+
* @see {@link https://en.wikipedia.org/wiki/Linear_interpolation | Linear interpolation}
|
|
158
|
+
* @public
|
|
159
|
+
*/
|
|
160
|
+
export const lerp: <T extends QuaternionLike>(
|
|
161
|
+
a: QuaternionLike,
|
|
162
|
+
b: QuaternionLike,
|
|
163
|
+
t: number,
|
|
164
|
+
out: T
|
|
165
|
+
) => T = vector4Lerp;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Normalize a quaternion.
|
|
169
|
+
* @param quaternion - The quaternion.
|
|
170
|
+
* @param out - The quaternion to store the result in.
|
|
171
|
+
* @returns The normalized quaternion.
|
|
172
|
+
* @public
|
|
173
|
+
*/
|
|
174
|
+
export const normalize: <T extends QuaternionLike>(
|
|
175
|
+
vector: QuaternionLike,
|
|
176
|
+
out: T
|
|
177
|
+
) => T = vector4Normalize;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Scale a quaternion by a scalar.
|
|
181
|
+
* @param quaternion - The multiplier.
|
|
182
|
+
* @param scalar - The multiplicand.
|
|
183
|
+
* @param out - The quaternion to store the result in.
|
|
184
|
+
* @returns The product.
|
|
185
|
+
* @public
|
|
186
|
+
*/
|
|
187
|
+
export const scale: <T extends QuaternionLike>(
|
|
188
|
+
vector: QuaternionLike,
|
|
189
|
+
scalar: number,
|
|
190
|
+
out: T
|
|
191
|
+
) => T = vector4Scale;
|
|
192
|
+
|
|
42
193
|
/**
|
|
43
194
|
* Create a quaternion from a three-by-three rotation matrix.
|
|
44
195
|
* @param matrix - The matrix.
|
|
45
196
|
* @param out - The quaternion to store the result in.
|
|
46
|
-
* @returns The quaternion.
|
|
47
|
-
* @see
|
|
197
|
+
* @returns The quaternion (not normalized).
|
|
198
|
+
* @see {@link https://en.wikipedia.org/wiki/Rotation_matrix | Rotation matrix}
|
|
199
|
+
* @see Ken Shoemake. Quaternion calculus and fast animation. SIGGRAPH Course Notes, 10:101-121, 1987.
|
|
200
|
+
* @public
|
|
48
201
|
*/
|
|
49
202
|
export const fromMatrix3 = <T extends QuaternionLike>(
|
|
50
203
|
matrix: Matrix3Like,
|
|
51
204
|
out: T
|
|
52
205
|
): T => {
|
|
53
|
-
const
|
|
206
|
+
const m0 = matrix[0];
|
|
207
|
+
const m4 = matrix[4];
|
|
208
|
+
const m8 = matrix[8];
|
|
209
|
+
|
|
210
|
+
const fTrace = m0 + m4 + m8;
|
|
54
211
|
if (fTrace > 0) {
|
|
55
212
|
let fRoot = Math.sqrt(fTrace + 1);
|
|
56
|
-
out[3] =
|
|
213
|
+
out[3] = fRoot / 2;
|
|
57
214
|
fRoot = 0.5 / fRoot;
|
|
58
215
|
out[0] = (matrix[5] - matrix[7]) * fRoot;
|
|
59
216
|
out[1] = (matrix[6] - matrix[2]) * fRoot;
|
|
@@ -62,10 +219,10 @@ export const fromMatrix3 = <T extends QuaternionLike>(
|
|
|
62
219
|
}
|
|
63
220
|
|
|
64
221
|
let i = 0 as 0 | 1 | 2;
|
|
65
|
-
if (
|
|
222
|
+
if (m4 > m0) {
|
|
66
223
|
i = 1;
|
|
67
224
|
}
|
|
68
|
-
if (
|
|
225
|
+
if (m8 > matrix[(i * 3 + i) as 0 | 4]) {
|
|
69
226
|
i = 2;
|
|
70
227
|
}
|
|
71
228
|
const j = ((i + 1) % 3) as 1 | 2 | 0;
|
|
@@ -77,7 +234,7 @@ export const fromMatrix3 = <T extends QuaternionLike>(
|
|
|
77
234
|
matrix[(k * 3 + k) as 7 | 0 | 4] +
|
|
78
235
|
1
|
|
79
236
|
);
|
|
80
|
-
out[i] =
|
|
237
|
+
out[i] = fRoot / 2;
|
|
81
238
|
fRoot = 0.5 / fRoot;
|
|
82
239
|
out[3] =
|
|
83
240
|
(matrix[(j * 3 + k) as 5 | 6 | 1] - matrix[(k * 3 + j) as 7 | 2 | 3]) *
|
|
@@ -91,26 +248,68 @@ export const fromMatrix3 = <T extends QuaternionLike>(
|
|
|
91
248
|
return out;
|
|
92
249
|
};
|
|
93
250
|
|
|
251
|
+
const ratio = Math.PI / 360;
|
|
252
|
+
|
|
94
253
|
/**
|
|
95
|
-
* Create a quaternion from equivalent
|
|
96
|
-
* @param x - The X angle.
|
|
97
|
-
* @param y - The Y angle.
|
|
98
|
-
* @param z - The Z angle.
|
|
254
|
+
* Create a quaternion from equivalent x-y'-z" (intrinsic) Tait-Bryan angles.
|
|
255
|
+
* @param x - The X angle in degrees.
|
|
256
|
+
* @param y - The Y angle in degrees.
|
|
257
|
+
* @param z - The Z angle in degrees.
|
|
99
258
|
* @param out - The quaternion to store the result in.
|
|
100
259
|
* @returns The quaternion.
|
|
101
|
-
* @see
|
|
260
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
261
|
+
* @public
|
|
102
262
|
*/
|
|
103
|
-
export const
|
|
263
|
+
export const fromEulerXyz = <T extends QuaternionLike>(
|
|
104
264
|
x: number,
|
|
105
265
|
y: number,
|
|
106
266
|
z: number,
|
|
107
267
|
out: T
|
|
108
268
|
): T => {
|
|
109
|
-
const
|
|
269
|
+
const x2 = x * ratio;
|
|
270
|
+
const y2 = y * ratio;
|
|
271
|
+
const z2 = z * ratio;
|
|
272
|
+
|
|
273
|
+
const sx = Math.sin(x2);
|
|
274
|
+
const cx = Math.cos(x2);
|
|
275
|
+
const sy = Math.sin(y2);
|
|
276
|
+
const cy = Math.cos(y2);
|
|
277
|
+
const sz = Math.sin(z2);
|
|
278
|
+
const cz = Math.cos(z2);
|
|
110
279
|
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
const
|
|
280
|
+
const sxcy = sx * cy;
|
|
281
|
+
const cxsy = cx * sy;
|
|
282
|
+
const cxcy = cx * cy;
|
|
283
|
+
const sxsy = sx * sy;
|
|
284
|
+
|
|
285
|
+
return fromValues(
|
|
286
|
+
sxcy * cz - cxsy * sz,
|
|
287
|
+
cxsy * cz + sxcy * sz,
|
|
288
|
+
cxcy * sz - sxsy * cz,
|
|
289
|
+
cxcy * cz + sxsy * sz,
|
|
290
|
+
out
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Create a quaternion from equivalent x-z'-y" (intrinsic) Tait-Bryan angles.
|
|
296
|
+
* @param x - The X angle in degrees.
|
|
297
|
+
* @param z - The Z angle in degrees.
|
|
298
|
+
* @param y - The Y angle in degrees.
|
|
299
|
+
* @param out - The quaternion to store the result in.
|
|
300
|
+
* @returns The quaternion.
|
|
301
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
302
|
+
* @public
|
|
303
|
+
*/
|
|
304
|
+
export const fromEulerXzy = <T extends QuaternionLike>(
|
|
305
|
+
x: number,
|
|
306
|
+
z: number,
|
|
307
|
+
y: number,
|
|
308
|
+
out: T
|
|
309
|
+
): T => {
|
|
310
|
+
const x2 = x * ratio;
|
|
311
|
+
const y2 = y * ratio;
|
|
312
|
+
const z2 = z * ratio;
|
|
114
313
|
|
|
115
314
|
const sx = Math.sin(x2);
|
|
116
315
|
const cx = Math.cos(x2);
|
|
@@ -119,60 +318,297 @@ export const fromEuler = <T extends QuaternionLike>(
|
|
|
119
318
|
const sz = Math.sin(z2);
|
|
120
319
|
const cz = Math.cos(z2);
|
|
121
320
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
321
|
+
const sxcy = sx * cy;
|
|
322
|
+
const cxsy = cx * sy;
|
|
323
|
+
const cxcy = cx * cy;
|
|
324
|
+
const sxsy = sx * sy;
|
|
325
|
+
|
|
326
|
+
return fromValues(
|
|
327
|
+
sxcy * cz - cxsy * sz,
|
|
328
|
+
cxsy * cz - sxcy * sz,
|
|
329
|
+
cxcy * sz + sxsy * cz,
|
|
330
|
+
cxcy * cz + sxsy * sz,
|
|
331
|
+
out
|
|
332
|
+
);
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Create a quaternion from equivalent y-x'-z" (intrinsic) Tait-Bryan angles.
|
|
337
|
+
* @param y - The Y angle in degrees.
|
|
338
|
+
* @param x - The X angle in degrees.
|
|
339
|
+
* @param z - The Z angle in degrees.
|
|
340
|
+
* @param out - The quaternion to store the result in.
|
|
341
|
+
* @returns The quaternion.
|
|
342
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
343
|
+
* @public
|
|
344
|
+
*/
|
|
345
|
+
export const fromEulerYxz = <T extends QuaternionLike>(
|
|
346
|
+
y: number,
|
|
347
|
+
x: number,
|
|
348
|
+
z: number,
|
|
349
|
+
out: T
|
|
350
|
+
): T => {
|
|
351
|
+
const x2 = x * ratio;
|
|
352
|
+
const y2 = y * ratio;
|
|
353
|
+
const z2 = z * ratio;
|
|
354
|
+
|
|
355
|
+
const sx = Math.sin(x2);
|
|
356
|
+
const cx = Math.cos(x2);
|
|
357
|
+
const sy = Math.sin(y2);
|
|
358
|
+
const cy = Math.cos(y2);
|
|
359
|
+
const sz = Math.sin(z2);
|
|
360
|
+
const cz = Math.cos(z2);
|
|
361
|
+
|
|
362
|
+
const sxcy = sx * cy;
|
|
363
|
+
const cxsy = cx * sy;
|
|
364
|
+
const cxcy = cx * cy;
|
|
365
|
+
const sxsy = sx * sy;
|
|
366
|
+
|
|
367
|
+
return fromValues(
|
|
368
|
+
sxcy * cz + cxsy * sz,
|
|
369
|
+
cxsy * cz - sxcy * sz,
|
|
370
|
+
cxcy * sz - sxsy * cz,
|
|
371
|
+
cxcy * cz + sxsy * sz,
|
|
372
|
+
out
|
|
373
|
+
);
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Create a quaternion from equivalent y-z'-x" (intrinsic) Tait-Bryan angles.
|
|
378
|
+
* @param y - The Y angle in degrees.
|
|
379
|
+
* @param z - The Z angle in degrees.
|
|
380
|
+
* @param x - The X angle in degrees.
|
|
381
|
+
* @param out - The quaternion to store the result in.
|
|
382
|
+
* @returns The quaternion.
|
|
383
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
384
|
+
* @public
|
|
385
|
+
*/
|
|
386
|
+
export const fromEulerYzx = <T extends QuaternionLike>(
|
|
387
|
+
y: number,
|
|
388
|
+
z: number,
|
|
389
|
+
x: number,
|
|
390
|
+
out: T
|
|
391
|
+
): T => {
|
|
392
|
+
const x2 = x * ratio;
|
|
393
|
+
const y2 = y * ratio;
|
|
394
|
+
const z2 = z * ratio;
|
|
395
|
+
|
|
396
|
+
const sx = Math.sin(x2);
|
|
397
|
+
const cx = Math.cos(x2);
|
|
398
|
+
const sy = Math.sin(y2);
|
|
399
|
+
const cy = Math.cos(y2);
|
|
400
|
+
const sz = Math.sin(z2);
|
|
401
|
+
const cz = Math.cos(z2);
|
|
402
|
+
|
|
403
|
+
const sxcy = sx * cy;
|
|
404
|
+
const cxsy = cx * sy;
|
|
405
|
+
const cxcy = cx * cy;
|
|
406
|
+
const sxsy = sx * sy;
|
|
407
|
+
|
|
408
|
+
return fromValues(
|
|
409
|
+
sxcy * cz + cxsy * sz,
|
|
410
|
+
cxsy * cz + sxcy * sz,
|
|
411
|
+
cxcy * sz - sxsy * cz,
|
|
412
|
+
cxcy * cz - sxsy * sz,
|
|
413
|
+
out
|
|
414
|
+
);
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Create a quaternion from equivalent z-x'-y" (intrinsic) Tait-Bryan angles.
|
|
419
|
+
* @param z - The Z angle in degrees.
|
|
420
|
+
* @param x - The X angle in degrees.
|
|
421
|
+
* @param y - The Y angle in degrees.
|
|
422
|
+
* @param out - The quaternion to store the result in.
|
|
423
|
+
* @returns The quaternion.
|
|
424
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
425
|
+
* @public
|
|
426
|
+
*/
|
|
427
|
+
export const fromEulerZxy = <T extends QuaternionLike>(
|
|
428
|
+
z: number,
|
|
429
|
+
x: number,
|
|
430
|
+
y: number,
|
|
431
|
+
out: T
|
|
432
|
+
): T => {
|
|
433
|
+
const x2 = x * ratio;
|
|
434
|
+
const y2 = y * ratio;
|
|
435
|
+
const z2 = z * ratio;
|
|
436
|
+
|
|
437
|
+
const sx = Math.sin(x2);
|
|
438
|
+
const cx = Math.cos(x2);
|
|
439
|
+
const sy = Math.sin(y2);
|
|
440
|
+
const cy = Math.cos(y2);
|
|
441
|
+
const sz = Math.sin(z2);
|
|
442
|
+
const cz = Math.cos(z2);
|
|
443
|
+
|
|
444
|
+
const sxcy = sx * cy;
|
|
445
|
+
const cxsy = cx * sy;
|
|
446
|
+
const cxcy = cx * cy;
|
|
447
|
+
const sxsy = sx * sy;
|
|
448
|
+
|
|
449
|
+
return fromValues(
|
|
450
|
+
sxcy * cz - cxsy * sz,
|
|
451
|
+
cxsy * cz + sxcy * sz,
|
|
452
|
+
cxcy * sz + sxsy * cz,
|
|
453
|
+
cxcy * cz - sxsy * sz,
|
|
454
|
+
out
|
|
455
|
+
);
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Create a quaternion from equivalent z-y'-x" (intrinsic) Tait-Bryan angles.
|
|
460
|
+
* @param z - The Z angle (yaw) in degrees.
|
|
461
|
+
* @param y - The Y angle (pitch) in degrees.
|
|
462
|
+
* @param x - The X angle (roll) in degrees.
|
|
463
|
+
* @param out - The quaternion to store the result in.
|
|
464
|
+
* @returns The quaternion.
|
|
465
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
466
|
+
* @public
|
|
467
|
+
*/
|
|
468
|
+
export const fromEulerZyx = <T extends QuaternionLike>(
|
|
469
|
+
z: number,
|
|
470
|
+
y: number,
|
|
471
|
+
x: number,
|
|
472
|
+
out: T
|
|
473
|
+
): T => {
|
|
474
|
+
const x2 = x * ratio;
|
|
475
|
+
const y2 = y * ratio;
|
|
476
|
+
const z2 = z * ratio;
|
|
477
|
+
|
|
478
|
+
const sx = Math.sin(x2);
|
|
479
|
+
const cx = Math.cos(x2);
|
|
480
|
+
const sy = Math.sin(y2);
|
|
481
|
+
const cy = Math.cos(y2);
|
|
482
|
+
const sz = Math.sin(z2);
|
|
483
|
+
const cz = Math.cos(z2);
|
|
484
|
+
|
|
485
|
+
const sxcy = sx * cy;
|
|
486
|
+
const cxsy = cx * sy;
|
|
487
|
+
const cxcy = cx * cy;
|
|
488
|
+
const sxsy = sx * sy;
|
|
489
|
+
|
|
490
|
+
return fromValues(
|
|
491
|
+
sxcy * cz - cxsy * sz,
|
|
492
|
+
cxsy * cz + sxcy * sz,
|
|
493
|
+
cxcy * sz - sxsy * cz,
|
|
494
|
+
cxcy * cz + sxsy * sz,
|
|
495
|
+
out
|
|
496
|
+
);
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Create a quaternion from equivalent z-y'-x" (intrinsic) Tait-Bryan angles.
|
|
501
|
+
* @param z - The Z angle (roll) in degrees.
|
|
502
|
+
* @param y - The Y angle (pitch) in degrees.
|
|
503
|
+
* @param x - The X angle (yaw) in degrees.
|
|
504
|
+
* @param out - The quaternion to store the result in.
|
|
505
|
+
* @returns The quaternion.
|
|
506
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
507
|
+
* @public
|
|
508
|
+
*/
|
|
509
|
+
export const fromEuler: <T extends QuaternionLike>(
|
|
510
|
+
z: number,
|
|
511
|
+
y: number,
|
|
512
|
+
x: number,
|
|
513
|
+
out: T
|
|
514
|
+
) => T = fromEulerZyx;
|
|
515
|
+
|
|
516
|
+
// Used in `toEuler`.
|
|
517
|
+
const halfEpsilon = 0.5 - epsilon;
|
|
518
|
+
const doubleRatio = 360 / Math.PI;
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Convert a quaternion to equivalent z-y'-x" (intrinsic) Tait-Bryan angles.
|
|
522
|
+
* @param quaternion - The quaternion.
|
|
523
|
+
* @param out - The vector in which to store the Tait-Bryan angles.
|
|
524
|
+
* @returns The Tait-Bryan angles in degrees in roll (z), pitch (y'), yaw (x") order.
|
|
525
|
+
* @public
|
|
526
|
+
*/
|
|
527
|
+
export const toEuler = <T extends Vector3Like>(
|
|
528
|
+
quaternion: QuaternionLike,
|
|
529
|
+
out: T
|
|
530
|
+
): T => {
|
|
531
|
+
const x = quaternion[0];
|
|
532
|
+
const y = quaternion[1];
|
|
533
|
+
const z = quaternion[2];
|
|
534
|
+
const w = quaternion[3];
|
|
535
|
+
|
|
536
|
+
const y2 = y * y;
|
|
537
|
+
const z2 = z * z;
|
|
538
|
+
const w2 = w * w;
|
|
539
|
+
|
|
540
|
+
const test = x * w - y * z;
|
|
541
|
+
|
|
542
|
+
const heu = halfEpsilon * (x * x + y2 + z2 + w2);
|
|
543
|
+
|
|
544
|
+
if (test > heu) {
|
|
545
|
+
return vector3FromValues(90, Math.atan2(y, x) * doubleRatio, 0, out);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (test < -heu) {
|
|
549
|
+
return vector3FromValues(-90, Math.atan2(y, x) * doubleRatio, 0, out);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return vector3FromValues(
|
|
553
|
+
radiansToDegrees(Math.asin(2 * (x * z - w * y))),
|
|
554
|
+
radiansToDegrees(Math.atan2(2 * (x * w + y * z), 1 - 2 * (z2 + w2))),
|
|
555
|
+
radiansToDegrees(Math.atan2(2 * (x * y + z * w), 1 - 2 * (y2 + z2))),
|
|
556
|
+
out
|
|
557
|
+
);
|
|
127
558
|
};
|
|
128
559
|
|
|
129
560
|
// Stores intermediary values for some functions.
|
|
130
|
-
const
|
|
561
|
+
const im3 = createMatrix3Like();
|
|
131
562
|
|
|
132
563
|
/**
|
|
133
|
-
* Create a quaternion with values corresponding to the given orthonormal set of vectors.
|
|
134
|
-
* @param view - The vector representing the viewing direction.
|
|
135
|
-
* @param right - The vector representing the local "right" direction.
|
|
136
|
-
* @param up - The vector representing the local "up" direction.
|
|
564
|
+
* Create a quaternion with values corresponding to the given orthonormal set of unit vectors.
|
|
565
|
+
* @param view - The unit vector representing the viewing direction.
|
|
566
|
+
* @param right - The unit vector representing the local "right" direction.
|
|
567
|
+
* @param up - The unit vector representing the local "up" direction.
|
|
137
568
|
* @param out - The quaternion to store the result in.
|
|
138
569
|
* @returns The quaternion.
|
|
570
|
+
* @public
|
|
139
571
|
*/
|
|
140
572
|
export const fromAxes = <T extends QuaternionLike>(
|
|
141
573
|
view: Vector3Like,
|
|
142
574
|
right: Vector3Like,
|
|
143
575
|
up: Vector3Like,
|
|
144
576
|
out: T
|
|
145
|
-
): T =>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
577
|
+
): T =>
|
|
578
|
+
normalize(
|
|
579
|
+
fromMatrix3(
|
|
580
|
+
matrix3FromValues(
|
|
581
|
+
right[0],
|
|
582
|
+
up[0],
|
|
583
|
+
-view[0],
|
|
584
|
+
right[1],
|
|
585
|
+
up[1],
|
|
586
|
+
-view[1],
|
|
587
|
+
right[2],
|
|
588
|
+
up[2],
|
|
589
|
+
-view[2],
|
|
590
|
+
im3
|
|
591
|
+
),
|
|
592
|
+
out
|
|
593
|
+
),
|
|
594
|
+
out
|
|
595
|
+
);
|
|
157
596
|
|
|
158
597
|
/**
|
|
159
598
|
* Set a quaternion to the identity.
|
|
160
599
|
* @param out - The quaternion to store the result in.
|
|
161
600
|
* @returns This quaternion.
|
|
601
|
+
* @public
|
|
162
602
|
*/
|
|
163
|
-
export const identity = <T extends QuaternionLike>(out: T): T =>
|
|
164
|
-
|
|
165
|
-
out[1] = 0;
|
|
166
|
-
out[2] = 0;
|
|
167
|
-
out[3] = 1;
|
|
168
|
-
return out;
|
|
169
|
-
};
|
|
603
|
+
export const identity = <T extends QuaternionLike>(out: T): T =>
|
|
604
|
+
fromValues(0, 0, 0, 1, out);
|
|
170
605
|
|
|
171
606
|
/**
|
|
172
607
|
* Calculate the axis and angle that represent a quaternion.
|
|
173
608
|
* @param quaternion - The quaternion.
|
|
174
609
|
* @param out - The axis and angle to store the result in.
|
|
175
610
|
* @returns The axis and angle.
|
|
611
|
+
* @public
|
|
176
612
|
*/
|
|
177
613
|
export const getAxisAngle = <T extends AxisAngle>(
|
|
178
614
|
quaternion: QuaternionLike,
|
|
@@ -181,10 +617,17 @@ export const getAxisAngle = <T extends AxisAngle>(
|
|
|
181
617
|
const r = Math.acos(quaternion[3]) * 2;
|
|
182
618
|
const s = Math.sin(r / 2);
|
|
183
619
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
620
|
+
if (s > epsilon) {
|
|
621
|
+
vector3FromValues(
|
|
622
|
+
quaternion[0] / s,
|
|
623
|
+
quaternion[1] / s,
|
|
624
|
+
quaternion[2] / s,
|
|
625
|
+
out.axis
|
|
626
|
+
);
|
|
627
|
+
} else {
|
|
628
|
+
vector3FromValues(1, 0, 0, out.axis);
|
|
629
|
+
}
|
|
630
|
+
|
|
188
631
|
out.angle = r;
|
|
189
632
|
return out;
|
|
190
633
|
};
|
|
@@ -194,19 +637,16 @@ export const getAxisAngle = <T extends AxisAngle>(
|
|
|
194
637
|
* @param axisAngle - The axis and angle.
|
|
195
638
|
* @param out - The quaternion to store the result in.
|
|
196
639
|
* @returns The quaternion.
|
|
640
|
+
* @public
|
|
197
641
|
*/
|
|
198
642
|
export const setAxisAngle = <T extends QuaternionLike>(
|
|
199
|
-
|
|
643
|
+
{ angle, axis }: AxisAngle,
|
|
200
644
|
out: T
|
|
201
645
|
): T => {
|
|
202
|
-
const r =
|
|
646
|
+
const r = angle / 2;
|
|
203
647
|
const s = Math.sin(r);
|
|
204
648
|
|
|
205
|
-
|
|
206
|
-
out[1] = s * axisAngle.axis[1];
|
|
207
|
-
out[2] = s * axisAngle.axis[2];
|
|
208
|
-
out[3] = Math.cos(r);
|
|
209
|
-
return out;
|
|
649
|
+
return fromValues(axis[0] * s, axis[1] * s, axis[2] * s, Math.cos(r), out);
|
|
210
650
|
};
|
|
211
651
|
|
|
212
652
|
/**
|
|
@@ -214,6 +654,7 @@ export const setAxisAngle = <T extends QuaternionLike>(
|
|
|
214
654
|
* @param a - The first unit quaternion.
|
|
215
655
|
* @param b - The second unit quaternion.
|
|
216
656
|
* @returns The angular distance in radians.
|
|
657
|
+
* @public
|
|
217
658
|
*/
|
|
218
659
|
export const getAngle = (a: QuaternionLike, b: QuaternionLike): number => {
|
|
219
660
|
const dp = dot(a, b);
|
|
@@ -226,6 +667,7 @@ export const getAngle = (a: QuaternionLike, b: QuaternionLike): number => {
|
|
|
226
667
|
* @param b - The multiplicand.
|
|
227
668
|
* @param out - The quaternion to store the result in.
|
|
228
669
|
* @returns The product.
|
|
670
|
+
* @public
|
|
229
671
|
*/
|
|
230
672
|
export const multiply = <T extends QuaternionLike>(
|
|
231
673
|
a: QuaternionLike,
|
|
@@ -242,11 +684,13 @@ export const multiply = <T extends QuaternionLike>(
|
|
|
242
684
|
const bz = b[2];
|
|
243
685
|
const bw = b[3];
|
|
244
686
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
687
|
+
return fromValues(
|
|
688
|
+
ax * bw + aw * bx + ay * bz - az * by,
|
|
689
|
+
ay * bw + aw * by + az * bx - ax * bz,
|
|
690
|
+
az * bw + aw * bz + ax * by - ay * bx,
|
|
691
|
+
aw * bw - ax * bx - ay * by - az * bz,
|
|
692
|
+
out
|
|
693
|
+
);
|
|
250
694
|
};
|
|
251
695
|
|
|
252
696
|
/**
|
|
@@ -255,27 +699,29 @@ export const multiply = <T extends QuaternionLike>(
|
|
|
255
699
|
* @param radians - The angle in radians.
|
|
256
700
|
* @param out - The quaternion to store the result in.
|
|
257
701
|
* @returns The rotated quaternion.
|
|
702
|
+
* @public
|
|
258
703
|
*/
|
|
259
704
|
export const rotateX = <T extends QuaternionLike>(
|
|
260
705
|
quaternion: QuaternionLike,
|
|
261
706
|
radians: number,
|
|
262
707
|
out: T
|
|
263
708
|
): T => {
|
|
264
|
-
const r = radians * 0.5;
|
|
265
|
-
|
|
266
709
|
const ax = quaternion[0];
|
|
267
710
|
const ay = quaternion[1];
|
|
268
711
|
const az = quaternion[2];
|
|
269
712
|
const aw = quaternion[3];
|
|
270
713
|
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
714
|
+
const r = radians / 2;
|
|
715
|
+
const s = Math.sin(r);
|
|
716
|
+
const c = Math.cos(r);
|
|
717
|
+
|
|
718
|
+
return fromValues(
|
|
719
|
+
ax * c + aw * s,
|
|
720
|
+
ay * c + az * s,
|
|
721
|
+
az * c - ay * s,
|
|
722
|
+
aw * c - ax * s,
|
|
723
|
+
out
|
|
724
|
+
);
|
|
279
725
|
};
|
|
280
726
|
|
|
281
727
|
/**
|
|
@@ -284,27 +730,29 @@ export const rotateX = <T extends QuaternionLike>(
|
|
|
284
730
|
* @param radians - The angle in radians.
|
|
285
731
|
* @param out - The quaternion to store the result in.
|
|
286
732
|
* @returns The rotated quaternion.
|
|
733
|
+
* @public
|
|
287
734
|
*/
|
|
288
735
|
export const rotateY = <T extends QuaternionLike>(
|
|
289
736
|
quaternion: QuaternionLike,
|
|
290
737
|
radians: number,
|
|
291
738
|
out: T
|
|
292
739
|
): T => {
|
|
293
|
-
const r = radians * 0.5;
|
|
294
|
-
|
|
295
740
|
const ax = quaternion[0];
|
|
296
741
|
const ay = quaternion[1];
|
|
297
742
|
const az = quaternion[2];
|
|
298
743
|
const aw = quaternion[3];
|
|
299
744
|
|
|
300
|
-
const
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
745
|
+
const r = radians / 2;
|
|
746
|
+
const s = Math.sin(r);
|
|
747
|
+
const c = Math.cos(r);
|
|
748
|
+
|
|
749
|
+
return fromValues(
|
|
750
|
+
ax * c - az * s,
|
|
751
|
+
ay * c + aw * s,
|
|
752
|
+
az * c + ax * s,
|
|
753
|
+
aw * c - ay * s,
|
|
754
|
+
out
|
|
755
|
+
);
|
|
308
756
|
};
|
|
309
757
|
|
|
310
758
|
/**
|
|
@@ -313,34 +761,37 @@ export const rotateY = <T extends QuaternionLike>(
|
|
|
313
761
|
* @param radians - The angle in radians.
|
|
314
762
|
* @param out - The quaternion to store the result in.
|
|
315
763
|
* @returns The rotated quaternion.
|
|
764
|
+
* @public
|
|
316
765
|
*/
|
|
317
766
|
export const rotateZ = <T extends QuaternionLike>(
|
|
318
767
|
quaternion: QuaternionLike,
|
|
319
768
|
radians: number,
|
|
320
769
|
out: T
|
|
321
770
|
): T => {
|
|
322
|
-
const r = radians * 0.5;
|
|
323
|
-
|
|
324
771
|
const ax = quaternion[0];
|
|
325
772
|
const ay = quaternion[1];
|
|
326
773
|
const az = quaternion[2];
|
|
327
774
|
const aw = quaternion[3];
|
|
328
775
|
|
|
329
|
-
const
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
776
|
+
const r = radians / 2;
|
|
777
|
+
const s = Math.sin(r);
|
|
778
|
+
const c = Math.cos(r);
|
|
779
|
+
|
|
780
|
+
return fromValues(
|
|
781
|
+
ax * c + ay * s,
|
|
782
|
+
ay * c - ax * s,
|
|
783
|
+
az * c + aw * s,
|
|
784
|
+
aw * c - az * s,
|
|
785
|
+
out
|
|
786
|
+
);
|
|
337
787
|
};
|
|
338
788
|
|
|
339
789
|
/**
|
|
340
790
|
* Calculate the fourth component of a unit quaternion from the first three, ignoring the existing fourth component.
|
|
341
|
-
* @param quaternion - The quaternion.
|
|
791
|
+
* @param quaternion - The unit quaternion.
|
|
342
792
|
* @param out - The quaternion to store the result in.
|
|
343
793
|
* @returns The quaternion.
|
|
794
|
+
* @public
|
|
344
795
|
*/
|
|
345
796
|
export const calculateW = <T extends QuaternionLike>(
|
|
346
797
|
quaternion: QuaternionLike,
|
|
@@ -350,18 +801,22 @@ export const calculateW = <T extends QuaternionLike>(
|
|
|
350
801
|
const y = quaternion[1];
|
|
351
802
|
const z = quaternion[2];
|
|
352
803
|
|
|
353
|
-
out
|
|
354
|
-
|
|
355
|
-
|
|
804
|
+
if (quaternion !== out) {
|
|
805
|
+
out[0] = x;
|
|
806
|
+
out[1] = y;
|
|
807
|
+
out[2] = z;
|
|
808
|
+
}
|
|
809
|
+
|
|
356
810
|
out[3] = Math.sqrt(Math.abs(1 - x * x - y * y - z * z));
|
|
357
811
|
return out;
|
|
358
812
|
};
|
|
359
813
|
|
|
360
814
|
/**
|
|
361
815
|
* Calculate the exponential of a unit quaternion.
|
|
362
|
-
* @param quaternion - The quaternion.
|
|
816
|
+
* @param quaternion - The unit quaternion.
|
|
363
817
|
* @param out - The quaternion to store the result in.
|
|
364
818
|
* @returns The exponential.
|
|
819
|
+
* @public
|
|
365
820
|
*/
|
|
366
821
|
export const exp = <T extends QuaternionLike>(
|
|
367
822
|
quaternion: QuaternionLike,
|
|
@@ -370,24 +825,20 @@ export const exp = <T extends QuaternionLike>(
|
|
|
370
825
|
const x = quaternion[0];
|
|
371
826
|
const y = quaternion[1];
|
|
372
827
|
const z = quaternion[2];
|
|
373
|
-
const w = quaternion[3];
|
|
374
828
|
|
|
375
|
-
const r = Math.sqrt(x * x + y * y + z * z);
|
|
376
|
-
const et = Math.exp(
|
|
829
|
+
const r = Math.sqrt(x * x + y * y + z * z); // `Math.hypot` is slower.
|
|
830
|
+
const et = Math.exp(quaternion[3]);
|
|
377
831
|
const s = r > 0 ? (et * Math.sin(r)) / r : 0;
|
|
378
832
|
|
|
379
|
-
|
|
380
|
-
out[1] = y * s;
|
|
381
|
-
out[2] = z * s;
|
|
382
|
-
out[3] = et * Math.cos(r);
|
|
383
|
-
return out;
|
|
833
|
+
return fromValues(x * s, y * s, z * s, et * Math.cos(r), out);
|
|
384
834
|
};
|
|
385
835
|
|
|
386
836
|
/**
|
|
387
837
|
* Calculate the natural logarithm of a unit quaternion.
|
|
388
|
-
* @param quaternion - The quaternion.
|
|
838
|
+
* @param quaternion - The unit quaternion.
|
|
389
839
|
* @param out - The quaternion to store the result in.
|
|
390
840
|
* @returns The natural logarithm.
|
|
841
|
+
* @public
|
|
391
842
|
*/
|
|
392
843
|
export const ln = <T extends QuaternionLike>(
|
|
393
844
|
quaternion: QuaternionLike,
|
|
@@ -398,30 +849,26 @@ export const ln = <T extends QuaternionLike>(
|
|
|
398
849
|
const z = quaternion[2];
|
|
399
850
|
const w = quaternion[3];
|
|
400
851
|
|
|
401
|
-
const
|
|
852
|
+
const xyz2 = x * x + y * y + z * z;
|
|
853
|
+
const r = Math.sqrt(xyz2); // `Math.hypot` is slower.
|
|
402
854
|
const t = r > 0 ? Math.atan2(r, w) / r : 0;
|
|
403
855
|
|
|
404
|
-
|
|
405
|
-
out[1] = y * t;
|
|
406
|
-
out[2] = z * t;
|
|
407
|
-
out[3] = 0.5 * Math.log(x * x + y * y + z * z + w * w);
|
|
408
|
-
return out;
|
|
856
|
+
return fromValues(x * t, y * t, z * t, Math.log(xyz2 + w * w) / 2, out);
|
|
409
857
|
};
|
|
410
858
|
|
|
411
859
|
/**
|
|
412
|
-
* Calculate a power of a unit quaternion.
|
|
413
|
-
* @param quaternion - The quaternion.
|
|
860
|
+
* Calculate a scalar power of a unit quaternion.
|
|
861
|
+
* @param quaternion - The unit quaternion.
|
|
414
862
|
* @param scalar - The amount to scale the quaternion by.
|
|
415
863
|
* @param out - The quaternion to store the result in.
|
|
416
|
-
* @returns The power.
|
|
864
|
+
* @returns The scalar power.
|
|
865
|
+
* @public
|
|
417
866
|
*/
|
|
418
867
|
export const pow = <T extends QuaternionLike>(
|
|
419
868
|
quaternion: QuaternionLike,
|
|
420
869
|
scalar: number,
|
|
421
870
|
out: T
|
|
422
|
-
): T =>
|
|
423
|
-
return exp(scale(ln(quaternion, out), scalar, out), out);
|
|
424
|
-
};
|
|
871
|
+
): T => exp(scale(ln(quaternion, out), scalar, out), out);
|
|
425
872
|
|
|
426
873
|
/**
|
|
427
874
|
* Perform a spherical linear interpolation between two quaternions.
|
|
@@ -430,7 +877,8 @@ export const pow = <T extends QuaternionLike>(
|
|
|
430
877
|
* @param t - The interpolation amount in `[0,1]`.
|
|
431
878
|
* @param out - The quaternion to store the result in.
|
|
432
879
|
* @returns The interpolated quaternion.
|
|
433
|
-
* @see
|
|
880
|
+
* @see {@link https://en.wikipedia.org/wiki/Slerp | Slerp}
|
|
881
|
+
* @public
|
|
434
882
|
*/
|
|
435
883
|
export const slerp = <T extends QuaternionLike>(
|
|
436
884
|
a: QuaternionLike,
|
|
@@ -472,31 +920,37 @@ export const slerp = <T extends QuaternionLike>(
|
|
|
472
920
|
scale1 = t;
|
|
473
921
|
}
|
|
474
922
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
923
|
+
return fromValues(
|
|
924
|
+
ax * scale0 + bx * scale1,
|
|
925
|
+
ay * scale0 + by * scale1,
|
|
926
|
+
az * scale0 + bz * scale1,
|
|
927
|
+
aw * scale0 + bw * scale1,
|
|
928
|
+
out
|
|
929
|
+
);
|
|
480
930
|
};
|
|
481
931
|
|
|
932
|
+
const pi2 = Math.PI * 2;
|
|
933
|
+
|
|
482
934
|
/**
|
|
483
935
|
* Set a quaternion to a random unit quaternion.
|
|
484
936
|
* @param out - The quaternion to store the result in.
|
|
485
937
|
* @returns The quaternion.
|
|
938
|
+
* @public
|
|
486
939
|
*/
|
|
487
940
|
export const random = <T extends QuaternionLike>(out: T): T => {
|
|
488
|
-
const
|
|
489
|
-
const
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
941
|
+
const rand = Math.random();
|
|
942
|
+
const sqInvRand = Math.sqrt(1 - rand);
|
|
943
|
+
const sqRand = Math.sqrt(rand);
|
|
944
|
+
const pi2u2 = pi2 * Math.random();
|
|
945
|
+
const pi2u3 = pi2 * Math.random();
|
|
946
|
+
|
|
947
|
+
return fromValues(
|
|
948
|
+
sqInvRand * Math.sin(pi2u2),
|
|
949
|
+
sqInvRand * Math.cos(pi2u2),
|
|
950
|
+
sqRand * Math.sin(pi2u3),
|
|
951
|
+
sqRand * Math.cos(pi2u3),
|
|
952
|
+
out
|
|
953
|
+
);
|
|
500
954
|
};
|
|
501
955
|
|
|
502
956
|
/**
|
|
@@ -504,6 +958,7 @@ export const random = <T extends QuaternionLike>(out: T): T => {
|
|
|
504
958
|
* @param quaternion - The quaternion.
|
|
505
959
|
* @param out - The quaternion to store the result in.
|
|
506
960
|
* @returns The inverse.
|
|
961
|
+
* @public
|
|
507
962
|
*/
|
|
508
963
|
export const invert = <T extends QuaternionLike>(
|
|
509
964
|
quaternion: QuaternionLike,
|
|
@@ -517,19 +972,9 @@ export const invert = <T extends QuaternionLike>(
|
|
|
517
972
|
const aDotA = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
|
|
518
973
|
const invDot = aDotA ? 1 / aDotA : 0;
|
|
519
974
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
out[2] = 0;
|
|
524
|
-
out[3] = 0;
|
|
525
|
-
return out;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
out[0] = -a0 * invDot;
|
|
529
|
-
out[1] = -a1 * invDot;
|
|
530
|
-
out[2] = -a2 * invDot;
|
|
531
|
-
out[3] = a3 * invDot;
|
|
532
|
-
return out;
|
|
975
|
+
return aDotA === 0 ?
|
|
976
|
+
fromValues(0, 0, 0, 0, out)
|
|
977
|
+
: fromValues(-a0 * invDot, -a1 * invDot, -a2 * invDot, a3 * invDot, out);
|
|
533
978
|
};
|
|
534
979
|
|
|
535
980
|
/**
|
|
@@ -537,17 +982,19 @@ export const invert = <T extends QuaternionLike>(
|
|
|
537
982
|
* @param quaternion - The quaternion.
|
|
538
983
|
* @param out - The quaternion to store the result in.
|
|
539
984
|
* @returns The conjugate.
|
|
985
|
+
* @public
|
|
540
986
|
*/
|
|
541
987
|
export const conjugate = <T extends QuaternionLike>(
|
|
542
988
|
quaternion: QuaternionLike,
|
|
543
989
|
out: T
|
|
544
|
-
): T =>
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
990
|
+
): T =>
|
|
991
|
+
fromValues(
|
|
992
|
+
-quaternion[0],
|
|
993
|
+
-quaternion[1],
|
|
994
|
+
-quaternion[2],
|
|
995
|
+
quaternion[3],
|
|
996
|
+
out
|
|
997
|
+
);
|
|
551
998
|
|
|
552
999
|
// Used to store intermediate values for some functions.
|
|
553
1000
|
const controlPointOne = createQuaternionLike();
|
|
@@ -562,7 +1009,8 @@ const controlPointTwo = createQuaternionLike();
|
|
|
562
1009
|
* @param t - The interpolation amount in `[0,1]`.
|
|
563
1010
|
* @param out - The quaternion to store the result in.
|
|
564
1011
|
* @returns The interpolated value.
|
|
565
|
-
* @see
|
|
1012
|
+
* @see {@link https://en.wikipedia.org/wiki/Slerp | Slerp}
|
|
1013
|
+
* @public
|
|
566
1014
|
*/
|
|
567
1015
|
export const sqlerp = <T extends QuaternionLike>(
|
|
568
1016
|
a: QuaternionLike,
|
|
@@ -571,15 +1019,59 @@ export const sqlerp = <T extends QuaternionLike>(
|
|
|
571
1019
|
d: QuaternionLike,
|
|
572
1020
|
t: number,
|
|
573
1021
|
out: T
|
|
1022
|
+
): T =>
|
|
1023
|
+
slerp(
|
|
1024
|
+
slerp(a, d, t, controlPointOne),
|
|
1025
|
+
slerp(b, c, t, controlPointTwo),
|
|
1026
|
+
2 * t * (1 - t),
|
|
1027
|
+
out
|
|
1028
|
+
);
|
|
1029
|
+
|
|
1030
|
+
// The unit three-dimensional vector that represents the X-axis.
|
|
1031
|
+
const xAxis = vector3FromValues(1, 0, 0, createVector3Like());
|
|
1032
|
+
|
|
1033
|
+
// The unit three-dimensional vector that represents the Y-axis.
|
|
1034
|
+
const yAxis = vector3FromValues(0, 1, 0, createVector3Like());
|
|
1035
|
+
|
|
1036
|
+
// Used to store intermediary values for some functions.
|
|
1037
|
+
const iv3 = createVector3Like();
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Create a unit quaternion that represents the shortest rotation from one unit vector to another.
|
|
1041
|
+
* @param a - The first unit vector.
|
|
1042
|
+
* @param b - The second unit vector.
|
|
1043
|
+
* @param out - The quaternion to store the result in.
|
|
1044
|
+
* @returns The unit quaternion.
|
|
1045
|
+
* @public
|
|
1046
|
+
*/
|
|
1047
|
+
export const fromRotationTo = <T extends QuaternionLike>(
|
|
1048
|
+
a: Vector3Like,
|
|
1049
|
+
b: Vector3Like,
|
|
1050
|
+
out: T
|
|
574
1051
|
): T => {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
1052
|
+
const dp = vector3Dot(a, b);
|
|
1053
|
+
|
|
1054
|
+
if (dp < epsilon - 1) {
|
|
1055
|
+
vector3Cross(xAxis, a, iv3);
|
|
1056
|
+
if (vector3GetMagnitude(iv3) < epsilon) {
|
|
1057
|
+
vector3Cross(yAxis, a, iv3);
|
|
1058
|
+
}
|
|
1059
|
+
vector3Normalize(iv3, iv3);
|
|
1060
|
+
return setAxisAngle({ angle: Math.PI, axis: iv3 }, out);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
if (dp > 1 - epsilon) {
|
|
1064
|
+
return fromValues(0, 0, 0, 1, out);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
vector3Cross(a, b, iv3);
|
|
1068
|
+
return normalize(fromValues(iv3[0], iv3[1], iv3[2], 1 + dp, out), out);
|
|
578
1069
|
};
|
|
579
1070
|
|
|
580
1071
|
/**
|
|
581
1072
|
* A complex number that is commonly used to describe rotations.
|
|
582
|
-
* @see
|
|
1073
|
+
* @see {@link https://en.wikipedia.org/wiki/Quaternion | Quaternion}
|
|
1074
|
+
* @public
|
|
583
1075
|
*/
|
|
584
1076
|
export default class Quaternion extends Float32Array implements QuaternionLike {
|
|
585
1077
|
/**
|
|
@@ -587,7 +1079,7 @@ export default class Quaternion extends Float32Array implements QuaternionLike {
|
|
|
587
1079
|
* @param matrix - The matrix.
|
|
588
1080
|
* @param out - The quaternion to store the result in.
|
|
589
1081
|
* @returns The quaternion.
|
|
590
|
-
* @see
|
|
1082
|
+
* @see {@link https://en.wikipedia.org/wiki/Rotation_matrix | Rotation matrix}
|
|
591
1083
|
*/
|
|
592
1084
|
public static fromMatrix3<T extends QuaternionLike = Quaternion>(
|
|
593
1085
|
matrix: Matrix3Like,
|
|
@@ -597,21 +1089,21 @@ export default class Quaternion extends Float32Array implements QuaternionLike {
|
|
|
597
1089
|
}
|
|
598
1090
|
|
|
599
1091
|
/**
|
|
600
|
-
* Create a quaternion from equivalent
|
|
601
|
-
* @param
|
|
602
|
-
* @param y - The y angle.
|
|
603
|
-
* @param
|
|
1092
|
+
* Create a quaternion from equivalent z-y'-x" (intrinsic) Tait-Bryan angles.
|
|
1093
|
+
* @param z - The z (roll) angle.
|
|
1094
|
+
* @param y - The y (pitch) angle.
|
|
1095
|
+
* @param x - The x (yaw) angle.
|
|
604
1096
|
* @param out - The quaternion to store the result in.
|
|
605
1097
|
* @returns The quaternion.
|
|
606
|
-
* @see
|
|
1098
|
+
* @see {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}
|
|
607
1099
|
*/
|
|
608
1100
|
public static fromEuler<T extends QuaternionLike = Quaternion>(
|
|
609
|
-
x: number,
|
|
610
|
-
y: number,
|
|
611
1101
|
z: number,
|
|
1102
|
+
y: number,
|
|
1103
|
+
x: number,
|
|
612
1104
|
out: T = new Quaternion() as Quaternion & T
|
|
613
1105
|
): T {
|
|
614
|
-
return fromEuler(
|
|
1106
|
+
return fromEuler(z, y, x, out);
|
|
615
1107
|
}
|
|
616
1108
|
|
|
617
1109
|
/**
|
|
@@ -650,9 +1142,24 @@ export default class Quaternion extends Float32Array implements QuaternionLike {
|
|
|
650
1142
|
return fromAxes(view, right, up, out);
|
|
651
1143
|
}
|
|
652
1144
|
|
|
1145
|
+
/**
|
|
1146
|
+
* Create a unit quaternion that represents the shortest rotation from one unit vector to another.
|
|
1147
|
+
* @param a - The first unit vector.
|
|
1148
|
+
* @param b - The second unit vector.
|
|
1149
|
+
* @param out - The quaternion to store the result in.
|
|
1150
|
+
* @returns The unit quaternion.
|
|
1151
|
+
*/
|
|
1152
|
+
public static fromRotationTo<T extends QuaternionLike = Quaternion>(
|
|
1153
|
+
a: Vector3Like,
|
|
1154
|
+
b: Vector3Like,
|
|
1155
|
+
out: T = new Quaternion() as Quaternion & T
|
|
1156
|
+
): T {
|
|
1157
|
+
return fromRotationTo(a, b, out);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
653
1160
|
/**
|
|
654
1161
|
* Create an identity quaternion.
|
|
655
|
-
* @see
|
|
1162
|
+
* @see {@link https://en.wikipedia.org/wiki/Quaternion | Quaternion}
|
|
656
1163
|
*/
|
|
657
1164
|
public constructor() {
|
|
658
1165
|
super(4);
|
|
@@ -810,7 +1317,7 @@ export default class Quaternion extends Float32Array implements QuaternionLike {
|
|
|
810
1317
|
* @param t - The interpolation amount in `[0,1]`.
|
|
811
1318
|
* @param out - The quaternion to store the result in.
|
|
812
1319
|
* @returns The interpolated quaternion.
|
|
813
|
-
* @see
|
|
1320
|
+
* @see {@link https://en.wikipedia.org/wiki/Slerp | Slerp}
|
|
814
1321
|
*/
|
|
815
1322
|
public slerp<T extends QuaternionLike = Quaternion>(
|
|
816
1323
|
quaternion: QuaternionLike,
|
|
@@ -967,7 +1474,7 @@ export default class Quaternion extends Float32Array implements QuaternionLike {
|
|
|
967
1474
|
* @param t - The interpolation amount in `[0,1]`.
|
|
968
1475
|
* @param out - The quaternion to store the result in.
|
|
969
1476
|
* @returns The interpolated value.
|
|
970
|
-
* @see
|
|
1477
|
+
* @see {@link https://en.wikipedia.org/wiki/Slerp | Slerp}
|
|
971
1478
|
*/
|
|
972
1479
|
public sqlerp<T extends QuaternionLike = Quaternion>(
|
|
973
1480
|
a: QuaternionLike,
|
|
@@ -978,4 +1485,15 @@ export default class Quaternion extends Float32Array implements QuaternionLike {
|
|
|
978
1485
|
): T {
|
|
979
1486
|
return sqlerp(this, a, b, quaternion, t, out);
|
|
980
1487
|
}
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
* Convert this quaternion to equivalent z-y'-x" (intrinsic) Tait-Bryan angles.
|
|
1491
|
+
* @param out - The vector in which to store the Tait-Bryan angles.
|
|
1492
|
+
* @returns The Tait-Bryan angles in degrees in roll (z), pitch (y'), yaw (x") order.
|
|
1493
|
+
*/
|
|
1494
|
+
public toEuler<T extends Vector3Like = Vector3>(
|
|
1495
|
+
out: T = new Vector3() as Vector3 & T
|
|
1496
|
+
): T {
|
|
1497
|
+
return toEuler(this, out);
|
|
1498
|
+
}
|
|
981
1499
|
}
|