glmaths 0.0.1
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 +952 -0
- package/benchmark.js +747 -0
- package/dist/cjs/glmaths.d.ts +12053 -0
- package/dist/cjs/glmaths.js +6496 -0
- package/dist/cjs/glmaths.js.map +1 -0
- package/dist/cjs/glmaths.min.js +2 -0
- package/dist/cjs/glmaths.min.js.map +1 -0
- package/dist/esm/glmaths.d.ts +12053 -0
- package/dist/esm/glmaths.js +6453 -0
- package/dist/esm/glmaths.js.map +1 -0
- package/dist/esm/glmaths.min.js +2 -0
- package/dist/esm/glmaths.min.js.map +1 -0
- package/dist/glmaths.d.ts +12053 -0
- package/dist/glmaths.js +6501 -0
- package/dist/glmaths.js.map +1 -0
- package/dist/glmaths.min.js +2 -0
- package/dist/glmaths.min.js.map +1 -0
- package/docs.js +64 -0
- package/package.json +37 -0
- package/rollup.config.js +70 -0
- package/src/index.ts +19 -0
- package/src/internalUtils.ts +78 -0
- package/src/mat2.ts +324 -0
- package/src/mat2x3.ts +328 -0
- package/src/mat3.ts +629 -0
- package/src/mat4.ts +1319 -0
- package/src/quat.ts +819 -0
- package/src/quat2.ts +412 -0
- package/src/utils.ts +248 -0
- package/src/vec2.ts +798 -0
- package/src/vec3.ts +1069 -0
- package/src/vec4.ts +810 -0
- package/tests/mat2.test.ts +277 -0
- package/tests/mat2x3.test.ts +217 -0
- package/tests/mat3.test.ts +306 -0
- package/tests/mat4.test.ts +586 -0
- package/tests/quat.test.ts +418 -0
- package/tests/quat2.test.ts +222 -0
- package/tests/utils.test.ts +115 -0
- package/tests/vec2.test.ts +617 -0
- package/tests/vec3.test.ts +649 -0
- package/tests/vec4.test.ts +390 -0
- package/tsconfig.json +17 -0
- package/tsconfig.test.json +8 -0
package/src/mat4.ts
ADDED
|
@@ -0,0 +1,1319 @@
|
|
|
1
|
+
import glm from '.'
|
|
2
|
+
import { equals } from './internalUtils'
|
|
3
|
+
import { Vec2 } from './vec2'
|
|
4
|
+
import { Vec3 } from './vec3'
|
|
5
|
+
import { Quat } from './quat'
|
|
6
|
+
import { Vec4 } from './vec4'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 4x4 Matrix in column-major order
|
|
10
|
+
* @extends Float32Array
|
|
11
|
+
*/
|
|
12
|
+
export class Mat4 extends Float32Array {
|
|
13
|
+
|
|
14
|
+
static get identity() { return new Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) }
|
|
15
|
+
static get Identity() { return new Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) }
|
|
16
|
+
static get IDENTITY() { return new Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) }
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new 4x4 matrix
|
|
20
|
+
*
|
|
21
|
+
* @param {Number} m00 component in column 0, row 0
|
|
22
|
+
* @param {Number} m01 component in column 0, row 1
|
|
23
|
+
* @param {Number} m02 component in column 0, row 2
|
|
24
|
+
* @param {Number} m03 component in column 0, row 3
|
|
25
|
+
* @param {Number} m10 component in column 1, row 0
|
|
26
|
+
* @param {Number} m11 component in column 1, row 1
|
|
27
|
+
* @param {Number} m12 component in column 1, row 2
|
|
28
|
+
* @param {Number} m13 component in column 1, row 3
|
|
29
|
+
* @param {Number} m20 component in column 2, row 0
|
|
30
|
+
* @param {Number} m21 component in column 2, row 1
|
|
31
|
+
* @param {Number} m22 component in column 2, row 2
|
|
32
|
+
* @param {Number} m23 component in column 2, row 3
|
|
33
|
+
* @param {Number} m30 component in column 3, row 0
|
|
34
|
+
* @param {Number} m31 component in column 3, row 1
|
|
35
|
+
* @param {Number} m32 component in column 3, row 2
|
|
36
|
+
* @param {Number} m33 component in column 3, row 3
|
|
37
|
+
*/
|
|
38
|
+
constructor(
|
|
39
|
+
m00 = 0, m01 = 0, m02 = 0, m03 = 0,
|
|
40
|
+
m10 = 0, m11 = 0, m12 = 0, m13 = 0,
|
|
41
|
+
m20 = 0, m21 = 0, m22 = 0, m23 = 0,
|
|
42
|
+
m30 = 0, m31 = 0, m32 = 0, m33 = 0
|
|
43
|
+
) {
|
|
44
|
+
super(16)
|
|
45
|
+
this[0] = m00
|
|
46
|
+
this[1] = m01
|
|
47
|
+
this[2] = m02
|
|
48
|
+
this[3] = m03
|
|
49
|
+
this[4] = m10
|
|
50
|
+
this[5] = m11
|
|
51
|
+
this[6] = m12
|
|
52
|
+
this[7] = m13
|
|
53
|
+
this[8] = m20
|
|
54
|
+
this[9] = m21
|
|
55
|
+
this[10] = m22
|
|
56
|
+
this[11] = m23
|
|
57
|
+
this[12] = m30
|
|
58
|
+
this[13] = m31
|
|
59
|
+
this[14] = m32
|
|
60
|
+
this[15] = m33
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates a new mat4 initialized with values from a matrix
|
|
65
|
+
*
|
|
66
|
+
* @returns {Mat4} a new 4x4 matrix
|
|
67
|
+
*/
|
|
68
|
+
clone() {
|
|
69
|
+
return new Mat4(
|
|
70
|
+
this[0], this[1], this[2], this[3],
|
|
71
|
+
this[4], this[5], this[6], this[7],
|
|
72
|
+
this[8], this[9], this[10], this[11],
|
|
73
|
+
this[12], this[13], this[14], this[15]
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Transposes a mat4
|
|
79
|
+
*
|
|
80
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
81
|
+
* @returns {Mat4} out
|
|
82
|
+
*/
|
|
83
|
+
transpose(out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
84
|
+
if (out === this) {
|
|
85
|
+
const a01 = this[1], a02 = this[2], a03 = this[3]
|
|
86
|
+
const a12 = this[6], a13 = this[7], a23 = this[11]
|
|
87
|
+
out[1] = this[4]
|
|
88
|
+
out[2] = this[8]
|
|
89
|
+
out[3] = this[12]
|
|
90
|
+
out[4] = a01
|
|
91
|
+
out[6] = this[9]
|
|
92
|
+
out[7] = this[13]
|
|
93
|
+
out[8] = a02
|
|
94
|
+
out[9] = a12
|
|
95
|
+
out[11] = this[14]
|
|
96
|
+
out[12] = a03
|
|
97
|
+
out[13] = a13
|
|
98
|
+
out[14] = a23
|
|
99
|
+
} else {
|
|
100
|
+
out[0] = this[0]; out[1] = this[4]; out[2] = this[8]; out[3] = this[12]
|
|
101
|
+
out[4] = this[1]; out[5] = this[5]; out[6] = this[9]; out[7] = this[13]
|
|
102
|
+
out[8] = this[2]; out[9] = this[6]; out[10] = this[10]; out[11] = this[14]
|
|
103
|
+
out[12] = this[3]; out[13] = this[7]; out[14] = this[11]; out[15] = this[15]
|
|
104
|
+
}
|
|
105
|
+
return out
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Inverts a mat4
|
|
110
|
+
*
|
|
111
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
112
|
+
* @returns {Mat4} out
|
|
113
|
+
*/
|
|
114
|
+
invert(out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
115
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
116
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
117
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
118
|
+
const a30 = this[12], a31 = this[13], a32 = this[14], a33 = this[15]
|
|
119
|
+
|
|
120
|
+
const b00 = a00 * a11 - a01 * a10
|
|
121
|
+
const b01 = a00 * a12 - a02 * a10
|
|
122
|
+
const b02 = a00 * a13 - a03 * a10
|
|
123
|
+
const b03 = a01 * a12 - a02 * a11
|
|
124
|
+
const b04 = a01 * a13 - a03 * a11
|
|
125
|
+
const b05 = a02 * a13 - a03 * a12
|
|
126
|
+
const b06 = a20 * a31 - a21 * a30
|
|
127
|
+
const b07 = a20 * a32 - a22 * a30
|
|
128
|
+
const b08 = a20 * a33 - a23 * a30
|
|
129
|
+
const b09 = a21 * a32 - a22 * a31
|
|
130
|
+
const b10 = a21 * a33 - a23 * a31
|
|
131
|
+
const b11 = a22 * a33 - a23 * a32
|
|
132
|
+
|
|
133
|
+
let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06
|
|
134
|
+
if (!det) return null
|
|
135
|
+
det = 1.0 / det
|
|
136
|
+
|
|
137
|
+
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det
|
|
138
|
+
out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det
|
|
139
|
+
out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det
|
|
140
|
+
out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det
|
|
141
|
+
out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det
|
|
142
|
+
out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det
|
|
143
|
+
out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det
|
|
144
|
+
out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det
|
|
145
|
+
out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det
|
|
146
|
+
out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det
|
|
147
|
+
out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det
|
|
148
|
+
out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det
|
|
149
|
+
out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det
|
|
150
|
+
out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det
|
|
151
|
+
out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det
|
|
152
|
+
out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det
|
|
153
|
+
return out
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Calculates the adjugate of a mat4
|
|
158
|
+
*
|
|
159
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
160
|
+
* @returns {Mat4} out
|
|
161
|
+
*/
|
|
162
|
+
adjoint(out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
163
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
164
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
165
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
166
|
+
const a30 = this[12], a31 = this[13], a32 = this[14], a33 = this[15]
|
|
167
|
+
|
|
168
|
+
const b00 = a00 * a11 - a01 * a10
|
|
169
|
+
const b01 = a00 * a12 - a02 * a10
|
|
170
|
+
const b02 = a00 * a13 - a03 * a10
|
|
171
|
+
const b03 = a01 * a12 - a02 * a11
|
|
172
|
+
const b04 = a01 * a13 - a03 * a11
|
|
173
|
+
const b05 = a02 * a13 - a03 * a12
|
|
174
|
+
const b06 = a20 * a31 - a21 * a30
|
|
175
|
+
const b07 = a20 * a32 - a22 * a30
|
|
176
|
+
const b08 = a20 * a33 - a23 * a30
|
|
177
|
+
const b09 = a21 * a32 - a22 * a31
|
|
178
|
+
const b10 = a21 * a33 - a23 * a31
|
|
179
|
+
const b11 = a22 * a33 - a23 * a32
|
|
180
|
+
|
|
181
|
+
out[0] = a11 * b11 - a12 * b10 + a13 * b09
|
|
182
|
+
out[1] = a02 * b10 - a01 * b11 - a03 * b09
|
|
183
|
+
out[2] = a31 * b05 - a32 * b04 + a33 * b03
|
|
184
|
+
out[3] = a22 * b04 - a21 * b05 - a23 * b03
|
|
185
|
+
out[4] = a12 * b08 - a10 * b11 - a13 * b07
|
|
186
|
+
out[5] = a00 * b11 - a02 * b08 + a03 * b07
|
|
187
|
+
out[6] = a32 * b02 - a30 * b05 - a33 * b01
|
|
188
|
+
out[7] = a20 * b05 - a22 * b02 + a23 * b01
|
|
189
|
+
out[8] = a10 * b10 - a11 * b08 + a13 * b06
|
|
190
|
+
out[9] = a01 * b08 - a00 * b10 - a03 * b06
|
|
191
|
+
out[10] = a30 * b04 - a31 * b02 + a33 * b00
|
|
192
|
+
out[11] = a21 * b02 - a20 * b04 - a23 * b00
|
|
193
|
+
out[12] = a11 * b07 - a10 * b09 - a12 * b06
|
|
194
|
+
out[13] = a00 * b09 - a01 * b07 + a02 * b06
|
|
195
|
+
out[14] = a31 * b01 - a30 * b03 - a32 * b00
|
|
196
|
+
out[15] = a20 * b03 - a21 * b01 + a22 * b00
|
|
197
|
+
return out
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Calculates the determinant of a mat4
|
|
202
|
+
*
|
|
203
|
+
* @returns {Number} determinant of a mat4
|
|
204
|
+
*/
|
|
205
|
+
determinant() {
|
|
206
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
207
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
208
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
209
|
+
const a30 = this[12], a31 = this[13], a32 = this[14], a33 = this[15]
|
|
210
|
+
return (
|
|
211
|
+
(a00 * a11 - a01 * a10) * (a22 * a33 - a23 * a32) -
|
|
212
|
+
(a00 * a12 - a02 * a10) * (a21 * a33 - a23 * a31) +
|
|
213
|
+
(a00 * a13 - a03 * a10) * (a21 * a32 - a22 * a31) +
|
|
214
|
+
(a01 * a12 - a02 * a11) * (a20 * a33 - a23 * a30) -
|
|
215
|
+
(a01 * a13 - a03 * a11) * (a20 * a32 - a22 * a30) +
|
|
216
|
+
(a02 * a13 - a03 * a12) * (a20 * a31 - a21 * a30)
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Multiplies with another matrix, or transforms a vector
|
|
222
|
+
*
|
|
223
|
+
* @param {Vec2 | Vec3 | Vec4 | Mat4} b the second operand
|
|
224
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
225
|
+
* @returns {Mat4} out
|
|
226
|
+
*/
|
|
227
|
+
multiply(b: Vec2): Vec2
|
|
228
|
+
multiply(b: Vec3): Vec3
|
|
229
|
+
multiply(b: Vec4): Vec4
|
|
230
|
+
multiply(b: Mat4, out?: Mat4): Mat4
|
|
231
|
+
multiply(b: Mat4 | Vec2 | Vec3 | Vec4, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
232
|
+
if (b instanceof Vec2)
|
|
233
|
+
return b.transformMat4(this)
|
|
234
|
+
if (b instanceof Vec3)
|
|
235
|
+
return b.transformMat4(this)
|
|
236
|
+
if (b instanceof Vec4)
|
|
237
|
+
return b.transformMat4(this)
|
|
238
|
+
|
|
239
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
240
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
241
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
242
|
+
const a30 = this[12], a31 = this[13], a32 = this[14], a33 = this[15]
|
|
243
|
+
|
|
244
|
+
let b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]
|
|
245
|
+
out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30
|
|
246
|
+
out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31
|
|
247
|
+
out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32
|
|
248
|
+
out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33
|
|
249
|
+
|
|
250
|
+
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]
|
|
251
|
+
out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30
|
|
252
|
+
out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31
|
|
253
|
+
out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32
|
|
254
|
+
out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33
|
|
255
|
+
|
|
256
|
+
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]
|
|
257
|
+
out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30
|
|
258
|
+
out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31
|
|
259
|
+
out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32
|
|
260
|
+
out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33
|
|
261
|
+
|
|
262
|
+
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]
|
|
263
|
+
out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30
|
|
264
|
+
out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31
|
|
265
|
+
out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32
|
|
266
|
+
out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33
|
|
267
|
+
return out
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Translates a mat4 by the given Vec3
|
|
272
|
+
*
|
|
273
|
+
* @param {Vec3} v vector to translate by
|
|
274
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
275
|
+
* @returns {Mat4} out
|
|
276
|
+
*/
|
|
277
|
+
translate(v: Vec3, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
278
|
+
const x = v[0], y = v[1], z = v[2]
|
|
279
|
+
if (out === this) {
|
|
280
|
+
out[12] = this[0] * x + this[4] * y + this[8] * z + this[12]
|
|
281
|
+
out[13] = this[1] * x + this[5] * y + this[9] * z + this[13]
|
|
282
|
+
out[14] = this[2] * x + this[6] * y + this[10] * z + this[14]
|
|
283
|
+
out[15] = this[3] * x + this[7] * y + this[11] * z + this[15]
|
|
284
|
+
} else {
|
|
285
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
286
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
287
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
288
|
+
out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03
|
|
289
|
+
out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13
|
|
290
|
+
out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23
|
|
291
|
+
out[12] = a00 * x + a10 * y + a20 * z + this[12]
|
|
292
|
+
out[13] = a01 * x + a11 * y + a21 * z + this[13]
|
|
293
|
+
out[14] = a02 * x + a12 * y + a22 * z + this[14]
|
|
294
|
+
out[15] = a03 * x + a13 * y + a23 * z + this[15]
|
|
295
|
+
}
|
|
296
|
+
return out
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Scales a mat4 by the dimensions in the given Vec3 not using vectorization
|
|
301
|
+
*
|
|
302
|
+
* @param {Vec3} v the Vec3 to scale the matrix by
|
|
303
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
304
|
+
* @returns {Mat4} out
|
|
305
|
+
*/
|
|
306
|
+
scale(v: Vec3, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
307
|
+
const x = v[0], y = v[1], z = v[2]
|
|
308
|
+
out[0] = this[0] * x; out[1] = this[1] * x; out[2] = this[2] * x; out[3] = this[3] * x
|
|
309
|
+
out[4] = this[4] * y; out[5] = this[5] * y; out[6] = this[6] * y; out[7] = this[7] * y
|
|
310
|
+
out[8] = this[8] * z; out[9] = this[9] * z; out[10] = this[10] * z; out[11] = this[11] * z
|
|
311
|
+
out[12] = this[12]; out[13] = this[13]; out[14] = this[14]; out[15] = this[15]
|
|
312
|
+
return out
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Rotates a mat4 by the given angle around the given axis
|
|
317
|
+
*
|
|
318
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
319
|
+
* @param {Vec3} axis the axis to rotate around
|
|
320
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
321
|
+
* @returns {Mat4} out
|
|
322
|
+
*/
|
|
323
|
+
rotate(rad: number, axis: Vec3, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
324
|
+
let x = axis[0], y = axis[1], z = axis[2]
|
|
325
|
+
let len = Math.sqrt(x * x + y * y + z * z)
|
|
326
|
+
if (len < glm.EPSILON) return null
|
|
327
|
+
len = 1 / len
|
|
328
|
+
x *= len; y *= len; z *= len
|
|
329
|
+
|
|
330
|
+
const s = Math.sin(rad), c = Math.cos(rad), t = 1 - c
|
|
331
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
332
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
333
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
334
|
+
|
|
335
|
+
const b00 = x * x * t + c, b01 = y * x * t + z * s, b02 = z * x * t - y * s
|
|
336
|
+
const b10 = x * y * t - z * s, b11 = y * y * t + c, b12 = z * y * t + x * s
|
|
337
|
+
const b20 = x * z * t + y * s, b21 = y * z * t - x * s, b22 = z * z * t + c
|
|
338
|
+
|
|
339
|
+
out[0] = a00 * b00 + a10 * b01 + a20 * b02
|
|
340
|
+
out[1] = a01 * b00 + a11 * b01 + a21 * b02
|
|
341
|
+
out[2] = a02 * b00 + a12 * b01 + a22 * b02
|
|
342
|
+
out[3] = a03 * b00 + a13 * b01 + a23 * b02
|
|
343
|
+
out[4] = a00 * b10 + a10 * b11 + a20 * b12
|
|
344
|
+
out[5] = a01 * b10 + a11 * b11 + a21 * b12
|
|
345
|
+
out[6] = a02 * b10 + a12 * b11 + a22 * b12
|
|
346
|
+
out[7] = a03 * b10 + a13 * b11 + a23 * b12
|
|
347
|
+
out[8] = a00 * b20 + a10 * b21 + a20 * b22
|
|
348
|
+
out[9] = a01 * b20 + a11 * b21 + a21 * b22
|
|
349
|
+
out[10] = a02 * b20 + a12 * b21 + a22 * b22
|
|
350
|
+
out[11] = a03 * b20 + a13 * b21 + a23 * b22
|
|
351
|
+
out[12] = this[12]; out[13] = this[13]; out[14] = this[14]; out[15] = this[15]
|
|
352
|
+
return out
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Rotates a mat4 by the given angle around the X axis
|
|
357
|
+
*
|
|
358
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
359
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
360
|
+
* @returns {Mat4} out
|
|
361
|
+
*/
|
|
362
|
+
rotateX(rad: number, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
363
|
+
const s = Math.sin(rad), c = Math.cos(rad)
|
|
364
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
365
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
366
|
+
|
|
367
|
+
out[4] = a10 * c + a20 * s; out[5] = a11 * c + a21 * s
|
|
368
|
+
out[6] = a12 * c + a22 * s; out[7] = a13 * c + a23 * s
|
|
369
|
+
out[8] = a20 * c - a10 * s; out[9] = a21 * c - a11 * s
|
|
370
|
+
out[10] = a22 * c - a12 * s; out[11] = a23 * c - a13 * s
|
|
371
|
+
|
|
372
|
+
if (out !== this) {
|
|
373
|
+
out[0] = this[0]; out[1] = this[1]; out[2] = this[2]; out[3] = this[3]
|
|
374
|
+
out[12] = this[12]; out[13] = this[13]; out[14] = this[14]; out[15] = this[15]
|
|
375
|
+
}
|
|
376
|
+
return out
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Rotates a mat4 by the given angle around the Y axis
|
|
381
|
+
*
|
|
382
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
383
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
384
|
+
* @returns {Mat4} out
|
|
385
|
+
*/
|
|
386
|
+
rotateY(rad: number, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
387
|
+
const s = Math.sin(rad), c = Math.cos(rad)
|
|
388
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
389
|
+
const a20 = this[8], a21 = this[9], a22 = this[10], a23 = this[11]
|
|
390
|
+
|
|
391
|
+
out[0] = a00 * c - a20 * s; out[1] = a01 * c - a21 * s
|
|
392
|
+
out[2] = a02 * c - a22 * s; out[3] = a03 * c - a23 * s
|
|
393
|
+
out[8] = a00 * s + a20 * c; out[9] = a01 * s + a21 * c
|
|
394
|
+
out[10] = a02 * s + a22 * c; out[11] = a03 * s + a23 * c
|
|
395
|
+
|
|
396
|
+
if (out !== this) {
|
|
397
|
+
out[4] = this[4]; out[5] = this[5]; out[6] = this[6]; out[7] = this[7]
|
|
398
|
+
out[12] = this[12]; out[13] = this[13]; out[14] = this[14]; out[15] = this[15]
|
|
399
|
+
}
|
|
400
|
+
return out
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Rotates a mat4 by the given angle around the Z axis
|
|
405
|
+
*
|
|
406
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
407
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
408
|
+
* @returns {Mat4} out
|
|
409
|
+
*/
|
|
410
|
+
rotateZ(rad: number, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
411
|
+
const s = Math.sin(rad), c = Math.cos(rad)
|
|
412
|
+
const a00 = this[0], a01 = this[1], a02 = this[2], a03 = this[3]
|
|
413
|
+
const a10 = this[4], a11 = this[5], a12 = this[6], a13 = this[7]
|
|
414
|
+
|
|
415
|
+
out[0] = a00 * c + a10 * s; out[1] = a01 * c + a11 * s
|
|
416
|
+
out[2] = a02 * c + a12 * s; out[3] = a03 * c + a13 * s
|
|
417
|
+
out[4] = a10 * c - a00 * s; out[5] = a11 * c - a01 * s
|
|
418
|
+
out[6] = a12 * c - a02 * s; out[7] = a13 * c - a03 * s
|
|
419
|
+
|
|
420
|
+
if (out !== this) {
|
|
421
|
+
out[8] = this[8]; out[9] = this[9]; out[10] = this[10]; out[11] = this[11]
|
|
422
|
+
out[12] = this[12]; out[13] = this[13]; out[14] = this[14]; out[15] = this[15]
|
|
423
|
+
}
|
|
424
|
+
return out
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Returns the translation vector component of a transformation matrix
|
|
429
|
+
*
|
|
430
|
+
* @param {Vec3} out vector to receive the translation values, defaults to new Vec3()
|
|
431
|
+
* @returns {Vec3} out
|
|
432
|
+
*/
|
|
433
|
+
getTranslation(out = new Vec3()) {
|
|
434
|
+
out[0] = this[12]; out[1] = this[13]; out[2] = this[14]
|
|
435
|
+
return out
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Returns the scaling factor component of a transformation matrix
|
|
440
|
+
*
|
|
441
|
+
* @param {Vec3} out vector to receive the scaling factor values, defaults to new Vec3()
|
|
442
|
+
* @returns {Vec3} out
|
|
443
|
+
*/
|
|
444
|
+
getScaling(out = new Vec3()) {
|
|
445
|
+
const m11 = this[0], m12 = this[1], m13 = this[2]
|
|
446
|
+
const m21 = this[4], m22 = this[5], m23 = this[6]
|
|
447
|
+
const m31 = this[8], m32 = this[9], m33 = this[10]
|
|
448
|
+
out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13)
|
|
449
|
+
out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23)
|
|
450
|
+
out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33)
|
|
451
|
+
return out
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Returns a quaternion representing the rotational component
|
|
456
|
+
* of a transformation matrix. If a matrix is built with
|
|
457
|
+
* fromRotationTranslation, the returned quaternion will be the
|
|
458
|
+
* same as the quaternion originally supplied.
|
|
459
|
+
*
|
|
460
|
+
* @param {Quat} out quaternion to receive the rotation values, defaults to new Quat()
|
|
461
|
+
* @returns {Quat} out
|
|
462
|
+
*/
|
|
463
|
+
getRotation(out = new Quat()) {
|
|
464
|
+
const scaling = this.getScaling()
|
|
465
|
+
const is1 = 1 / scaling[0], is2 = 1 / scaling[1], is3 = 1 / scaling[2]
|
|
466
|
+
|
|
467
|
+
const sm11 = this[0] * is1, sm12 = this[1] * is2, sm13 = this[2] * is3
|
|
468
|
+
const sm21 = this[4] * is1, sm22 = this[5] * is2, sm23 = this[6] * is3
|
|
469
|
+
const sm31 = this[8] * is1, sm32 = this[9] * is2, sm33 = this[10] * is3
|
|
470
|
+
|
|
471
|
+
const trace = sm11 + sm22 + sm33
|
|
472
|
+
let S = 0
|
|
473
|
+
|
|
474
|
+
if (trace > 0) {
|
|
475
|
+
S = Math.sqrt(trace + 1.0) * 2
|
|
476
|
+
out[3] = 0.25 * S
|
|
477
|
+
out[0] = (sm23 - sm32) / S
|
|
478
|
+
out[1] = (sm31 - sm13) / S
|
|
479
|
+
out[2] = (sm12 - sm21) / S
|
|
480
|
+
} else if (sm11 > sm22 && sm11 > sm33) {
|
|
481
|
+
S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2
|
|
482
|
+
out[3] = (sm23 - sm32) / S
|
|
483
|
+
out[0] = 0.25 * S
|
|
484
|
+
out[1] = (sm12 + sm21) / S
|
|
485
|
+
out[2] = (sm31 + sm13) / S
|
|
486
|
+
} else if (sm22 > sm33) {
|
|
487
|
+
S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2
|
|
488
|
+
out[3] = (sm31 - sm13) / S
|
|
489
|
+
out[0] = (sm12 + sm21) / S
|
|
490
|
+
out[1] = 0.25 * S
|
|
491
|
+
out[2] = (sm23 + sm32) / S
|
|
492
|
+
} else {
|
|
493
|
+
S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2
|
|
494
|
+
out[3] = (sm12 - sm21) / S
|
|
495
|
+
out[0] = (sm31 + sm13) / S
|
|
496
|
+
out[1] = (sm23 + sm32) / S
|
|
497
|
+
out[2] = 0.25 * S
|
|
498
|
+
}
|
|
499
|
+
return out
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Decomposes a transformation matrix into its rotation, translation, and scale components
|
|
504
|
+
*
|
|
505
|
+
* @param {Quat} out_r quaternion to receive the rotation component, defaults to new Quat()
|
|
506
|
+
* @param {Vec3} out_t vector to receive the translation component, defaults to new Vec3()
|
|
507
|
+
* @param {Vec3} out_s vector to receive the scaling component, defaults to new Vec3()
|
|
508
|
+
* @returns {Quat} out_r
|
|
509
|
+
*/
|
|
510
|
+
decompose(out_r = new Quat(), out_t = new Vec3(), out_s = new Vec3()) {
|
|
511
|
+
out_t[0] = this[12]; out_t[1] = this[13]; out_t[2] = this[14]
|
|
512
|
+
|
|
513
|
+
const m11 = this[0], m12 = this[1], m13 = this[2]
|
|
514
|
+
const m21 = this[4], m22 = this[5], m23 = this[6]
|
|
515
|
+
const m31 = this[8], m32 = this[9], m33 = this[10]
|
|
516
|
+
|
|
517
|
+
out_s[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13)
|
|
518
|
+
out_s[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23)
|
|
519
|
+
out_s[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33)
|
|
520
|
+
|
|
521
|
+
const is1 = 1 / out_s[0], is2 = 1 / out_s[1], is3 = 1 / out_s[2]
|
|
522
|
+
|
|
523
|
+
const sm11 = m11 * is1, sm12 = m12 * is2, sm13 = m13 * is3
|
|
524
|
+
const sm21 = m21 * is1, sm22 = m22 * is2, sm23 = m23 * is3
|
|
525
|
+
const sm31 = m31 * is1, sm32 = m32 * is2, sm33 = m33 * is3
|
|
526
|
+
|
|
527
|
+
const trace = sm11 + sm22 + sm33
|
|
528
|
+
let S = 0
|
|
529
|
+
|
|
530
|
+
if (trace > 0) {
|
|
531
|
+
S = Math.sqrt(trace + 1.0) * 2
|
|
532
|
+
out_r[3] = 0.25 * S
|
|
533
|
+
out_r[0] = (sm23 - sm32) / S
|
|
534
|
+
out_r[1] = (sm31 - sm13) / S
|
|
535
|
+
out_r[2] = (sm12 - sm21) / S
|
|
536
|
+
} else if (sm11 > sm22 && sm11 > sm33) {
|
|
537
|
+
S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2
|
|
538
|
+
out_r[3] = (sm23 - sm32) / S
|
|
539
|
+
out_r[0] = 0.25 * S
|
|
540
|
+
out_r[1] = (sm12 + sm21) / S
|
|
541
|
+
out_r[2] = (sm31 + sm13) / S
|
|
542
|
+
} else if (sm22 > sm33) {
|
|
543
|
+
S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2
|
|
544
|
+
out_r[3] = (sm31 - sm13) / S
|
|
545
|
+
out_r[0] = (sm12 + sm21) / S
|
|
546
|
+
out_r[1] = 0.25 * S
|
|
547
|
+
out_r[2] = (sm23 + sm32) / S
|
|
548
|
+
} else {
|
|
549
|
+
S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2
|
|
550
|
+
out_r[3] = (sm12 - sm21) / S
|
|
551
|
+
out_r[0] = (sm31 + sm13) / S
|
|
552
|
+
out_r[1] = (sm23 + sm32) / S
|
|
553
|
+
out_r[2] = 0.25 * S
|
|
554
|
+
}
|
|
555
|
+
return out_r
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Creates a matrix from a vector translation
|
|
560
|
+
*
|
|
561
|
+
* @param {Vec3} v translation vector
|
|
562
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
563
|
+
* @returns {Mat4} out
|
|
564
|
+
*/
|
|
565
|
+
static fromTranslation(v: Vec3, out = new Mat4()) {
|
|
566
|
+
out[0] = out[5] = out[10] = out[15] = 1
|
|
567
|
+
out[1] = out[2] = out[3] = out[4] = out[6] = out[7] = out[8] = out[9] = out[11] = 0
|
|
568
|
+
out[12] = v[0]
|
|
569
|
+
out[13] = v[1]
|
|
570
|
+
out[14] = v[2]
|
|
571
|
+
return out
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Creates a matrix from a vector scaling
|
|
576
|
+
*
|
|
577
|
+
* @param {Vec3} v scaling vector
|
|
578
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
579
|
+
* @returns {Mat4} out
|
|
580
|
+
*/
|
|
581
|
+
static fromScaling(v: Vec3, out = new Mat4()) {
|
|
582
|
+
out[0] = v[0]
|
|
583
|
+
out[5] = v[1]
|
|
584
|
+
out[10] = v[2]
|
|
585
|
+
out[1] = out[2] = out[3] = out[4] = out[6] = out[7] = out[8] = out[9] = out[11] = out[12] = out[13] = out[14] = 0
|
|
586
|
+
out[15] = 1
|
|
587
|
+
return out
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Creates a matrix from a given angle around a given axis
|
|
592
|
+
*
|
|
593
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
594
|
+
* @param {Vec3} axis the axis to rotate around
|
|
595
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
596
|
+
* @returns {Mat4} out
|
|
597
|
+
*/
|
|
598
|
+
static fromRotation(rad: number, axis: Vec3, out = new Mat4()) {
|
|
599
|
+
let x = axis[0], y = axis[1], z = axis[2]
|
|
600
|
+
let len = Math.sqrt(x * x + y * y + z * z)
|
|
601
|
+
if (len < glm.EPSILON) return null
|
|
602
|
+
len = 1 / len
|
|
603
|
+
x *= len; y *= len; z *= len
|
|
604
|
+
|
|
605
|
+
const s = Math.sin(rad), c = Math.cos(rad), t = 1 - c
|
|
606
|
+
|
|
607
|
+
out[0] = x * x * t + c; out[1] = y * x * t + z * s; out[2] = z * x * t - y * s; out[3] = 0
|
|
608
|
+
out[4] = x * y * t - z * s; out[5] = y * y * t + c; out[6] = z * y * t + x * s; out[7] = 0
|
|
609
|
+
out[8] = x * z * t + y * s; out[9] = y * z * t - x * s; out[10] = z * z * t + c; out[11] = 0
|
|
610
|
+
out[12] = out[13] = out[14] = 0
|
|
611
|
+
out[15] = 1
|
|
612
|
+
return out
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Creates a matrix from the given angle around the X axis
|
|
617
|
+
*
|
|
618
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
619
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
620
|
+
* @returns {Mat4} out
|
|
621
|
+
*/
|
|
622
|
+
static fromXRotation(rad: number, out = new Mat4()) {
|
|
623
|
+
const s = Math.sin(rad), c = Math.cos(rad)
|
|
624
|
+
out[0] = 1
|
|
625
|
+
out[1] = out[2] = out[3] = out[4] = out[7] = out[8] = out[11] = out[12] = out[13] = out[14] = 0
|
|
626
|
+
out[5] = c
|
|
627
|
+
out[6] = s
|
|
628
|
+
out[9] = -s
|
|
629
|
+
out[10] = c
|
|
630
|
+
out[15] = 1
|
|
631
|
+
return out
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Creates a matrix from the given angle around the Y axis
|
|
636
|
+
*
|
|
637
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
638
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
639
|
+
* @returns {Mat4} out
|
|
640
|
+
*/
|
|
641
|
+
static fromYRotation(rad: number, out = new Mat4()) {
|
|
642
|
+
const s = Math.sin(rad), c = Math.cos(rad)
|
|
643
|
+
out[0] = c
|
|
644
|
+
out[1] = out[3] = out[4] = out[6] = out[7] = out[9] = out[11] = out[12] = out[13] = out[14] = 0
|
|
645
|
+
out[2] = -s
|
|
646
|
+
out[5] = out[15] = 1
|
|
647
|
+
out[8] = s
|
|
648
|
+
out[10] = c
|
|
649
|
+
return out
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Creates a matrix from the given angle around the Z axis
|
|
654
|
+
*
|
|
655
|
+
* @param {Number} rad the angle to rotate the matrix by
|
|
656
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
657
|
+
* @returns {Mat4} out
|
|
658
|
+
*/
|
|
659
|
+
static fromZRotation(rad: number, out = new Mat4()) {
|
|
660
|
+
const s = Math.sin(rad), c = Math.cos(rad)
|
|
661
|
+
out[0] = c
|
|
662
|
+
out[1] = s
|
|
663
|
+
out[4] = -s
|
|
664
|
+
out[5] = c
|
|
665
|
+
out[2] = out[3] = out[6] = out[7] = out[8] = out[9] = out[11] = out[12] = out[13] = out[14] = 0
|
|
666
|
+
out[10] = out[15] = 1
|
|
667
|
+
return out
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Creates a matrix from a quaternion rotation and vector translation
|
|
672
|
+
*
|
|
673
|
+
* @param {Quat} q rotation quaternion
|
|
674
|
+
* @param {Vec3} v translation vector
|
|
675
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
676
|
+
* @returns {Mat4} out
|
|
677
|
+
*/
|
|
678
|
+
static fromRotationTranslation(q: Quat, v: Vec3, out = new Mat4()) {
|
|
679
|
+
const x = q[0], y = q[1], z = q[2], w = q[3]
|
|
680
|
+
const x2 = x + x, y2 = y + y, z2 = z + z
|
|
681
|
+
const xx = x * x2, xy = x * y2, xz = x * z2
|
|
682
|
+
const yy = y * y2, yz = y * z2, zz = z * z2
|
|
683
|
+
const wx = w * x2, wy = w * y2, wz = w * z2
|
|
684
|
+
|
|
685
|
+
out[0] = 1 - (yy + zz); out[1] = xy + wz; out[2] = xz - wy
|
|
686
|
+
out[3] = out[7] = out[11] = 0
|
|
687
|
+
out[4] = xy - wz; out[5] = 1 - (xx + zz); out[6] = yz + wx
|
|
688
|
+
out[8] = xz + wy; out[9] = yz - wx; out[10] = 1 - (xx + yy)
|
|
689
|
+
out[12] = v[0]; out[13] = v[1]; out[14] = v[2]; out[15] = 1
|
|
690
|
+
return out
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Creates a matrix from a quaternion rotation, vector translation, and vector scale
|
|
695
|
+
*
|
|
696
|
+
* @param {Quat} q rotation quaternion
|
|
697
|
+
* @param {Vec3} v translation vector
|
|
698
|
+
* @param {Vec3} s scaling vector
|
|
699
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
700
|
+
* @returns {Mat4} out
|
|
701
|
+
*/
|
|
702
|
+
static fromRotationTranslationScale(q: Quat, v: Vec3, s: Vec3, out = new Mat4()) {
|
|
703
|
+
const x = q[0], y = q[1], z = q[2], w = q[3]
|
|
704
|
+
const x2 = x + x, y2 = y + y, z2 = z + z
|
|
705
|
+
const xx = x * x2, xy = x * y2, xz = x * z2
|
|
706
|
+
const yy = y * y2, yz = y * z2, zz = z * z2
|
|
707
|
+
const wx = w * x2, wy = w * y2, wz = w * z2
|
|
708
|
+
const sx = s[0], sy = s[1], sz = s[2]
|
|
709
|
+
|
|
710
|
+
out[0] = (1 - (yy + zz)) * sx; out[1] = (xy + wz) * sx; out[2] = (xz - wy) * sx;
|
|
711
|
+
out[3] = out[7] = out[11] = 0
|
|
712
|
+
out[4] = (xy - wz) * sy; out[5] = (1 - (xx + zz)) * sy; out[6] = (yz + wx) * sy;
|
|
713
|
+
out[8] = (xz + wy) * sz; out[9] = (yz - wx) * sz; out[10] = (1 - (xx + yy)) * sz;
|
|
714
|
+
out[12] = v[0]; out[13] = v[1]; out[14] = v[2]; out[15] = 1
|
|
715
|
+
return out
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Creates a matrix from a quaternion rotation, vector translation, vector scale, and origin
|
|
720
|
+
*
|
|
721
|
+
* @param {Quat} q rotation quaternion
|
|
722
|
+
* @param {Vec3} v translation vector
|
|
723
|
+
* @param {Vec3} s scaling vector
|
|
724
|
+
* @param {Vec3} o the origin vector
|
|
725
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
726
|
+
* @returns {Mat4} out
|
|
727
|
+
*/
|
|
728
|
+
static fromRotationTranslationScaleOrigin(q: Quat, v: Vec3, s: Vec3, o: Vec3, out = new Mat4()) {
|
|
729
|
+
const x = q[0], y = q[1], z = q[2], w = q[3]
|
|
730
|
+
const x2 = x + x, y2 = y + y, z2 = z + z
|
|
731
|
+
const xx = x * x2, xy = x * y2, xz = x * z2
|
|
732
|
+
const yy = y * y2, yz = y * z2, zz = z * z2
|
|
733
|
+
const wx = w * x2, wy = w * y2, wz = w * z2
|
|
734
|
+
const sx = s[0], sy = s[1], sz = s[2]
|
|
735
|
+
const ox = o[0], oy = o[1], oz = o[2]
|
|
736
|
+
|
|
737
|
+
const out0 = (1 - (yy + zz)) * sx
|
|
738
|
+
const out1 = (xy + wz) * sx
|
|
739
|
+
const out2 = (xz - wy) * sx
|
|
740
|
+
const out4 = (xy - wz) * sy
|
|
741
|
+
const out5 = (1 - (xx + zz)) * sy
|
|
742
|
+
const out6 = (yz + wx) * sy
|
|
743
|
+
const out8 = (xz + wy) * sz
|
|
744
|
+
const out9 = (yz - wx) * sz
|
|
745
|
+
const out10 = (1 - (xx + yy)) * sz
|
|
746
|
+
|
|
747
|
+
out[0] = out0; out[1] = out1; out[2] = out2
|
|
748
|
+
out[4] = out4; out[5] = out5; out[6] = out6
|
|
749
|
+
out[8] = out8; out[9] = out9; out[10] = out10
|
|
750
|
+
out[3] = out[7] = out[11] = 0
|
|
751
|
+
out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz)
|
|
752
|
+
out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz)
|
|
753
|
+
out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz)
|
|
754
|
+
out[15] = 1
|
|
755
|
+
return out
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Calculates a 4x4 matrix from the given quaternion
|
|
760
|
+
*
|
|
761
|
+
* @param {Quat} q quaternion to create matrix from
|
|
762
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
763
|
+
* @returns {Mat4} out
|
|
764
|
+
*/
|
|
765
|
+
static fromQuat(q: Quat, out = new Mat4()) {
|
|
766
|
+
const x = q[0], y = q[1], z = q[2], w = q[3]
|
|
767
|
+
const x2 = x + x, y2 = y + y, z2 = z + z
|
|
768
|
+
const xx = x * x2, yx = y * x2, yy = y * y2
|
|
769
|
+
const zx = z * x2, zy = z * y2, zz = z * z2
|
|
770
|
+
const wx = w * x2, wy = w * y2, wz = w * z2
|
|
771
|
+
|
|
772
|
+
out[0] = 1 - yy - zz; out[1] = yx + wz; out[2] = zx - wy
|
|
773
|
+
out[4] = yx - wz; out[5] = 1 - xx - zz; out[6] = zy + wx
|
|
774
|
+
out[8] = zx + wy; out[9] = zy - wx; out[10] = 1 - xx - yy
|
|
775
|
+
out[3] = out[7] = out[11] = out[12] = out[13] = out[14] = 0
|
|
776
|
+
out[15] = 1
|
|
777
|
+
return out
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Generates a frustum matrix with the given bounds
|
|
782
|
+
*
|
|
783
|
+
* @param {Number} left left bound of the frustum
|
|
784
|
+
* @param {Number} right right bound of the frustum
|
|
785
|
+
* @param {Number} bottom bottom bound of the frustum
|
|
786
|
+
* @param {Number} top top bound of the frustum
|
|
787
|
+
* @param {Number} near near bound of the frustum
|
|
788
|
+
* @param {Number} far far bound of the frustum
|
|
789
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
790
|
+
* @returns {Mat4} out
|
|
791
|
+
*/
|
|
792
|
+
static frustum(left: number, right: number, bottom: number, top: number, near: number, far: number, out = new Mat4()) {
|
|
793
|
+
const rl = 1 / (right - left)
|
|
794
|
+
const tb = 1 / (top - bottom)
|
|
795
|
+
const nf = 1 / (near - far)
|
|
796
|
+
const lh = glm.LEFT_HANDED
|
|
797
|
+
out[0] = near * 2 * rl
|
|
798
|
+
out[5] = near * 2 * tb
|
|
799
|
+
out[8] = (right + left) * rl; out[9] = (top + bottom) * tb; out[10] = lh ? -(far + near) * nf : (far + near) * nf; out[11] = lh ? 1 : -1
|
|
800
|
+
out[1] = out[2] = out[3] = out[4] = out[6] = out[7] = out[12] = out[13] = out[15] = 0
|
|
801
|
+
out[14] = far * near * 2 * nf
|
|
802
|
+
return out
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* Generates a perspective projection matrix with the given bounds.
|
|
807
|
+
* The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
|
|
808
|
+
* which matches WebGL/OpenGL's clip volume.
|
|
809
|
+
*
|
|
810
|
+
* @param {Number} fovy vertical field of view in radians
|
|
811
|
+
* @param {Number} aspect aspect ratio, typically viewport width / height
|
|
812
|
+
* @param {Number} near near bound of the frustum
|
|
813
|
+
* @param {Number | null} far far bound of the frustum, can be null or Infinity
|
|
814
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
815
|
+
* @returns {Mat4} out
|
|
816
|
+
*/
|
|
817
|
+
static perspectiveNO(fovy: number, aspect: number, near: number, far: number | null, out = new Mat4()) {
|
|
818
|
+
const f = 1.0 / Math.tan(fovy / 2)
|
|
819
|
+
const lh = glm.LEFT_HANDED
|
|
820
|
+
out[0] = f / aspect
|
|
821
|
+
out[1] = out[2] = out[3] = out[4] = out[6] = out[7] = out[8] = out[9] = out[12] = out[13] = out[15] = 0
|
|
822
|
+
out[5] = f
|
|
823
|
+
out[11] = lh ? 1 : -1
|
|
824
|
+
if (far != null && far !== Infinity) {
|
|
825
|
+
const nf = 1 / (near - far)
|
|
826
|
+
out[10] = lh ? -(far + near) * nf : (far + near) * nf
|
|
827
|
+
out[14] = 2 * far * near * nf
|
|
828
|
+
} else {
|
|
829
|
+
out[10] = lh ? 1 : -1
|
|
830
|
+
out[14] = -2 * near
|
|
831
|
+
}
|
|
832
|
+
return out
|
|
833
|
+
}
|
|
834
|
+
static perspective = this.perspectiveNO
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Generates a perspective projection matrix with the given bounds.
|
|
838
|
+
* The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
|
|
839
|
+
* which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
|
|
840
|
+
*
|
|
841
|
+
* @param {Number} fovy vertical field of view in radians
|
|
842
|
+
* @param {Number} aspect aspect ratio, typically viewport width / height
|
|
843
|
+
* @param {Number} near near bound of the frustum
|
|
844
|
+
* @param {Number | null} far far bound of the frustum, can be null or Infinity
|
|
845
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
846
|
+
* @returns {Mat4} out
|
|
847
|
+
*/
|
|
848
|
+
static perspectiveZO(fovy: number, aspect: number, near: number, far: number | null, out = new Mat4()) {
|
|
849
|
+
const f = 1.0 / Math.tan(fovy / 2)
|
|
850
|
+
const lh = glm.LEFT_HANDED
|
|
851
|
+
out[0] = f / aspect; out[1] = 0; out[2] = 0; out[3] = 0
|
|
852
|
+
out[4] = 0; out[5] = f; out[6] = 0; out[7] = 0
|
|
853
|
+
out[8] = 0; out[9] = 0; out[11] = lh ? 1 : -1
|
|
854
|
+
out[12] = 0; out[13] = 0; out[15] = 0
|
|
855
|
+
if (far != null && far !== Infinity) {
|
|
856
|
+
const nf = 1 / (near - far)
|
|
857
|
+
out[10] = lh ? -far * nf : far * nf
|
|
858
|
+
out[14] = far * near * nf
|
|
859
|
+
} else {
|
|
860
|
+
out[10] = lh ? 1 : -1
|
|
861
|
+
out[14] = -near
|
|
862
|
+
}
|
|
863
|
+
return out
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Generates a perspective projection matrix with the given field of view
|
|
868
|
+
*
|
|
869
|
+
* @param {Object} fov object containing upDegrees, downDegrees, leftDegrees, rightDegrees
|
|
870
|
+
* @param {Number} near near bound of the frustum
|
|
871
|
+
* @param {Number} far far bound of the frustum
|
|
872
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
873
|
+
* @returns {Mat4} out
|
|
874
|
+
*/
|
|
875
|
+
static perspectiveFromFieldOfView(fov: { upDegrees: number, downDegrees: number, leftDegrees: number, rightDegrees: number }, near: number, far: number, out = new Mat4()) {
|
|
876
|
+
const upTan = Math.tan((fov.upDegrees * Math.PI) / 180.0)
|
|
877
|
+
const downTan = Math.tan((fov.downDegrees * Math.PI) / 180.0)
|
|
878
|
+
const leftTan = Math.tan((fov.leftDegrees * Math.PI) / 180.0)
|
|
879
|
+
const rightTan = Math.tan((fov.rightDegrees * Math.PI) / 180.0)
|
|
880
|
+
const xScale = 2.0 / (leftTan + rightTan)
|
|
881
|
+
const yScale = 2.0 / (upTan + downTan)
|
|
882
|
+
|
|
883
|
+
out[0] = xScale; out[1] = 0; out[2] = 0; out[3] = 0
|
|
884
|
+
out[4] = 0; out[5] = yScale; out[6] = 0; out[7] = 0
|
|
885
|
+
const lh = glm.LEFT_HANDED
|
|
886
|
+
out[8] = -((leftTan - rightTan) * xScale * 0.5)
|
|
887
|
+
out[9] = (upTan - downTan) * yScale * 0.5
|
|
888
|
+
out[10] = lh ? -far / (near - far) : far / (near - far)
|
|
889
|
+
out[11] = lh ? 1.0 : -1.0
|
|
890
|
+
out[12] = 0; out[13] = 0
|
|
891
|
+
out[14] = (far * near) / (near - far)
|
|
892
|
+
out[15] = 0
|
|
893
|
+
return out
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Generates an orthogonal projection matrix with the given bounds.
|
|
898
|
+
* The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
|
|
899
|
+
* which matches WebGL/OpenGL's clip volume.
|
|
900
|
+
*
|
|
901
|
+
* @param {Number} left left bound of the frustum
|
|
902
|
+
* @param {Number} right right bound of the frustum
|
|
903
|
+
* @param {Number} bottom bottom bound of the frustum
|
|
904
|
+
* @param {Number} top top bound of the frustum
|
|
905
|
+
* @param {Number} near near bound of the frustum
|
|
906
|
+
* @param {Number} far far bound of the frustum
|
|
907
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
908
|
+
* @returns {Mat4} out
|
|
909
|
+
*/
|
|
910
|
+
static orthoNO(left: number, right: number, bottom: number, top: number, near: number, far: number, out = new Mat4()) {
|
|
911
|
+
const lr = 1 / (left - right)
|
|
912
|
+
const bt = 1 / (bottom - top)
|
|
913
|
+
const nf = 1 / (near - far)
|
|
914
|
+
const s = glm.LEFT_HANDED ? -1 : 1
|
|
915
|
+
out[0] = -2 * lr; out[1] = 0; out[2] = 0; out[3] = 0
|
|
916
|
+
out[4] = 0; out[5] = -2 * bt; out[6] = 0; out[7] = 0
|
|
917
|
+
out[8] = 0; out[9] = 0; out[10] = s * 2 * nf; out[11] = 0
|
|
918
|
+
out[12] = (left + right) * lr; out[13] = (top + bottom) * bt; out[14] = (far + near) * nf; out[15] = 1
|
|
919
|
+
return out
|
|
920
|
+
}
|
|
921
|
+
static ortho = this.orthoNO
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Generates an orthogonal projection matrix with the given bounds.
|
|
925
|
+
* The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
|
|
926
|
+
* which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
|
|
927
|
+
*
|
|
928
|
+
* @param {Number} left left bound of the frustum
|
|
929
|
+
* @param {Number} right right bound of the frustum
|
|
930
|
+
* @param {Number} bottom bottom bound of the frustum
|
|
931
|
+
* @param {Number} top top bound of the frustum
|
|
932
|
+
* @param {Number} near near bound of the frustum
|
|
933
|
+
* @param {Number} far far bound of the frustum
|
|
934
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
935
|
+
* @returns {Mat4} out
|
|
936
|
+
*/
|
|
937
|
+
static orthoZO(left: number, right: number, bottom: number, top: number, near: number, far: number, out = new Mat4()) {
|
|
938
|
+
const lr = 1 / (left - right)
|
|
939
|
+
const bt = 1 / (bottom - top)
|
|
940
|
+
const nf = 1 / (near - far)
|
|
941
|
+
const s = glm.LEFT_HANDED ? -1 : 1
|
|
942
|
+
out[0] = -2 * lr; out[1] = 0; out[2] = 0; out[3] = 0
|
|
943
|
+
out[4] = 0; out[5] = -2 * bt; out[6] = 0; out[7] = 0
|
|
944
|
+
out[8] = 0; out[9] = 0; out[10] = s * nf; out[11] = 0
|
|
945
|
+
out[12] = (left + right) * lr; out[13] = (top + bottom) * bt; out[14] = near * nf; out[15] = 1
|
|
946
|
+
return out
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* Generates a look-at matrix with the given eye position, focal point, and up axis.
|
|
951
|
+
* If you want a matrix that actually makes an object look at another object, use targetTo instead.
|
|
952
|
+
*
|
|
953
|
+
* @param {Vec3} eye position of the viewer
|
|
954
|
+
* @param {Vec3} center point the viewer is looking at
|
|
955
|
+
* @param {Vec3} up vector pointing up
|
|
956
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
957
|
+
* @returns {Mat4} out
|
|
958
|
+
*/
|
|
959
|
+
static lookAt(eye: Vec3, center: Vec3, up: Vec3, out = new Mat4()) {
|
|
960
|
+
let x0, x1, x2, y0, y1, y2, z0, z1, z2, len
|
|
961
|
+
|
|
962
|
+
const eyex = eye[0], eyey = eye[1], eyez = eye[2]
|
|
963
|
+
const upx = up[0], upy = up[1], upz = up[2]
|
|
964
|
+
const centerx = center[0], centery = center[1], centerz = center[2]
|
|
965
|
+
|
|
966
|
+
if (eye.equals(center)) {
|
|
967
|
+
out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0
|
|
968
|
+
out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0
|
|
969
|
+
out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0
|
|
970
|
+
out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1
|
|
971
|
+
return out
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
if (glm.LEFT_HANDED) {
|
|
975
|
+
z0 = centerx - eyex; z1 = centery - eyey; z2 = centerz - eyez
|
|
976
|
+
} else {
|
|
977
|
+
z0 = eyex - centerx; z1 = eyey - centery; z2 = eyez - centerz
|
|
978
|
+
}
|
|
979
|
+
len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2)
|
|
980
|
+
z0 *= len; z1 *= len; z2 *= len
|
|
981
|
+
|
|
982
|
+
x0 = upy * z2 - upz * z1
|
|
983
|
+
x1 = upz * z0 - upx * z2
|
|
984
|
+
x2 = upx * z1 - upy * z0
|
|
985
|
+
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2)
|
|
986
|
+
if (!len) { x0 = 0; x1 = 0; x2 = 0 }
|
|
987
|
+
else { len = 1 / len; x0 *= len; x1 *= len; x2 *= len }
|
|
988
|
+
|
|
989
|
+
y0 = z1 * x2 - z2 * x1
|
|
990
|
+
y1 = z2 * x0 - z0 * x2
|
|
991
|
+
y2 = z0 * x1 - z1 * x0
|
|
992
|
+
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2)
|
|
993
|
+
if (!len) { y0 = 0; y1 = 0; y2 = 0 }
|
|
994
|
+
else { len = 1 / len; y0 *= len; y1 *= len; y2 *= len }
|
|
995
|
+
|
|
996
|
+
out[0] = x0; out[1] = y0; out[2] = z0; out[3] = 0
|
|
997
|
+
out[4] = x1; out[5] = y1; out[6] = z1; out[7] = 0
|
|
998
|
+
out[8] = x2; out[9] = y2; out[10] = z2; out[11] = 0
|
|
999
|
+
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez)
|
|
1000
|
+
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez)
|
|
1001
|
+
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez)
|
|
1002
|
+
out[15] = 1
|
|
1003
|
+
return out
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Generates a matrix that makes something look at a given point from a given eye position
|
|
1008
|
+
*
|
|
1009
|
+
* @param {Vec3} eye position of the viewer
|
|
1010
|
+
* @param {Vec3} target point the viewer is looking at
|
|
1011
|
+
* @param {Vec3} up vector pointing up
|
|
1012
|
+
* @param {Mat4} out the receiving matrix, defaults to new Mat4()
|
|
1013
|
+
* @returns {Mat4} out
|
|
1014
|
+
*/
|
|
1015
|
+
static targetTo(eye: Vec3, target: Vec3, up: Vec3, out = new Mat4()) {
|
|
1016
|
+
const eyex = eye[0], eyey = eye[1], eyez = eye[2]
|
|
1017
|
+
const upx = up[0], upy = up[1], upz = up[2]
|
|
1018
|
+
|
|
1019
|
+
let z0, z1, z2
|
|
1020
|
+
if (glm.LEFT_HANDED) {
|
|
1021
|
+
z0 = target[0] - eyex; z1 = target[1] - eyey; z2 = target[2] - eyez
|
|
1022
|
+
} else {
|
|
1023
|
+
z0 = eyex - target[0]; z1 = eyey - target[1]; z2 = eyez - target[2]
|
|
1024
|
+
}
|
|
1025
|
+
let len = z0 * z0 + z1 * z1 + z2 * z2
|
|
1026
|
+
if (len > 0) {
|
|
1027
|
+
len = 1 / Math.sqrt(len)
|
|
1028
|
+
z0 *= len; z1 *= len; z2 *= len
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
let x0 = upy * z2 - upz * z1
|
|
1032
|
+
let x1 = upz * z0 - upx * z2
|
|
1033
|
+
let x2 = upx * z1 - upy * z0
|
|
1034
|
+
len = x0 * x0 + x1 * x1 + x2 * x2
|
|
1035
|
+
if (len > 0) {
|
|
1036
|
+
len = 1 / Math.sqrt(len)
|
|
1037
|
+
x0 *= len; x1 *= len; x2 *= len
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
out[0] = x0; out[1] = x1; out[2] = x2; out[3] = 0
|
|
1041
|
+
out[4] = z1 * x2 - z2 * x1; out[5] = z2 * x0 - z0 * x2; out[6] = z0 * x1 - z1 * x0; out[7] = 0
|
|
1042
|
+
out[8] = z0; out[9] = z1; out[10] = z2; out[11] = 0
|
|
1043
|
+
out[12] = eyex; out[13] = eyey; out[14] = eyez; out[15] = 1
|
|
1044
|
+
return out
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* Generates a perspective projection matrix with the far plane at infinity.
|
|
1049
|
+
* Uses clip space z range of [-1, 1].
|
|
1050
|
+
*
|
|
1051
|
+
* @param {Number} fovy Vertical field of view in radians
|
|
1052
|
+
* @param {Number} aspect Aspect ratio (width / height)
|
|
1053
|
+
* @param {Number} near Near bound of the frustum
|
|
1054
|
+
* @param {Mat4} out the receiving matrix, defaults to a new Mat4
|
|
1055
|
+
* @returns {Mat4} out
|
|
1056
|
+
*/
|
|
1057
|
+
static infinitePerspective(fovy: number, aspect: number, near: number, out = new Mat4()) {
|
|
1058
|
+
const f = 1.0 / Math.tan(fovy / 2)
|
|
1059
|
+
const lh = glm.LEFT_HANDED
|
|
1060
|
+
out[0] = f / aspect
|
|
1061
|
+
out[1] = out[2] = out[3] = out[4] = out[6] = out[7] = out[8] = out[9] = out[12] = out[13] = out[15] = 0
|
|
1062
|
+
out[5] = f
|
|
1063
|
+
out[10] = lh ? 1 : -1
|
|
1064
|
+
out[11] = lh ? 1 : -1
|
|
1065
|
+
out[14] = -2 * near
|
|
1066
|
+
return out
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* Projects a 3D point to window coordinates using the given model and
|
|
1071
|
+
* projection matrices and viewport.
|
|
1072
|
+
*
|
|
1073
|
+
* @param {Vec3} obj the 3D point to project
|
|
1074
|
+
* @param {Mat4} model the model matrix
|
|
1075
|
+
* @param {Mat4} proj the projection matrix
|
|
1076
|
+
* @param {Vec4} viewport the viewport as [x, y, width, height]
|
|
1077
|
+
* @param {Vec3} out the receiving vector, defaults to a new Vec3
|
|
1078
|
+
* @returns {Vec3} out
|
|
1079
|
+
*/
|
|
1080
|
+
static project(obj: Vec3, model: Mat4, proj: Mat4, viewport: Vec4, out = new Vec3()): Vec3 {
|
|
1081
|
+
const x = obj[0], y = obj[1], z = obj[2]
|
|
1082
|
+
const tx = model[0]*x + model[4]*y + model[8]*z + model[12]
|
|
1083
|
+
const ty = model[1]*x + model[5]*y + model[9]*z + model[13]
|
|
1084
|
+
const tz = model[2]*x + model[6]*y + model[10]*z + model[14]
|
|
1085
|
+
const tw = model[3]*x + model[7]*y + model[11]*z + model[15]
|
|
1086
|
+
|
|
1087
|
+
let px = proj[0]*tx + proj[4]*ty + proj[8]*tz + proj[12]*tw
|
|
1088
|
+
let py = proj[1]*tx + proj[5]*ty + proj[9]*tz + proj[13]*tw
|
|
1089
|
+
let pz = proj[2]*tx + proj[6]*ty + proj[10]*tz + proj[14]*tw
|
|
1090
|
+
let pw = proj[3]*tx + proj[7]*ty + proj[11]*tz + proj[15]*tw
|
|
1091
|
+
|
|
1092
|
+
pw = pw || 1.0
|
|
1093
|
+
px /= pw; py /= pw; pz /= pw
|
|
1094
|
+
|
|
1095
|
+
out[0] = viewport[0] + viewport[2] * (px * 0.5 + 0.5)
|
|
1096
|
+
out[1] = viewport[1] + viewport[3] * (py * 0.5 + 0.5)
|
|
1097
|
+
out[2] = pz * 0.5 + 0.5
|
|
1098
|
+
return out
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Unprojects a 2D window coordinate back to 3D world coordinates using the
|
|
1103
|
+
* given model and projection matrices and viewport.
|
|
1104
|
+
*
|
|
1105
|
+
* @param {Vec3} win the window coordinate [x, y, z] where z is depth (0 to 1)
|
|
1106
|
+
* @param {Mat4} model the model matrix
|
|
1107
|
+
* @param {Mat4} proj the projection matrix
|
|
1108
|
+
* @param {Vec4} viewport the viewport as [x, y, width, height]
|
|
1109
|
+
* @param {Vec3} out the receiving vector, defaults to a new Vec3
|
|
1110
|
+
* @returns {Vec3 | null} out, or null if the combined matrix is not invertible
|
|
1111
|
+
*/
|
|
1112
|
+
static unProject(win: Vec3, model: Mat4, proj: Mat4, viewport: Vec4, out = new Vec3()): Vec3 | null {
|
|
1113
|
+
const a00 = model[0], a01 = model[1], a02 = model[2], a03 = model[3]
|
|
1114
|
+
const a10 = model[4], a11 = model[5], a12 = model[6], a13 = model[7]
|
|
1115
|
+
const a20 = model[8], a21 = model[9], a22 = model[10], a23 = model[11]
|
|
1116
|
+
const a30 = model[12], a31 = model[13], a32 = model[14], a33 = model[15]
|
|
1117
|
+
|
|
1118
|
+
const pm = new Mat4()
|
|
1119
|
+
let b0 = proj[0], b1 = proj[1], b2 = proj[2], b3 = proj[3]
|
|
1120
|
+
pm[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
|
1121
|
+
pm[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
|
1122
|
+
pm[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
|
1123
|
+
pm[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
|
1124
|
+
|
|
1125
|
+
b0 = proj[4]; b1 = proj[5]; b2 = proj[6]; b3 = proj[7]
|
|
1126
|
+
pm[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
|
1127
|
+
pm[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
|
1128
|
+
pm[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
|
1129
|
+
pm[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
|
1130
|
+
|
|
1131
|
+
b0 = proj[8]; b1 = proj[9]; b2 = proj[10]; b3 = proj[11]
|
|
1132
|
+
pm[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
|
1133
|
+
pm[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
|
1134
|
+
pm[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
|
1135
|
+
pm[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
|
1136
|
+
|
|
1137
|
+
b0 = proj[12]; b1 = proj[13]; b2 = proj[14]; b3 = proj[15]
|
|
1138
|
+
pm[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30
|
|
1139
|
+
pm[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31
|
|
1140
|
+
pm[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32
|
|
1141
|
+
pm[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33
|
|
1142
|
+
|
|
1143
|
+
const inv = pm.invert()
|
|
1144
|
+
if (!inv) return null
|
|
1145
|
+
|
|
1146
|
+
const nx = (win[0] - viewport[0]) / viewport[2] * 2 - 1
|
|
1147
|
+
const ny = (win[1] - viewport[1]) / viewport[3] * 2 - 1
|
|
1148
|
+
const nz = win[2] * 2 - 1
|
|
1149
|
+
|
|
1150
|
+
let w = inv[3]*nx + inv[7]*ny + inv[11]*nz + inv[15]
|
|
1151
|
+
w = w || 1.0
|
|
1152
|
+
out[0] = (inv[0]*nx + inv[4]*ny + inv[8]*nz + inv[12]) / w
|
|
1153
|
+
out[1] = (inv[1]*nx + inv[5]*ny + inv[9]*nz + inv[13]) / w
|
|
1154
|
+
out[2] = (inv[2]*nx + inv[6]*ny + inv[10]*nz + inv[14]) / w
|
|
1155
|
+
return out
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* Returns Frobenius norm of a mat4
|
|
1160
|
+
*
|
|
1161
|
+
* @returns {Number} Frobenius norm
|
|
1162
|
+
*/
|
|
1163
|
+
frob() {
|
|
1164
|
+
return Math.sqrt(
|
|
1165
|
+
this[0] * this[0] + this[1] * this[1] + this[2] * this[2] + this[3] * this[3] +
|
|
1166
|
+
this[4] * this[4] + this[5] * this[5] + this[6] * this[6] + this[7] * this[7] +
|
|
1167
|
+
this[8] * this[8] + this[9] * this[9] + this[10] * this[10] + this[11] * this[11] +
|
|
1168
|
+
this[12] * this[12] + this[13] * this[13] + this[14] * this[14] + this[15] * this[15]
|
|
1169
|
+
)
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
/**
|
|
1173
|
+
* Adds two mat4's
|
|
1174
|
+
*
|
|
1175
|
+
* @param {Mat4} b the second operand
|
|
1176
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
1177
|
+
* @returns {Mat4} out
|
|
1178
|
+
*/
|
|
1179
|
+
plus(b: Mat4, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
1180
|
+
out[0] = this[0] + b[0]; out[1] = this[1] + b[1]; out[2] = this[2] + b[2]; out[3] = this[3] + b[3]
|
|
1181
|
+
out[4] = this[4] + b[4]; out[5] = this[5] + b[5]; out[6] = this[6] + b[6]; out[7] = this[7] + b[7]
|
|
1182
|
+
out[8] = this[8] + b[8]; out[9] = this[9] + b[9]; out[10] = this[10] + b[10]; out[11] = this[11] + b[11]
|
|
1183
|
+
out[12] = this[12] + b[12]; out[13] = this[13] + b[13]; out[14] = this[14] + b[14]; out[15] = this[15] + b[15]
|
|
1184
|
+
return out
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Subtracts matrix b from a mat4
|
|
1189
|
+
*
|
|
1190
|
+
* @param {Mat4} b the second operand
|
|
1191
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
1192
|
+
* @returns {Mat4} out
|
|
1193
|
+
*/
|
|
1194
|
+
minus(b: Mat4, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
1195
|
+
out[0] = this[0] - b[0]; out[1] = this[1] - b[1]; out[2] = this[2] - b[2]; out[3] = this[3] - b[3]
|
|
1196
|
+
out[4] = this[4] - b[4]; out[5] = this[5] - b[5]; out[6] = this[6] - b[6]; out[7] = this[7] - b[7]
|
|
1197
|
+
out[8] = this[8] - b[8]; out[9] = this[9] - b[9]; out[10] = this[10] - b[10]; out[11] = this[11] - b[11]
|
|
1198
|
+
out[12] = this[12] - b[12]; out[13] = this[13] - b[13]; out[14] = this[14] - b[14]; out[15] = this[15] - b[15]
|
|
1199
|
+
return out
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Multiplies each element of a mat4 by a scalar number
|
|
1204
|
+
*
|
|
1205
|
+
* @param {Number} b amount to scale the matrix's elements by
|
|
1206
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
1207
|
+
* @returns {Mat4} out
|
|
1208
|
+
*/
|
|
1209
|
+
scaleScalar(b: number, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
1210
|
+
out[0] = this[0] * b; out[1] = this[1] * b; out[2] = this[2] * b; out[3] = this[3] * b
|
|
1211
|
+
out[4] = this[4] * b; out[5] = this[5] * b; out[6] = this[6] * b; out[7] = this[7] * b
|
|
1212
|
+
out[8] = this[8] * b; out[9] = this[9] * b; out[10] = this[10] * b; out[11] = this[11] * b
|
|
1213
|
+
out[12] = this[12] * b; out[13] = this[13] * b; out[14] = this[14] * b; out[15] = this[15] * b
|
|
1214
|
+
return out
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Adds two mat4's after multiplying each element of the second operand by a scalar value
|
|
1219
|
+
*
|
|
1220
|
+
* @param {Mat4} b the second operand
|
|
1221
|
+
* @param {Number} scale the amount to scale b's elements by before adding
|
|
1222
|
+
* @param {Mat4} out the receiving matrix, defaults to this
|
|
1223
|
+
* @returns {Mat4} out
|
|
1224
|
+
*/
|
|
1225
|
+
multiplyScalarAndAdd(b: Mat4, scale: number, out = glm.ALWAYS_COPY ? new Mat4() : this) {
|
|
1226
|
+
out[0] = this[0] + b[0] * scale; out[1] = this[1] + b[1] * scale
|
|
1227
|
+
out[2] = this[2] + b[2] * scale; out[3] = this[3] + b[3] * scale
|
|
1228
|
+
out[4] = this[4] + b[4] * scale; out[5] = this[5] + b[5] * scale
|
|
1229
|
+
out[6] = this[6] + b[6] * scale; out[7] = this[7] + b[7] * scale
|
|
1230
|
+
out[8] = this[8] + b[8] * scale; out[9] = this[9] + b[9] * scale
|
|
1231
|
+
out[10] = this[10] + b[10] * scale; out[11] = this[11] + b[11] * scale
|
|
1232
|
+
out[12] = this[12] + b[12] * scale; out[13] = this[13] + b[13] * scale
|
|
1233
|
+
out[14] = this[14] + b[14] * scale; out[15] = this[15] + b[15] * scale
|
|
1234
|
+
return out
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Returns a string representation of a mat4
|
|
1239
|
+
*
|
|
1240
|
+
* @returns {String} string representation of the matrix
|
|
1241
|
+
*/
|
|
1242
|
+
toString() {
|
|
1243
|
+
return `mat4(${this[0]}, ${this[1]}, ${this[2]}, ${this[3]},\t${this[4]}, ${this[5]}, ${this[6]}, ${this[7]},\t${this[8]}, ${this[9]}, ${this[10]}, ${this[11]},\t${this[12]}, ${this[13]}, ${this[14]}, ${this[15]})`
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* Returns whether a mat4 and another have exactly the same elements in the same position
|
|
1248
|
+
*
|
|
1249
|
+
* @param {Mat4} b the matrix to compare against
|
|
1250
|
+
* @returns {Boolean} true if the matrices are equal, false otherwise
|
|
1251
|
+
*/
|
|
1252
|
+
exactEquals(b: Mat4) {
|
|
1253
|
+
return (
|
|
1254
|
+
this[0] === b[0] && this[1] === b[1] && this[2] === b[2] && this[3] === b[3] &&
|
|
1255
|
+
this[4] === b[4] && this[5] === b[5] && this[6] === b[6] && this[7] === b[7] &&
|
|
1256
|
+
this[8] === b[8] && this[9] === b[9] && this[10] === b[10] && this[11] === b[11] &&
|
|
1257
|
+
this[12] === b[12] && this[13] === b[13] && this[14] === b[14] && this[15] === b[15]
|
|
1258
|
+
)
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* Returns whether a mat4 and another are approximately equal
|
|
1263
|
+
*
|
|
1264
|
+
* @param {Mat4} b the matrix to compare against
|
|
1265
|
+
* @returns {Boolean} true if the matrices are approximately equal, false otherwise
|
|
1266
|
+
*/
|
|
1267
|
+
equals(b: Mat4) {
|
|
1268
|
+
return (
|
|
1269
|
+
equals(this[0], b[0]) && equals(this[1], b[1]) && equals(this[2], b[2]) && equals(this[3], b[3]) &&
|
|
1270
|
+
equals(this[4], b[4]) && equals(this[5], b[5]) && equals(this[6], b[6]) && equals(this[7], b[7]) &&
|
|
1271
|
+
equals(this[8], b[8]) && equals(this[9], b[9]) && equals(this[10], b[10]) && equals(this[11], b[11]) &&
|
|
1272
|
+
equals(this[12], b[12]) && equals(this[13], b[13]) && equals(this[14], b[14]) && equals(this[15], b[15])
|
|
1273
|
+
)
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
export interface Mat4 {
|
|
1278
|
+
add: (b: Mat4, out?: Mat4) => Mat4
|
|
1279
|
+
sub: (b: Mat4, out?: Mat4) => Mat4
|
|
1280
|
+
subtract: (b: Mat4, out?: Mat4) => Mat4
|
|
1281
|
+
mul(b: Vec2): Vec2
|
|
1282
|
+
mul(b: Vec3): Vec3
|
|
1283
|
+
mul(b: Vec4): Vec4
|
|
1284
|
+
mul(b: Mat4, out?: Mat4): Mat4
|
|
1285
|
+
mult(b: Vec2): Vec2
|
|
1286
|
+
mult(b: Vec3): Vec3
|
|
1287
|
+
mult(b: Vec4): Vec4
|
|
1288
|
+
mult(b: Mat4, out?: Mat4): Mat4
|
|
1289
|
+
times(b: Vec2): Vec2
|
|
1290
|
+
times(b: Vec3): Vec3
|
|
1291
|
+
times(b: Vec4): Vec4
|
|
1292
|
+
times(b: Mat4, out?: Mat4): Mat4
|
|
1293
|
+
str: () => string
|
|
1294
|
+
multiplyScalar: (b: number, out?: Mat4) => Mat4
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
// @aliases
|
|
1298
|
+
Mat4.prototype.add = Mat4.prototype.plus
|
|
1299
|
+
Mat4.prototype.sub = Mat4.prototype.minus
|
|
1300
|
+
Mat4.prototype.subtract = Mat4.prototype.minus
|
|
1301
|
+
Mat4.prototype.mul = Mat4.prototype.multiply
|
|
1302
|
+
Mat4.prototype.mult = Mat4.prototype.multiply
|
|
1303
|
+
Mat4.prototype.times = Mat4.prototype.multiply
|
|
1304
|
+
Mat4.prototype.str = Mat4.prototype.toString
|
|
1305
|
+
Mat4.prototype.multiplyScalar = Mat4.prototype.scaleScalar
|
|
1306
|
+
|
|
1307
|
+
export const mat4 = Object.assign(
|
|
1308
|
+
(...args: (number | Float32Array)[]): Mat4 => {
|
|
1309
|
+
const out = new Mat4()
|
|
1310
|
+
let i = 0
|
|
1311
|
+
for (const a of args) {
|
|
1312
|
+
if (typeof a === 'number') out[i++] = a
|
|
1313
|
+
else for (const v of a) out[i++] = v
|
|
1314
|
+
}
|
|
1315
|
+
return out
|
|
1316
|
+
},
|
|
1317
|
+
Mat4
|
|
1318
|
+
)
|
|
1319
|
+
export const mat4x4 = mat4
|