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/benchmark.js ADDED
@@ -0,0 +1,747 @@
1
+ const Benchmark = require('benchmark')
2
+
3
+ // Benchmark.options.maxTime = 0.1;
4
+ // Benchmark.options.minSamples = 1;
5
+
6
+ const glm = require('gl-matrix/gl-matrix-min.js');
7
+ const glmaths = require('./dist/cjs/glmaths.min.js');
8
+
9
+ // we expect user fully utilizing the library
10
+ glmaths.ALWAYS_COPY = false
11
+
12
+ // apparantely, this makes v8 jit load up glmaths.Vec3 in advance
13
+ // initialization is def slower than gl-matrix, if it affects the benchmark that much
14
+ class Vec2Extended extends glmaths.Vec2 { constructor() { super() } }
15
+ class Vec3Extended extends glmaths.Vec3 { constructor() { super() } }
16
+ class Vec4Extended extends glmaths.Vec4 { constructor() { super() } }
17
+
18
+ const allResults = []
19
+
20
+ function formatOps(hz) {
21
+ if (hz >= 1e9) return `${(hz / 1e9).toFixed(1)}B`
22
+ if (hz >= 1e6) return `${(hz / 1e6).toFixed(1)}M`
23
+ if (hz >= 1e3) return `${(hz / 1e3).toFixed(1)}K`
24
+ return `${hz.toFixed(0)}`
25
+ }
26
+
27
+ function runSuite(suite) {
28
+ return new Promise(resolve => {
29
+ suite
30
+ .on('cycle', e => console.log(' ' + String(e.target)))
31
+ .on('complete', function () {
32
+ const fastest = this.filter('fastest').map('name');
33
+ console.log(' → Fastest: ' + fastest.join(', '));
34
+
35
+ const benchmarks = Array.from(this)
36
+ const glmEntry = benchmarks.find(b => b.name.startsWith('gl-matrix'))
37
+ const glmathsEntry = benchmarks.find(b => b.name.startsWith('glm'))
38
+
39
+ if (glmEntry || glmathsEntry) {
40
+ const row = { name: this.name }
41
+ if (glmEntry) {
42
+ row.glmOps = glmEntry.hz
43
+ row.glmRme = glmEntry.stats.rme
44
+ }
45
+ if (glmathsEntry) {
46
+ row.glmathsOps = glmathsEntry.hz
47
+ row.glmathsRme = glmathsEntry.stats.rme
48
+ }
49
+ if (glmEntry && glmathsEntry) {
50
+ const pct = ((glmathsEntry.hz - glmEntry.hz) / glmEntry.hz) * 100
51
+ row.diff = pct
52
+ }
53
+ allResults.push(row)
54
+ }
55
+
56
+ if (!glmEntry && benchmarks.length > 1) {
57
+
58
+ } else if (!glmEntry && !glmathsEntry) {
59
+ for (const b of benchmarks) {
60
+ allResults.push({
61
+ name: `${this.name}: ${b.name}`,
62
+ glmathsOps: b.hz,
63
+ glmathsRme: b.stats.rme
64
+ })
65
+ }
66
+ }
67
+
68
+ resolve();
69
+ })
70
+ .run({ async: true });
71
+ });
72
+ }
73
+
74
+ function printMarkdownTable() {
75
+ console.log('\n')
76
+ console.log('## Benchmark Results\n')
77
+ console.log('| Operation | gl-matrix | glm | Diff |')
78
+ console.log('|:---|---:|---:|---:|')
79
+
80
+ for (const r of allResults) {
81
+ const glmCol = r.glmOps
82
+ ? `${formatOps(r.glmOps)} ops/s ±${r.glmRme.toFixed(1)}%`
83
+ : '—'
84
+ const glmathsCol = r.glmathsOps
85
+ ? `${formatOps(r.glmathsOps)} ops/s ±${r.glmathsRme.toFixed(1)}%`
86
+ : '—'
87
+ let diffCol = '—'
88
+ if (r.diff !== undefined) {
89
+ const sign = r.diff >= 0 ? '+' : ''
90
+ const bold = Math.abs(r.diff) > 10
91
+ const text = `${sign}${r.diff.toFixed(0)}%`
92
+ diffCol = bold ? `**${text}**` : text
93
+ }
94
+ console.log(`| ${r.name} | ${glmCol} | ${glmathsCol} | ${diffCol} |`)
95
+ }
96
+
97
+ console.log('')
98
+ }
99
+
100
+ // ─────────────────────────────────────────────
101
+ // Vec3 benchmarks
102
+ // ─────────────────────────────────────────────
103
+ function vec3Benchmarks() {
104
+
105
+ const s1 = new Benchmark.Suite('Vec3 creation');
106
+ s1.add('gl-matrix vec3.fromValues(1, 2, 3)', () => {
107
+ const v = glm.vec3.fromValues(1, 2, 3);
108
+ });
109
+ s1.add('gl-matrix vec3.create() vec3.set(1, 2, 3)', () => {
110
+ const v = glm.vec3.create()
111
+ glm.vec3.set(v, 1, 2, 3)
112
+ });
113
+ s1.add('glmaths vec3(1,2,3)', () => {
114
+ const v = glmaths.vec3(1, 2, 3);
115
+ });
116
+ // s1.add('glmaths new Vec3(1,2,3)', () => {
117
+ // const v = new glmaths.Vec3(1, 2, 3);
118
+ // });
119
+
120
+
121
+ const a1 = glm.vec3.fromValues(1, 2, 3);
122
+ const b1 = glm.vec3.fromValues(4, 5, 6);
123
+ const out1 = glm.vec3.create();
124
+ const a2 = new glmaths.Vec3(1, 2, 3);
125
+ const b2 = new glmaths.Vec3(4, 5, 6);
126
+ const out2 = new glmaths.Vec3();
127
+
128
+ const s2 = new Benchmark.Suite('Vec3 add');
129
+ s2.add('gl-matrix vec3.add(out, a, b)', () => {
130
+ glm.vec3.add(out1, a1, b1);
131
+ });
132
+ s2.add('gl-matrix vec3.add(a, a, b)', () => {
133
+ glm.vec3.add(a1, a1, b1);
134
+ });
135
+ s2.add('glmaths a.add(b, out)', () => {
136
+ a2.add(b2, out2);
137
+ });
138
+ s2.add('glmaths a.add(b) [in-place]', () => {
139
+ a2.add(b2);
140
+ });
141
+
142
+
143
+ const s3 = new Benchmark.Suite('Vec3 dot');
144
+ s3.add('gl-matrix vec3.dot(a, b)', () => {
145
+ glm.vec3.dot(out1, a1, b1);
146
+ });
147
+ s3.add('glmaths vec3.dot(b)', () => {
148
+ glmaths.vec3.dot(out2, a2, b2);
149
+ });
150
+
151
+
152
+ const crossOut1 = glm.vec3.create();
153
+ const crossOut2 = new glmaths.Vec3();
154
+ const s4 = new Benchmark.Suite('Vec3 cross');
155
+ s4.add('gl-matrix vec3.cross(out, a, b)', () => {
156
+ glm.vec3.cross(crossOut1, a1, b1);
157
+ });
158
+ s4.add('glmaths Vec3.cross(a, b, out)', () => {
159
+ glmaths.Vec3.cross(a2, b2, crossOut2);
160
+ });
161
+
162
+
163
+ const normA1 = glm.vec3.fromValues(3, 4, 5);
164
+ const normOut1 = glm.vec3.create();
165
+ const normA2 = new glmaths.Vec3(3, 4, 5);
166
+ const normOut2 = new glmaths.Vec3();
167
+ const s5 = new Benchmark.Suite('Vec3 normalize');
168
+ s5.add('gl-matrix vec3.normalize(out, a)', () => {
169
+ glm.vec3.normalize(normOut1, normA1);
170
+ });
171
+ s5.add('glmaths a.normalize(out)', () => {
172
+ normA2.normalize(normOut2);
173
+ });
174
+
175
+
176
+ const s6 = new Benchmark.Suite('Vec3 scale');
177
+ s6.add('gl-matrix vec3.scale(out, a, 2.5)', () => {
178
+ glm.vec3.scale(out1, a1, 2.5);
179
+ });
180
+ s6.add('glmaths a.scale(2.5, out)', () => {
181
+ a2.scale(2.5, out2);
182
+ });
183
+
184
+
185
+ const s7 = new Benchmark.Suite('Vec3 length');
186
+ s7.add('gl-matrix vec3.length(a)', () => {
187
+ glm.vec3.length(a1);
188
+ });
189
+ s7.add('glmaths a.len()', () => {
190
+ a2.len();
191
+ });
192
+
193
+
194
+ const s8 = new Benchmark.Suite('Vec3 distance');
195
+ s8.add('gl-matrix vec3.distance(a, b)', () => {
196
+ glm.vec3.distance(a1, b1);
197
+ });
198
+ s8.add('glmaths Vec3.distance(a, b)', () => {
199
+ glmaths.Vec3.distance(a2, b2);
200
+ });
201
+
202
+
203
+ const lerpOut1 = glm.vec3.create();
204
+ const lerpOut2 = new glmaths.Vec3();
205
+ const s9 = new Benchmark.Suite('Vec3 lerp');
206
+ s9.add('gl-matrix vec3.lerp(out, a, b, 0.5)', () => {
207
+ glm.vec3.lerp(lerpOut1, a1, b1, 0.5);
208
+ });
209
+ s9.add('glmaths Vec3.lerp(a, b, 0.5, out)', () => {
210
+ glmaths.Vec3.lerp(a2, b2, 0.5, lerpOut2);
211
+ });
212
+
213
+ return runSuite(s1)
214
+ .then(() => runSuite(s2))
215
+ .then(() => runSuite(s3))
216
+ .then(() => runSuite(s4))
217
+ .then(() => runSuite(s5))
218
+ .then(() => runSuite(s6))
219
+ .then(() => runSuite(s7))
220
+ .then(() => runSuite(s8))
221
+ .then(() => runSuite(s9));
222
+ }
223
+
224
+ // ─────────────────────────────────────────────
225
+ // Vec2 benchmarks
226
+ // ─────────────────────────────────────────────
227
+ function vec2Benchmarks() {
228
+
229
+ const s1 = new Benchmark.Suite('Vec2 creation');
230
+ s1.add('gl-matrix vec2.fromValues(1, 2)', () => {
231
+ const v = glm.vec2.fromValues(1, 2);
232
+ });
233
+ s1.add('gl-matrix v=vec2.create() vec2.set(v, 1, 2)', () => {
234
+ const v = glm.vec2.create()
235
+ glm.vec2.set(v, 1, 2)
236
+ });
237
+ s1.add('glmaths vec2(1,2)', () => {
238
+ const v = glmaths.vec2(1, 2);
239
+ });
240
+ // s1.add('glmaths new Vec2(1,2)', () => {
241
+ // const v = new glmaths.Vec2(1, 2);
242
+ // });
243
+
244
+ const a1 = glm.vec2.fromValues(3, 7);
245
+ const b1 = glm.vec2.fromValues(1, 4);
246
+ const out1 = glm.vec2.create();
247
+ const a2 = new glmaths.Vec2(3, 7);
248
+ const b2 = new glmaths.Vec2(1, 4);
249
+ const out2 = new glmaths.Vec2();
250
+
251
+
252
+ const s2 = new Benchmark.Suite('Vec2 add');
253
+ s2.add('gl-matrix vec2.add(out, a, b)', () => {
254
+ glm.vec2.add(out1, a1, b1);
255
+ });
256
+ s2.add('glmaths a.add(b, out)', () => {
257
+ a2.add(b2, out2);
258
+ });
259
+
260
+
261
+ const normOut1 = glm.vec2.create();
262
+ const normOut2 = new glmaths.Vec2();
263
+ const s3 = new Benchmark.Suite('Vec2 normalize');
264
+ s3.add('gl-matrix vec2.normalize(out, a)', () => {
265
+ glm.vec2.normalize(normOut1, a1);
266
+ });
267
+ s3.add('glmaths a.normalize(out)', () => {
268
+ a2.normalize(normOut2);
269
+ });
270
+
271
+ return runSuite(s1).then(() => runSuite(s2));
272
+ }
273
+
274
+ // ─────────────────────────────────────────────
275
+ // Vec4 benchmarks
276
+ // ─────────────────────────────────────────────
277
+ function vec4Benchmarks() {
278
+ const a1 = glm.vec4.fromValues(1, 2, 3, 4);
279
+ const b1 = glm.vec4.fromValues(5, 6, 7, 8);
280
+ const out1 = glm.vec4.create();
281
+ const a2 = new glmaths.Vec4(1, 2, 3, 4);
282
+ const b2 = new glmaths.Vec4(5, 6, 7, 8);
283
+ const out2 = new glmaths.Vec4();
284
+
285
+
286
+ const s1 = new Benchmark.Suite('Vec4 add');
287
+ s1.add('gl-matrix vec4.add(out, a, b)', () => {
288
+ glm.vec4.add(out1, a1, b1);
289
+ });
290
+ s1.add('glmaths a.add(b, out)', () => {
291
+ a2.add(b2, out2);
292
+ });
293
+
294
+
295
+ const normOut1 = glm.vec4.create();
296
+ const normOut2 = new glmaths.Vec4();
297
+ const s2 = new Benchmark.Suite('Vec4 normalize');
298
+ s2.add('gl-matrix vec4.normalize(out, a)', () => {
299
+ glm.vec4.normalize(normOut1, a1);
300
+ });
301
+ s2.add('glmaths a.normalize(out)', () => {
302
+ a2.normalize(normOut2);
303
+ });
304
+
305
+ return runSuite(s1).then(() => runSuite(s2));
306
+ }
307
+
308
+ // ─────────────────────────────────────────────
309
+ // Mat4 benchmarks
310
+ // ─────────────────────────────────────────────
311
+ function mat4Benchmarks() {
312
+
313
+ const s1 = new Benchmark.Suite('Mat4 creation');
314
+ s1.add('gl-matrix mat4.create()', () => {
315
+ glm.mat4.create();
316
+ });
317
+ s1.add('glmaths mat4()', () => {
318
+ glmaths.mat4();
319
+ });
320
+ s1.add('glmaths new Mat4()', () => {
321
+ new glmaths.Mat4();
322
+ });
323
+
324
+
325
+ const ma1 = glm.mat4.create(); glm.mat4.fromRotation(ma1, 0.5, [0, 1, 0]);
326
+ const mb1 = glm.mat4.create(); glm.mat4.fromTranslation(mb1, [1, 2, 3]);
327
+ const mout1 = glm.mat4.create();
328
+
329
+ const ma2 = glmaths.Mat4.fromRotation(0.5, new glmaths.Vec3(0, 1, 0));
330
+ const mb2 = glmaths.Mat4.fromTranslation(new glmaths.Vec3(1, 2, 3));
331
+ const mout2 = new glmaths.Mat4();
332
+
333
+ const s2 = new Benchmark.Suite('Mat4 multiply');
334
+ s2.add('gl-matrix mat4.multiply(out, a, b)', () => {
335
+ glm.mat4.multiply(mout1, ma1, mb1);
336
+ });
337
+ s2.add('glmaths a.multiply(b, out)', () => {
338
+ ma2.multiply(mb2, mout2);
339
+ });
340
+
341
+
342
+ const invOut1 = glm.mat4.create();
343
+ const invOut2 = new glmaths.Mat4();
344
+ const s3 = new Benchmark.Suite('Mat4 invert');
345
+ s3.add('gl-matrix mat4.invert(out, a)', () => {
346
+ glm.mat4.invert(invOut1, ma1);
347
+ });
348
+ s3.add('glmaths a.invert(out)', () => {
349
+ ma2.invert(invOut2);
350
+ });
351
+
352
+
353
+ const trOut1 = glm.mat4.create();
354
+ const trOut2 = new glmaths.Mat4();
355
+ const s4 = new Benchmark.Suite('Mat4 transpose');
356
+ s4.add('gl-matrix mat4.transpose(out, a)', () => {
357
+ glm.mat4.transpose(trOut1, ma1);
358
+ });
359
+ s4.add('glmaths a.transpose(out)', () => {
360
+ ma2.transpose(trOut2);
361
+ });
362
+
363
+
364
+ const tv = [1, 2, 3];
365
+ const tv2 = new glmaths.Vec3(1, 2, 3);
366
+ const tlOut1 = glm.mat4.create();
367
+ const tlOut2 = new glmaths.Mat4();
368
+ const s5 = new Benchmark.Suite('Mat4 translate');
369
+ s5.add('gl-matrix mat4.translate(out, a, v)', () => {
370
+ glm.mat4.translate(tlOut1, ma1, tv);
371
+ });
372
+ s5.add('glmaths a.translate(v, out)', () => {
373
+ ma2.translate(tv2, tlOut2);
374
+ });
375
+
376
+
377
+ const sv = [2, 2, 2];
378
+ const sv2 = new glmaths.Vec3(2, 2, 2);
379
+ const scOut1 = glm.mat4.create();
380
+ const scOut2 = new glmaths.Mat4();
381
+ const s6 = new Benchmark.Suite('Mat4 scale');
382
+ s6.add('gl-matrix mat4.scale(out, a, v)', () => {
383
+ glm.mat4.scale(scOut1, ma1, sv);
384
+ });
385
+ s6.add('glmaths a.scale(v, out)', () => {
386
+ ma2.scale(sv2, scOut2);
387
+ });
388
+
389
+
390
+ const rxOut1 = glm.mat4.create();
391
+ const rxOut2 = new glmaths.Mat4();
392
+ const s7 = new Benchmark.Suite('Mat4 rotateX');
393
+ s7.add('gl-matrix mat4.rotateX(out, a, rad)', () => {
394
+ glm.mat4.rotateX(rxOut1, ma1, 0.7);
395
+ });
396
+ s7.add('glmaths a.rotateX(rad, out)', () => {
397
+ ma2.rotateX(0.7, rxOut2);
398
+ });
399
+
400
+
401
+ const s8 = new Benchmark.Suite('Mat4 determinant');
402
+ s8.add('gl-matrix mat4.determinant(a)', () => {
403
+ glm.mat4.determinant(ma1);
404
+ });
405
+ s8.add('glmaths a.determinant()', () => {
406
+ ma2.determinant();
407
+ });
408
+
409
+
410
+ const pOut1 = glm.mat4.create();
411
+ const pOut2 = new glmaths.Mat4();
412
+ const s9 = new Benchmark.Suite('Mat4 perspective');
413
+ s9.add('gl-matrix mat4.perspective(out, fov, asp, near, far)', () => {
414
+ glm.mat4.perspective(pOut1, Math.PI / 4, 16 / 9, 0.1, 1000);
415
+ });
416
+ s9.add('glmaths Mat4.perspective(fov, asp, near, far, out)', () => {
417
+ glmaths.Mat4.perspective(Math.PI / 4, 16 / 9, 0.1, 1000, pOut2);
418
+ });
419
+
420
+
421
+ const eye = [0, 5, 10];
422
+ const center = [0, 0, 0];
423
+ const up = [0, 1, 0];
424
+ const eye2 = new glmaths.Vec3(0, 5, 10);
425
+ const center2 = new glmaths.Vec3(0, 0, 0);
426
+ const up2 = new glmaths.Vec3(0, 1, 0);
427
+ const laOut1 = glm.mat4.create();
428
+ const laOut2 = new glmaths.Mat4();
429
+ const s10 = new Benchmark.Suite('Mat4 lookAt');
430
+ s10.add('gl-matrix mat4.lookAt(out, eye, center, up)', () => {
431
+ glm.mat4.lookAt(laOut1, eye, center, up);
432
+ });
433
+ s10.add('glmaths Mat4.lookAt(eye, center, up, out)', () => {
434
+ glmaths.Mat4.lookAt(eye2, center2, up2, laOut2);
435
+ });
436
+
437
+ return runSuite(s1)
438
+ .then(() => runSuite(s2))
439
+ .then(() => runSuite(s3))
440
+ .then(() => runSuite(s4))
441
+ .then(() => runSuite(s5))
442
+ .then(() => runSuite(s6))
443
+ .then(() => runSuite(s7))
444
+ .then(() => runSuite(s8))
445
+ .then(() => runSuite(s9))
446
+ .then(() => runSuite(s10));
447
+ }
448
+
449
+ // ─────────────────────────────────────────────
450
+ // Mat3 benchmarks
451
+ // ─────────────────────────────────────────────
452
+ function mat3Benchmarks() {
453
+ const ma1 = glm.mat3.create();
454
+ glm.mat3.fromRotation(ma1, 0.5);
455
+ const mb1 = glm.mat3.create();
456
+ glm.mat3.fromRotation(mb1, 1.2);
457
+ const mout1 = glm.mat3.create();
458
+
459
+ const ma2 = glmaths.Mat3.fromRotation(0.5);
460
+ const mb2 = glmaths.Mat3.fromRotation(1.2);
461
+ const mout2 = new glmaths.Mat3();
462
+
463
+
464
+ const s1 = new Benchmark.Suite('Mat3 multiply');
465
+ s1.add('gl-matrix mat3.multiply(out, a, b)', () => {
466
+ glm.mat3.multiply(mout1, ma1, mb1);
467
+ });
468
+ s1.add('glmaths a.multiply(b, out)', () => {
469
+ ma2.multiply(mb2, mout2);
470
+ });
471
+
472
+
473
+ const invOut1 = glm.mat3.create();
474
+ const invOut2 = new glmaths.Mat3();
475
+ const s2 = new Benchmark.Suite('Mat3 invert');
476
+ s2.add('gl-matrix mat3.invert(out, a)', () => {
477
+ glm.mat3.invert(invOut1, ma1);
478
+ });
479
+ s2.add('glmaths a.invert(out)', () => {
480
+ ma2.invert(invOut2);
481
+ });
482
+
483
+ return runSuite(s1).then(() => runSuite(s2));
484
+ }
485
+
486
+ // ─────────────────────────────────────────────
487
+ // Quat benchmarks
488
+ // ─────────────────────────────────────────────
489
+ function quatBenchmarks() {
490
+ const a1 = glm.quat.create(); glm.quat.rotateX(a1, a1, 0.5);
491
+ const b1 = glm.quat.create(); glm.quat.rotateY(b1, b1, 0.8);
492
+ const out1 = glm.quat.create();
493
+
494
+ const a2 = new glmaths.Quat(); a2.rotateX(0.5);
495
+ const b2 = new glmaths.Quat(); b2.rotateY(0.8);
496
+ const out2 = new glmaths.Quat();
497
+
498
+
499
+ const s1 = new Benchmark.Suite('Quat multiply');
500
+ s1.add('gl-matrix quat.multiply(out, a, b)', () => {
501
+ glm.quat.multiply(out1, a1, b1);
502
+ });
503
+ s1.add('glmaths a.multiply(b, out)', () => {
504
+ a2.multiply(b2, out2);
505
+ });
506
+
507
+
508
+ const slOut1 = glm.quat.create();
509
+ const slOut2 = new glmaths.Quat();
510
+ const s2 = new Benchmark.Suite('Quat slerp');
511
+ s2.add('gl-matrix quat.slerp(out, a, b, 0.5)', () => {
512
+ glm.quat.slerp(slOut1, a1, b1, 0.5);
513
+ });
514
+ s2.add('glmaths a.slerp(b, 0.5, out)', () => {
515
+ a2.slerp(b2, 0.5, slOut2);
516
+ });
517
+
518
+
519
+ const nOut1 = glm.quat.create();
520
+ const nOut2 = new glmaths.Quat();
521
+ const s3 = new Benchmark.Suite('Quat normalize');
522
+ s3.add('gl-matrix quat.normalize(out, a)', () => {
523
+ glm.quat.normalize(nOut1, a1);
524
+ });
525
+ s3.add('glmaths a.normalize(out)', () => {
526
+ a2.normalize(nOut2);
527
+ });
528
+
529
+
530
+ const iOut1 = glm.quat.create();
531
+ const iOut2 = new glmaths.Quat();
532
+ const s4 = new Benchmark.Suite('Quat invert');
533
+ s4.add('gl-matrix quat.invert(out, a)', () => {
534
+ glm.quat.invert(iOut1, a1);
535
+ });
536
+ s4.add('glmaths a.invert(out)', () => {
537
+ a2.invert(iOut2);
538
+ });
539
+
540
+
541
+ const axis = [0, 1, 0];
542
+ const axis2 = new glmaths.Vec3(0, 1, 0);
543
+ const faOut1 = glm.quat.create();
544
+ const faOut2 = new glmaths.Quat();
545
+ const s5 = new Benchmark.Suite('Quat fromAxisAngle');
546
+ s5.add('gl-matrix quat.setAxisAngle(out, axis, rad)', () => {
547
+ glm.quat.setAxisAngle(faOut1, axis, 1.2);
548
+ });
549
+ s5.add('glmaths Quat.fromAxisAngle(axis, rad, out)', () => {
550
+ glmaths.Quat.fromAxisAngle(axis2, 1.2, faOut2);
551
+ });
552
+
553
+ return runSuite(s1)
554
+ .then(() => runSuite(s2))
555
+ .then(() => runSuite(s3))
556
+ .then(() => runSuite(s4))
557
+ .then(() => runSuite(s5));
558
+ }
559
+
560
+ // ─────────────────────────────────────────────
561
+ // Swizzle overhead (unique to glm)
562
+ // ─────────────────────────────────────────────
563
+ function swizzleBenchmarks() {
564
+ const v = new glmaths.Vec3(1, 2, 3);
565
+
566
+
567
+ const s1 = new Benchmark.Suite('Swizzle');
568
+ s1.add('Direct component access v[0], v[1], v[2]', () => {
569
+ const x = v[0], y = v[1], z = v[2];
570
+ });
571
+ s1.add('Named property access v.x, v.y, v.z', () => {
572
+ const x = v.x, y = v.y, z = v.z;
573
+ });
574
+ s1.add('Swizzle v.xyz', () => {
575
+ const r = v.xyz;
576
+ });
577
+ s1.add('Swizzle v.zyx', () => {
578
+ const r = v.zyx;
579
+ });
580
+ s1.add('Swizzle v.xy (Vec2)', () => {
581
+ const r = v.xy;
582
+ });
583
+
584
+ return runSuite(s1);
585
+ }
586
+
587
+ // ─────────────────────────────────────────────
588
+ // New method benchmarks
589
+ // ─────────────────────────────────────────────
590
+ function newMethodBenchmarks() {
591
+ // --- Vec3 transformMat4 ---
592
+ const tv = new glmaths.Vec3(1, 2, 3);
593
+ const tmat = glmaths.Mat4.fromTranslation(new glmaths.Vec3(10, 20, 30));
594
+ const tvOut = new glmaths.Vec3();
595
+
596
+ const tv1 = glm.vec3.fromValues(1, 2, 3);
597
+ const tmat1 = glm.mat4.create(); glm.mat4.fromTranslation(tmat1, [10, 20, 30]);
598
+ const tvOut1 = glm.vec3.create();
599
+
600
+ const s1 = new Benchmark.Suite('Vec3 transformMat4');
601
+ s1.add('gl-matrix vec3.transformMat4(out, v, m)', () => {
602
+ glm.vec3.transformMat4(tvOut1, tv1, tmat1);
603
+ });
604
+ s1.add('glmaths v.transformMat4(m, out)', () => {
605
+ tv.transformMat4(tmat, tvOut);
606
+ });
607
+
608
+ // --- Vec3 transformQuat ---
609
+ const tq1 = glm.quat.create(); glm.quat.rotateY(tq1, tq1, 0.5);
610
+ const tqOut1 = glm.vec3.create();
611
+ const tq2 = new glmaths.Quat(); tq2.rotateY(0.5);
612
+ const tqOut2 = new glmaths.Vec3();
613
+
614
+ const s2 = new Benchmark.Suite('Vec3 transformQuat');
615
+ s2.add('gl-matrix vec3.transformQuat(out, v, q)', () => {
616
+ glm.vec3.transformQuat(tqOut1, tv1, tq1);
617
+ });
618
+ s2.add('glmaths v.transformQuat(q, out)', () => {
619
+ tv.transformQuat(tq2, tqOut2);
620
+ });
621
+
622
+ // --- Vec3 scaleAndAdd ---
623
+ const saA1 = glm.vec3.fromValues(1, 2, 3);
624
+ const saB1 = glm.vec3.fromValues(4, 5, 6);
625
+ const saOut1 = glm.vec3.create();
626
+ const saA2 = new glmaths.Vec3(1, 2, 3);
627
+ const saB2 = new glmaths.Vec3(4, 5, 6);
628
+ const saOut2 = new glmaths.Vec3();
629
+
630
+ const s3 = new Benchmark.Suite('Vec3 scaleAndAdd');
631
+ s3.add('gl-matrix vec3.scaleAndAdd(out, a, b, s)', () => {
632
+ glm.vec3.scaleAndAdd(saOut1, saA1, saB1, 2.5);
633
+ });
634
+ s3.add('glmaths a.scaleAndAdd(b, s, out)', () => {
635
+ saA2.scaleAndAdd(saB2, 2.5, saOut2);
636
+ });
637
+
638
+ // --- Vec3 GLSL: mix/clamp ---
639
+ const mixA2 = new glmaths.Vec3(0, 0, 0);
640
+ const mixB2 = new glmaths.Vec3(10, 20, 30);
641
+ const mixOut2 = new glmaths.Vec3();
642
+
643
+ const s4 = new Benchmark.Suite('Vec3 mix (lerp)');
644
+ s4.add('gl-matrix vec3.lerp(out, a, b, 0.5)', () => {
645
+ glm.vec3.lerp(saOut1, saA1, saB1, 0.5);
646
+ });
647
+ s4.add('glmaths a.mix(b, 0.5, out)', () => {
648
+ mixA2.mix(mixB2, 0.5, mixOut2);
649
+ });
650
+
651
+ // --- Vec4 transformMat4 ---
652
+ const v4a1 = glm.vec4.fromValues(1, 2, 3, 1);
653
+ const v4out1 = glm.vec4.create();
654
+ const v4a2 = new glmaths.Vec4(1, 2, 3, 1);
655
+ const v4out2 = new glmaths.Vec4();
656
+
657
+ const s5 = new Benchmark.Suite('Vec4 transformMat4');
658
+ s5.add('gl-matrix vec4.transformMat4(out, v, m)', () => {
659
+ glm.vec4.transformMat4(v4out1, v4a1, tmat1);
660
+ });
661
+ s5.add('glmaths v.transformMat4(m, out)', () => {
662
+ v4a2.transformMat4(tmat, v4out2);
663
+ });
664
+
665
+ // --- Mat4 project/unProject ---
666
+ const projMat = glmaths.Mat4.perspective(Math.PI / 4, 16 / 9, 0.1, 100);
667
+ const modelMat = glmaths.Mat4.identity;
668
+ const viewport = new glmaths.Vec4(0, 0, 800, 600);
669
+ const worldPt = new glmaths.Vec3(1, 2, -5);
670
+
671
+ const s6 = new Benchmark.Suite('Mat4 project');
672
+ s6.add('glmaths Mat4.project(obj, model, proj, vp)', () => {
673
+ glmaths.Mat4.project(worldPt, modelMat, projMat, viewport);
674
+ });
675
+
676
+ const winPt = glmaths.Mat4.project(worldPt, modelMat, projMat, viewport);
677
+ const s7 = new Benchmark.Suite('Mat4 unProject');
678
+ s7.add('glmaths Mat4.unProject(win, model, proj, vp)', () => {
679
+ glmaths.Mat4.unProject(winPt, modelMat, projMat, viewport);
680
+ });
681
+
682
+ // --- Quat euler angles ---
683
+ const eq = new glmaths.Quat(); eq.rotateX(0.5); eq.rotateY(0.3);
684
+ const s8 = new Benchmark.Suite('Quat eulerAngles / pitch / yaw / roll');
685
+ s8.add('glmaths q.pitch()', () => { eq.pitch(); });
686
+ s8.add('glmaths q.yaw()', () => { eq.yaw(); });
687
+ s8.add('glmaths q.roll()', () => { eq.roll(); });
688
+ s8.add('glmaths q.eulerAngles()', () => { eq.eulerAngles(); });
689
+
690
+ // --- Quat toMat4 ---
691
+ const qm4Out = new glmaths.Mat4();
692
+ const s9 = new Benchmark.Suite('Quat toMat4 vs Mat4.fromQuat');
693
+ s9.add('glmaths Mat4.fromQuat(q, out)', () => {
694
+ glmaths.Mat4.fromQuat(eq, qm4Out);
695
+ });
696
+ s9.add('glmaths q.toMat4(out)', () => {
697
+ eq.toMat4(qm4Out);
698
+ });
699
+
700
+ // --- Quat2 operations ---
701
+ const dqA = glmaths.Quat2.fromRotationTranslation(
702
+ glmaths.Quat.fromAxisAngle(new glmaths.Vec3(0, 1, 0), 0.5),
703
+ new glmaths.Vec3(1, 2, 3)
704
+ );
705
+ const dqB = glmaths.Quat2.fromTranslation(new glmaths.Vec3(4, 5, 6));
706
+ const dqOut = new glmaths.Quat2();
707
+
708
+ const s10 = new Benchmark.Suite('Quat2 multiply');
709
+ s10.add('glmaths a.multiply(b, out)', () => {
710
+ dqA.multiply(dqB, dqOut);
711
+ });
712
+
713
+ const s11 = new Benchmark.Suite('Quat2 getTranslation');
714
+ s11.add('glmaths dq.getTranslation()', () => {
715
+ dqA.getTranslation();
716
+ });
717
+
718
+ return runSuite(s1)
719
+ .then(() => runSuite(s2))
720
+ .then(() => runSuite(s3))
721
+ .then(() => runSuite(s4))
722
+ .then(() => runSuite(s5))
723
+ .then(() => runSuite(s6))
724
+ .then(() => runSuite(s7))
725
+ .then(() => runSuite(s8))
726
+ .then(() => runSuite(s9))
727
+ .then(() => runSuite(s10))
728
+ .then(() => runSuite(s11));
729
+ }
730
+
731
+ // ─────────────────────────────────────────────
732
+ // Run all
733
+ // ─────────────────────────────────────────────
734
+ async function main() {
735
+ await vec3Benchmarks();
736
+ await vec2Benchmarks();
737
+ await vec4Benchmarks();
738
+ await mat4Benchmarks();
739
+ await mat3Benchmarks();
740
+ await quatBenchmarks();
741
+ await swizzleBenchmarks();
742
+ await newMethodBenchmarks();
743
+
744
+ printMarkdownTable();
745
+ }
746
+
747
+ main().catch(console.error);