@vib3code/sdk 2.0.3-canary.45332e3 → 2.0.3-canary.4874bcf
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/DOCS/AGENT_HARNESS_ARCHITECTURE.md +2 -0
- package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
- package/DOCS/ARCHITECTURE.md +1 -0
- package/DOCS/CI_TESTING.md +2 -0
- package/DOCS/CLI_ONBOARDING.md +2 -0
- package/DOCS/CONTROL_REFERENCE.md +2 -0
- package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +2 -0
- package/DOCS/ENV_SETUP.md +2 -0
- package/DOCS/EPIC_SCROLL_EVENTS.md +2 -0
- package/DOCS/EXPANSION_DESIGN.md +979 -0
- package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
- package/DOCS/EXPORT_FORMATS.md +2 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
- package/DOCS/HANDOFF_LANDING_PAGE.md +2 -0
- package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +2 -0
- package/DOCS/LICENSING_TIERS.md +2 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +2 -0
- package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +3 -1
- package/DOCS/OBS_SETUP_GUIDE.md +2 -0
- package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
- package/DOCS/PRODUCT_STRATEGY.md +2 -0
- package/DOCS/PROJECT_SETUP.md +2 -0
- package/DOCS/README.md +5 -3
- package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +2 -0
- package/DOCS/RENDERER_LIFECYCLE.md +2 -0
- package/DOCS/REPO_MANIFEST.md +2 -0
- package/DOCS/ROADMAP.md +2 -0
- package/DOCS/SCROLL_TIMELINE_v3.md +2 -0
- package/DOCS/SITE_REFACTOR_PLAN.md +2 -0
- package/DOCS/STATUS.md +2 -0
- package/DOCS/SYSTEM_INVENTORY.md +2 -0
- package/DOCS/TELEMETRY_EXPORTS.md +2 -0
- package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +2 -0
- package/DOCS/VISUAL_ANALYSIS_FACETAD.md +2 -0
- package/DOCS/VISUAL_ANALYSIS_SIMONE.md +2 -0
- package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +2 -0
- package/DOCS/WEBGPU_STATUS.md +2 -0
- package/DOCS/XR_BENCHMARKS.md +2 -0
- package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -34
- package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -80
- package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -42
- package/DOCS/archive/SESSION_014_PLAN.md +1 -195
- package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -56
- package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -72
- package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -741
- package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -38
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-01-31.md +2 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +2 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +2 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +2 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +2 -0
- package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
- package/DOCS/dev-tracks/README.md +2 -0
- package/package.json +2 -4
- package/src/cli/index.js +59 -5
- package/src/experimental/GameLoop.js +72 -0
- package/src/experimental/LatticePhysics.js +100 -0
- package/src/experimental/LiveDirector.js +143 -0
- package/src/experimental/PlayerController4D.js +154 -0
- package/src/experimental/VIB3Actor.js +138 -0
- package/src/experimental/VIB3Compositor.js +117 -0
- package/src/experimental/VIB3Link.js +122 -0
- package/src/experimental/VIB3Orchestrator.js +146 -0
- package/src/experimental/VIB3Universe.js +109 -0
- package/src/experimental/demos/CrystalLabyrinth.js +202 -0
- package/src/export/SVGExporter.js +9 -5
- package/src/features/CollectionManager.js +27 -9
- package/src/gallery/CollectionManager.js +27 -9
- package/src/geometry/generators/Crystal.js +2 -2
- package/src/geometry/warp/HypersphereCore.js +53 -24
- package/src/math/Mat4x4.js +418 -142
- package/src/math/Projection.js +57 -7
- package/src/math/Rotor4D.js +102 -73
- package/src/math/Vec4.js +265 -111
- package/src/quantum/QuantumVisualizer.js +28 -0
- package/src/scene/Node4D.js +74 -24
- package/src/testing/ProjectionClass.test.js +38 -0
- package/src/variations/VariationManager.js +6 -1
- package/src/wasm/WasmLoader.js +11 -6
- package/tools/update_projection.py +109 -0
package/src/math/Mat4x4.js
CHANGED
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
import { Vec4 } from './Vec4.js';
|
|
19
19
|
|
|
20
20
|
export class Mat4x4 {
|
|
21
|
+
/**
|
|
22
|
+
* Internal token to skip initialization during construction
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
static UNINITIALIZED = {};
|
|
26
|
+
|
|
21
27
|
/**
|
|
22
28
|
* Create a new 4x4 matrix
|
|
23
29
|
* Default is identity matrix
|
|
@@ -26,6 +32,8 @@ export class Mat4x4 {
|
|
|
26
32
|
constructor(elements = null) {
|
|
27
33
|
this.data = new Float32Array(16);
|
|
28
34
|
|
|
35
|
+
if (elements === Mat4x4.UNINITIALIZED) return;
|
|
36
|
+
|
|
29
37
|
if (elements) {
|
|
30
38
|
if (elements.length !== 16) {
|
|
31
39
|
throw new Error('Mat4x4 requires exactly 16 elements');
|
|
@@ -40,17 +48,25 @@ export class Mat4x4 {
|
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Reset to identity matrix
|
|
53
|
+
* @returns {Mat4x4} this
|
|
54
|
+
*/
|
|
55
|
+
identity() {
|
|
56
|
+
const d = this.data;
|
|
57
|
+
d[0] = 1; d[1] = 0; d[2] = 0; d[3] = 0;
|
|
58
|
+
d[4] = 0; d[5] = 1; d[6] = 0; d[7] = 0;
|
|
59
|
+
d[8] = 0; d[9] = 0; d[10] = 1; d[11] = 0;
|
|
60
|
+
d[12] = 0; d[13] = 0; d[14] = 0; d[15] = 1;
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
43
64
|
/**
|
|
44
65
|
* Create identity matrix
|
|
45
66
|
* @returns {Mat4x4}
|
|
46
67
|
*/
|
|
47
68
|
static identity() {
|
|
48
|
-
return new Mat4x4(
|
|
49
|
-
1, 0, 0, 0,
|
|
50
|
-
0, 1, 0, 0,
|
|
51
|
-
0, 0, 1, 0,
|
|
52
|
-
0, 0, 0, 1
|
|
53
|
-
]);
|
|
69
|
+
return new Mat4x4();
|
|
54
70
|
}
|
|
55
71
|
|
|
56
72
|
/**
|
|
@@ -58,7 +74,7 @@ export class Mat4x4 {
|
|
|
58
74
|
* @returns {Mat4x4}
|
|
59
75
|
*/
|
|
60
76
|
static zero() {
|
|
61
|
-
return new Mat4x4(
|
|
77
|
+
return new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
62
78
|
}
|
|
63
79
|
|
|
64
80
|
/**
|
|
@@ -157,10 +173,11 @@ export class Mat4x4 {
|
|
|
157
173
|
/**
|
|
158
174
|
* Multiply two matrices
|
|
159
175
|
* @param {Mat4x4} m - Right operand
|
|
176
|
+
* @param {Mat4x4} [target=null] - Optional target matrix to store result
|
|
160
177
|
* @returns {Mat4x4} New matrix = this * m
|
|
161
178
|
*/
|
|
162
|
-
multiply(m) {
|
|
163
|
-
const out = new Mat4x4();
|
|
179
|
+
multiply(m, target = null) {
|
|
180
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
164
181
|
const r = out.data;
|
|
165
182
|
const a = this.data;
|
|
166
183
|
const b = m.data;
|
|
@@ -259,16 +276,22 @@ export class Mat4x4 {
|
|
|
259
276
|
/**
|
|
260
277
|
* Transform a Vec4 by this matrix
|
|
261
278
|
* @param {Vec4} v
|
|
279
|
+
* @param {Vec4} [target=null] - Optional target vector to store result
|
|
262
280
|
* @returns {Vec4} Transformed vector
|
|
263
281
|
*/
|
|
264
|
-
multiplyVec4(v) {
|
|
282
|
+
multiplyVec4(v, target = null) {
|
|
265
283
|
const m = this.data;
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
const out = target || new Vec4();
|
|
285
|
+
|
|
286
|
+
// Cache components to support aliasing (target === v)
|
|
287
|
+
const x = v.x, y = v.y, z = v.z, w = v.w;
|
|
288
|
+
|
|
289
|
+
out.x = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
|
|
290
|
+
out.y = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
|
|
291
|
+
out.z = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
|
|
292
|
+
out.w = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
|
|
293
|
+
|
|
294
|
+
return out;
|
|
272
295
|
}
|
|
273
296
|
|
|
274
297
|
/**
|
|
@@ -310,41 +333,57 @@ export class Mat4x4 {
|
|
|
310
333
|
/**
|
|
311
334
|
* Add another matrix
|
|
312
335
|
* @param {Mat4x4} m
|
|
336
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
313
337
|
* @returns {Mat4x4} New matrix
|
|
314
338
|
*/
|
|
315
|
-
add(m) {
|
|
316
|
-
const
|
|
339
|
+
add(m, target = null) {
|
|
340
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
341
|
+
const r = out.data;
|
|
342
|
+
const a = this.data;
|
|
343
|
+
const b = m.data;
|
|
344
|
+
|
|
317
345
|
for (let i = 0; i < 16; i++) {
|
|
318
|
-
|
|
346
|
+
r[i] = a[i] + b[i];
|
|
319
347
|
}
|
|
320
|
-
return
|
|
348
|
+
return out;
|
|
321
349
|
}
|
|
322
350
|
|
|
323
351
|
/**
|
|
324
352
|
* Multiply by scalar
|
|
325
353
|
* @param {number} s
|
|
354
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
326
355
|
* @returns {Mat4x4} New matrix
|
|
327
356
|
*/
|
|
328
|
-
scale(s) {
|
|
329
|
-
const
|
|
357
|
+
scale(s, target = null) {
|
|
358
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
359
|
+
const r = out.data;
|
|
360
|
+
const a = this.data;
|
|
361
|
+
|
|
330
362
|
for (let i = 0; i < 16; i++) {
|
|
331
|
-
|
|
363
|
+
r[i] = a[i] * s;
|
|
332
364
|
}
|
|
333
|
-
return
|
|
365
|
+
return out;
|
|
334
366
|
}
|
|
335
367
|
|
|
336
368
|
/**
|
|
337
369
|
* Transpose matrix
|
|
370
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
338
371
|
* @returns {Mat4x4} New transposed matrix
|
|
339
372
|
*/
|
|
340
|
-
transpose() {
|
|
373
|
+
transpose(target = null) {
|
|
341
374
|
const m = this.data;
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
375
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
376
|
+
const r = out.data;
|
|
377
|
+
// If target is same as source, use intermediate or careful swap
|
|
378
|
+
if (target === this) {
|
|
379
|
+
return this.transposeInPlace();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
r[0] = m[0]; r[4] = m[1]; r[8] = m[2]; r[12] = m[3];
|
|
383
|
+
r[1] = m[4]; r[5] = m[5]; r[9] = m[6]; r[13] = m[7];
|
|
384
|
+
r[2] = m[8]; r[6] = m[9]; r[10] = m[10]; r[14] = m[11];
|
|
385
|
+
r[3] = m[12]; r[7] = m[13]; r[11] = m[14]; r[15] = m[15];
|
|
386
|
+
return out;
|
|
348
387
|
}
|
|
349
388
|
|
|
350
389
|
/**
|
|
@@ -395,61 +434,85 @@ export class Mat4x4 {
|
|
|
395
434
|
|
|
396
435
|
/**
|
|
397
436
|
* Calculate inverse matrix
|
|
437
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
398
438
|
* @returns {Mat4x4|null} Inverse matrix or null if singular
|
|
399
439
|
*/
|
|
400
|
-
inverse() {
|
|
440
|
+
inverse(target = null) {
|
|
401
441
|
const m = this.data;
|
|
402
|
-
const
|
|
442
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
443
|
+
const inv = out.data;
|
|
444
|
+
|
|
445
|
+
// Note: For in-place inversion (target === this), we need to be careful.
|
|
446
|
+
// The standard algorithm uses input values for every output cell.
|
|
447
|
+
// We can check for aliasing or use local variables if we wanted full safety,
|
|
448
|
+
// but simplest is to compute to temp if aliased, or just computing to the array directly works
|
|
449
|
+
// IF we cache everything first. But here we are writing to `inv` index by index.
|
|
450
|
+
// If inv === m, writing inv[0] destroys m[0] which is needed for inv[5] etc.
|
|
451
|
+
// So aliasing is NOT safe with this direct write approach.
|
|
452
|
+
|
|
453
|
+
// Handle aliasing by cloning first if needed, or using temp array.
|
|
454
|
+
// Since we want performance, let's detect aliasing.
|
|
455
|
+
let sourceData = m;
|
|
456
|
+
if (target === this) {
|
|
457
|
+
// Copy source data to temp array so we can write to 'this.data' safely
|
|
458
|
+
// We can't avoid allocation entirely in this specific edge case easily without unrolling everything into locals,
|
|
459
|
+
// which is huge for 4x4 inverse.
|
|
460
|
+
// Using a static temp buffer would be unsafe for threading/recursion (not an issue in JS single thread usually but still).
|
|
461
|
+
// Let's just clone the source data for the calculation.
|
|
462
|
+
sourceData = new Float32Array(m);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const s = sourceData;
|
|
403
466
|
|
|
404
|
-
inv[0] =
|
|
405
|
-
|
|
467
|
+
inv[0] = s[5] * s[10] * s[15] - s[5] * s[11] * s[14] - s[9] * s[6] * s[15] +
|
|
468
|
+
s[9] * s[7] * s[14] + s[13] * s[6] * s[11] - s[13] * s[7] * s[10];
|
|
406
469
|
|
|
407
|
-
inv[4] = -
|
|
408
|
-
|
|
470
|
+
inv[4] = -s[4] * s[10] * s[15] + s[4] * s[11] * s[14] + s[8] * s[6] * s[15] -
|
|
471
|
+
s[8] * s[7] * s[14] - s[12] * s[6] * s[11] + s[12] * s[7] * s[10];
|
|
409
472
|
|
|
410
|
-
inv[8] =
|
|
411
|
-
|
|
473
|
+
inv[8] = s[4] * s[9] * s[15] - s[4] * s[11] * s[13] - s[8] * s[5] * s[15] +
|
|
474
|
+
s[8] * s[7] * s[13] + s[12] * s[5] * s[11] - s[12] * s[7] * s[9];
|
|
412
475
|
|
|
413
|
-
inv[12] = -
|
|
414
|
-
|
|
476
|
+
inv[12] = -s[4] * s[9] * s[14] + s[4] * s[10] * s[13] + s[8] * s[5] * s[14] -
|
|
477
|
+
s[8] * s[6] * s[13] - s[12] * s[5] * s[10] + s[12] * s[6] * s[9];
|
|
415
478
|
|
|
416
|
-
inv[1] = -
|
|
417
|
-
|
|
479
|
+
inv[1] = -s[1] * s[10] * s[15] + s[1] * s[11] * s[14] + s[9] * s[2] * s[15] -
|
|
480
|
+
s[9] * s[3] * s[14] - s[13] * s[2] * s[11] + s[13] * s[3] * s[10];
|
|
418
481
|
|
|
419
|
-
inv[5] =
|
|
420
|
-
|
|
482
|
+
inv[5] = s[0] * s[10] * s[15] - s[0] * s[11] * s[14] - s[8] * s[2] * s[15] +
|
|
483
|
+
s[8] * s[3] * s[14] + s[12] * s[2] * s[11] - s[12] * s[3] * s[10];
|
|
421
484
|
|
|
422
|
-
inv[9] = -
|
|
423
|
-
|
|
485
|
+
inv[9] = -s[0] * s[9] * s[15] + s[0] * s[11] * s[13] + s[8] * s[1] * s[15] -
|
|
486
|
+
s[8] * s[3] * s[13] - s[12] * s[1] * s[11] + s[12] * s[3] * s[9];
|
|
424
487
|
|
|
425
|
-
inv[13] =
|
|
426
|
-
|
|
488
|
+
inv[13] = s[0] * s[9] * s[14] - s[0] * s[10] * s[13] - s[8] * s[1] * s[14] +
|
|
489
|
+
s[8] * s[2] * s[13] + s[12] * s[1] * s[10] - s[12] * s[2] * s[9];
|
|
427
490
|
|
|
428
|
-
inv[2] =
|
|
429
|
-
|
|
491
|
+
inv[2] = s[1] * s[6] * s[15] - s[1] * s[7] * s[14] - s[5] * s[2] * s[15] +
|
|
492
|
+
s[5] * s[3] * s[14] + s[13] * s[2] * s[7] - s[13] * s[3] * s[6];
|
|
430
493
|
|
|
431
|
-
inv[6] = -
|
|
432
|
-
|
|
494
|
+
inv[6] = -s[0] * s[6] * s[15] + s[0] * s[7] * s[14] + s[4] * s[2] * s[15] -
|
|
495
|
+
s[4] * s[3] * s[14] - s[12] * s[2] * s[7] + s[12] * s[3] * s[6];
|
|
433
496
|
|
|
434
|
-
inv[10] =
|
|
435
|
-
|
|
497
|
+
inv[10] = s[0] * s[5] * s[15] - s[0] * s[7] * s[13] - s[4] * s[1] * s[15] +
|
|
498
|
+
s[4] * s[3] * s[13] + s[12] * s[1] * s[7] - s[12] * s[3] * s[5];
|
|
436
499
|
|
|
437
|
-
inv[14] = -
|
|
438
|
-
|
|
500
|
+
inv[14] = -s[0] * s[5] * s[14] + s[0] * s[6] * s[13] + s[4] * s[1] * s[14] -
|
|
501
|
+
s[4] * s[2] * s[13] - s[12] * s[1] * s[6] + s[12] * s[2] * s[5];
|
|
439
502
|
|
|
440
|
-
inv[3] = -
|
|
441
|
-
|
|
503
|
+
inv[3] = -s[1] * s[6] * s[11] + s[1] * s[7] * s[10] + s[5] * s[2] * s[11] -
|
|
504
|
+
s[5] * s[3] * s[10] - s[9] * s[2] * s[7] + s[9] * s[3] * s[6];
|
|
442
505
|
|
|
443
|
-
inv[7] =
|
|
444
|
-
|
|
506
|
+
inv[7] = s[0] * s[6] * s[11] - s[0] * s[7] * s[10] - s[4] * s[2] * s[11] +
|
|
507
|
+
s[4] * s[3] * s[10] + s[8] * s[2] * s[7] - s[8] * s[3] * s[6];
|
|
445
508
|
|
|
446
|
-
inv[11] = -
|
|
447
|
-
|
|
509
|
+
inv[11] = -s[0] * s[5] * s[11] + s[0] * s[7] * s[9] + s[4] * s[1] * s[11] -
|
|
510
|
+
s[4] * s[3] * s[9] - s[8] * s[1] * s[7] + s[8] * s[3] * s[5];
|
|
448
511
|
|
|
449
|
-
inv[15] =
|
|
450
|
-
|
|
512
|
+
inv[15] = s[0] * s[5] * s[10] - s[0] * s[6] * s[9] - s[4] * s[1] * s[10] +
|
|
513
|
+
s[4] * s[2] * s[9] + s[8] * s[1] * s[6] - s[8] * s[2] * s[5];
|
|
451
514
|
|
|
452
|
-
const det =
|
|
515
|
+
const det = s[0] * inv[0] + s[1] * inv[4] + s[2] * inv[8] + s[3] * inv[12];
|
|
453
516
|
|
|
454
517
|
if (Math.abs(det) < 1e-10) {
|
|
455
518
|
return null; // Singular matrix
|
|
@@ -460,7 +523,7 @@ export class Mat4x4 {
|
|
|
460
523
|
inv[i] *= invDet;
|
|
461
524
|
}
|
|
462
525
|
|
|
463
|
-
return
|
|
526
|
+
return out;
|
|
464
527
|
}
|
|
465
528
|
|
|
466
529
|
/**
|
|
@@ -547,103 +610,279 @@ export class Mat4x4 {
|
|
|
547
610
|
return new Mat4x4(json.data);
|
|
548
611
|
}
|
|
549
612
|
|
|
613
|
+
// ========== IN-PLACE ROTATIONS ==========
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Rotate in XY plane in place
|
|
617
|
+
* @param {number} angle
|
|
618
|
+
* @returns {Mat4x4} this
|
|
619
|
+
*/
|
|
620
|
+
rotateXY(angle) {
|
|
621
|
+
const c = Math.cos(angle);
|
|
622
|
+
const s = Math.sin(angle);
|
|
623
|
+
const m = this.data;
|
|
624
|
+
|
|
625
|
+
for (let i = 0; i < 4; i++) {
|
|
626
|
+
const a0 = m[i]; // Col 0
|
|
627
|
+
const a1 = m[i + 4]; // Col 1
|
|
628
|
+
m[i] = a0 * c + a1 * s;
|
|
629
|
+
m[i + 4] = -a0 * s + a1 * c;
|
|
630
|
+
}
|
|
631
|
+
return this;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Rotate in XZ plane in place
|
|
636
|
+
* @param {number} angle
|
|
637
|
+
* @returns {Mat4x4} this
|
|
638
|
+
*/
|
|
639
|
+
rotateXZ(angle) {
|
|
640
|
+
const c = Math.cos(angle);
|
|
641
|
+
const s = Math.sin(angle);
|
|
642
|
+
const m = this.data;
|
|
643
|
+
|
|
644
|
+
for (let i = 0; i < 4; i++) {
|
|
645
|
+
const a0 = m[i]; // Col 0
|
|
646
|
+
const a2 = m[i + 8]; // Col 2
|
|
647
|
+
m[i] = a0 * c - a2 * s;
|
|
648
|
+
m[i + 8] = a0 * s + a2 * c;
|
|
649
|
+
}
|
|
650
|
+
return this;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Rotate in YZ plane in place
|
|
655
|
+
* @param {number} angle
|
|
656
|
+
* @returns {Mat4x4} this
|
|
657
|
+
*/
|
|
658
|
+
rotateYZ(angle) {
|
|
659
|
+
const c = Math.cos(angle);
|
|
660
|
+
const s = Math.sin(angle);
|
|
661
|
+
const m = this.data;
|
|
662
|
+
|
|
663
|
+
for (let i = 0; i < 4; i++) {
|
|
664
|
+
const a1 = m[i + 4]; // Col 1
|
|
665
|
+
const a2 = m[i + 8]; // Col 2
|
|
666
|
+
m[i + 4] = a1 * c + a2 * s;
|
|
667
|
+
m[i + 8] = -a1 * s + a2 * c;
|
|
668
|
+
}
|
|
669
|
+
return this;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Rotate in XW plane in place
|
|
674
|
+
* @param {number} angle
|
|
675
|
+
* @returns {Mat4x4} this
|
|
676
|
+
*/
|
|
677
|
+
rotateXW(angle) {
|
|
678
|
+
const c = Math.cos(angle);
|
|
679
|
+
const s = Math.sin(angle);
|
|
680
|
+
const m = this.data;
|
|
681
|
+
|
|
682
|
+
for (let i = 0; i < 4; i++) {
|
|
683
|
+
const a0 = m[i]; // Col 0
|
|
684
|
+
const a3 = m[i + 12]; // Col 3
|
|
685
|
+
m[i] = a0 * c + a3 * s;
|
|
686
|
+
m[i + 12] = -a0 * s + a3 * c;
|
|
687
|
+
}
|
|
688
|
+
return this;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Rotate in YW plane in place
|
|
693
|
+
* @param {number} angle
|
|
694
|
+
* @returns {Mat4x4} this
|
|
695
|
+
*/
|
|
696
|
+
rotateYW(angle) {
|
|
697
|
+
const c = Math.cos(angle);
|
|
698
|
+
const s = Math.sin(angle);
|
|
699
|
+
const m = this.data;
|
|
700
|
+
|
|
701
|
+
for (let i = 0; i < 4; i++) {
|
|
702
|
+
const a1 = m[i + 4]; // Col 1
|
|
703
|
+
const a3 = m[i + 12]; // Col 3
|
|
704
|
+
m[i + 4] = a1 * c + a3 * s;
|
|
705
|
+
m[i + 12] = -a1 * s + a3 * c;
|
|
706
|
+
}
|
|
707
|
+
return this;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Rotate in ZW plane in place
|
|
712
|
+
* @param {number} angle
|
|
713
|
+
* @returns {Mat4x4} this
|
|
714
|
+
*/
|
|
715
|
+
rotateZW(angle) {
|
|
716
|
+
const c = Math.cos(angle);
|
|
717
|
+
const s = Math.sin(angle);
|
|
718
|
+
const m = this.data;
|
|
719
|
+
|
|
720
|
+
for (let i = 0; i < 4; i++) {
|
|
721
|
+
const a2 = m[i + 8]; // Col 2
|
|
722
|
+
const a3 = m[i + 12]; // Col 3
|
|
723
|
+
m[i + 8] = a2 * c + a3 * s;
|
|
724
|
+
m[i + 12] = -a2 * s + a3 * c;
|
|
725
|
+
}
|
|
726
|
+
return this;
|
|
727
|
+
}
|
|
728
|
+
|
|
550
729
|
// ========== ROTATION MATRICES FOR ALL 6 PLANES ==========
|
|
551
730
|
|
|
552
731
|
/**
|
|
553
732
|
* Create XY plane rotation matrix (standard Z-axis rotation in 3D)
|
|
554
733
|
* @param {number} angle - Rotation angle in radians
|
|
734
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
555
735
|
* @returns {Mat4x4}
|
|
556
736
|
*/
|
|
557
|
-
static rotationXY(angle) {
|
|
737
|
+
static rotationXY(angle, target = null) {
|
|
558
738
|
const c = Math.cos(angle);
|
|
559
739
|
const s = Math.sin(angle);
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
0
|
|
565
|
-
|
|
740
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
741
|
+
const r = out.data;
|
|
742
|
+
|
|
743
|
+
if (target) {
|
|
744
|
+
r[0] = c; r[1] = s; r[2] = 0; r[3] = 0;
|
|
745
|
+
r[4] = -s; r[5] = c; r[6] = 0; r[7] = 0;
|
|
746
|
+
r[8] = 0; r[9] = 0; r[10] = 1; r[11] = 0;
|
|
747
|
+
r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1;
|
|
748
|
+
} else {
|
|
749
|
+
r[0] = c; r[1] = s;
|
|
750
|
+
r[4] = -s; r[5] = c;
|
|
751
|
+
r[10] = 1;
|
|
752
|
+
r[15] = 1;
|
|
753
|
+
}
|
|
754
|
+
return out;
|
|
566
755
|
}
|
|
567
756
|
|
|
568
757
|
/**
|
|
569
758
|
* Create XZ plane rotation matrix (standard Y-axis rotation in 3D)
|
|
570
759
|
* @param {number} angle - Rotation angle in radians
|
|
760
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
571
761
|
* @returns {Mat4x4}
|
|
572
762
|
*/
|
|
573
|
-
static rotationXZ(angle) {
|
|
763
|
+
static rotationXZ(angle, target = null) {
|
|
574
764
|
const c = Math.cos(angle);
|
|
575
765
|
const s = Math.sin(angle);
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
0
|
|
581
|
-
|
|
766
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
767
|
+
const r = out.data;
|
|
768
|
+
|
|
769
|
+
if (target) {
|
|
770
|
+
r[0] = c; r[1] = 0; r[2] = -s; r[3] = 0;
|
|
771
|
+
r[4] = 0; r[5] = 1; r[6] = 0; r[7] = 0;
|
|
772
|
+
r[8] = s; r[9] = 0; r[10] = c; r[11] = 0;
|
|
773
|
+
r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1;
|
|
774
|
+
} else {
|
|
775
|
+
r[0] = c; r[2] = -s;
|
|
776
|
+
r[5] = 1;
|
|
777
|
+
r[8] = s; r[10] = c;
|
|
778
|
+
r[15] = 1;
|
|
779
|
+
}
|
|
780
|
+
return out;
|
|
582
781
|
}
|
|
583
782
|
|
|
584
783
|
/**
|
|
585
784
|
* Create YZ plane rotation matrix (standard X-axis rotation in 3D)
|
|
586
785
|
* @param {number} angle - Rotation angle in radians
|
|
786
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
587
787
|
* @returns {Mat4x4}
|
|
588
788
|
*/
|
|
589
|
-
static rotationYZ(angle) {
|
|
789
|
+
static rotationYZ(angle, target = null) {
|
|
590
790
|
const c = Math.cos(angle);
|
|
591
791
|
const s = Math.sin(angle);
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
0
|
|
597
|
-
|
|
792
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
793
|
+
const r = out.data;
|
|
794
|
+
|
|
795
|
+
if (target) {
|
|
796
|
+
r[0] = 1; r[1] = 0; r[2] = 0; r[3] = 0;
|
|
797
|
+
r[4] = 0; r[5] = c; r[6] = s; r[7] = 0;
|
|
798
|
+
r[8] = 0; r[9] = -s; r[10] = c; r[11] = 0;
|
|
799
|
+
r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1;
|
|
800
|
+
} else {
|
|
801
|
+
r[0] = 1;
|
|
802
|
+
r[5] = c; r[6] = s;
|
|
803
|
+
r[9] = -s; r[10] = c;
|
|
804
|
+
r[15] = 1;
|
|
805
|
+
}
|
|
806
|
+
return out;
|
|
598
807
|
}
|
|
599
808
|
|
|
600
809
|
/**
|
|
601
810
|
* Create XW plane rotation matrix (4D hyperspace rotation)
|
|
602
811
|
* Creates "inside-out" effect when w approaches viewer
|
|
603
812
|
* @param {number} angle - Rotation angle in radians
|
|
813
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
604
814
|
* @returns {Mat4x4}
|
|
605
815
|
*/
|
|
606
|
-
static rotationXW(angle) {
|
|
816
|
+
static rotationXW(angle, target = null) {
|
|
607
817
|
const c = Math.cos(angle);
|
|
608
818
|
const s = Math.sin(angle);
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
819
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
820
|
+
const r = out.data;
|
|
821
|
+
|
|
822
|
+
if (target) {
|
|
823
|
+
r[0] = c; r[1] = 0; r[2] = 0; r[3] = s;
|
|
824
|
+
r[4] = 0; r[5] = 1; r[6] = 0; r[7] = 0;
|
|
825
|
+
r[8] = 0; r[9] = 0; r[10] = 1; r[11] = 0;
|
|
826
|
+
r[12] = -s; r[13] = 0; r[14] = 0; r[15] = c;
|
|
827
|
+
} else {
|
|
828
|
+
r[0] = c; r[3] = s;
|
|
829
|
+
r[5] = 1;
|
|
830
|
+
r[10] = 1;
|
|
831
|
+
r[12] = -s; r[15] = c;
|
|
832
|
+
}
|
|
833
|
+
return out;
|
|
615
834
|
}
|
|
616
835
|
|
|
617
836
|
/**
|
|
618
837
|
* Create YW plane rotation matrix (4D hyperspace rotation)
|
|
619
838
|
* @param {number} angle - Rotation angle in radians
|
|
839
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
620
840
|
* @returns {Mat4x4}
|
|
621
841
|
*/
|
|
622
|
-
static rotationYW(angle) {
|
|
842
|
+
static rotationYW(angle, target = null) {
|
|
623
843
|
const c = Math.cos(angle);
|
|
624
844
|
const s = Math.sin(angle);
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
0
|
|
630
|
-
|
|
845
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
846
|
+
const r = out.data;
|
|
847
|
+
|
|
848
|
+
if (target) {
|
|
849
|
+
r[0] = 1; r[1] = 0; r[2] = 0; r[3] = 0;
|
|
850
|
+
r[4] = 0; r[5] = c; r[6] = 0; r[7] = s;
|
|
851
|
+
r[8] = 0; r[9] = 0; r[10] = 1; r[11] = 0;
|
|
852
|
+
r[12] = 0; r[13] = -s; r[14] = 0; r[15] = c;
|
|
853
|
+
} else {
|
|
854
|
+
r[0] = 1;
|
|
855
|
+
r[5] = c; r[7] = s;
|
|
856
|
+
r[10] = 1;
|
|
857
|
+
r[13] = -s; r[15] = c;
|
|
858
|
+
}
|
|
859
|
+
return out;
|
|
631
860
|
}
|
|
632
861
|
|
|
633
862
|
/**
|
|
634
863
|
* Create ZW plane rotation matrix (4D hyperspace rotation)
|
|
635
864
|
* @param {number} angle - Rotation angle in radians
|
|
865
|
+
* @param {Mat4x4} [target=null] - Optional target matrix
|
|
636
866
|
* @returns {Mat4x4}
|
|
637
867
|
*/
|
|
638
|
-
static rotationZW(angle) {
|
|
868
|
+
static rotationZW(angle, target = null) {
|
|
639
869
|
const c = Math.cos(angle);
|
|
640
870
|
const s = Math.sin(angle);
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
0
|
|
646
|
-
|
|
871
|
+
const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
872
|
+
const r = out.data;
|
|
873
|
+
|
|
874
|
+
if (target) {
|
|
875
|
+
r[0] = 1; r[1] = 0; r[2] = 0; r[3] = 0;
|
|
876
|
+
r[4] = 0; r[5] = 1; r[6] = 0; r[7] = 0;
|
|
877
|
+
r[8] = 0; r[9] = 0; r[10] = c; r[11] = s;
|
|
878
|
+
r[12] = 0; r[13] = 0; r[14] = -s; r[15] = c;
|
|
879
|
+
} else {
|
|
880
|
+
r[0] = 1;
|
|
881
|
+
r[5] = 1;
|
|
882
|
+
r[10] = c; r[11] = s;
|
|
883
|
+
r[14] = -s; r[15] = c;
|
|
884
|
+
}
|
|
885
|
+
return out;
|
|
647
886
|
}
|
|
648
887
|
|
|
649
888
|
/**
|
|
@@ -669,24 +908,58 @@ export class Mat4x4 {
|
|
|
669
908
|
* Create combined rotation matrix from all 6 angles
|
|
670
909
|
* Order: XY, XZ, YZ, XW, YW, ZW
|
|
671
910
|
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
* @param {number}
|
|
677
|
-
* @param {number} [
|
|
678
|
-
* @param {number} [
|
|
911
|
+
* Supports two signatures:
|
|
912
|
+
* 1. rotationFromAngles(angles, target?)
|
|
913
|
+
* 2. rotationFromAngles(xy, xz, yz, xw, yw, zw, target?)
|
|
914
|
+
*
|
|
915
|
+
* @param {object|number} anglesOrXY - Rotation angles object OR XY angle
|
|
916
|
+
* @param {number|Mat4x4} [xzOrTarget] - XZ angle OR target matrix
|
|
917
|
+
* @param {number} [yz=0] - YZ angle
|
|
918
|
+
* @param {number} [xw=0] - XW angle
|
|
919
|
+
* @param {number} [yw=0] - YW angle
|
|
920
|
+
* @param {number} [zw=0] - ZW angle
|
|
921
|
+
* @param {Mat4x4} [target=null] - Target matrix (if using 6-arg signature)
|
|
679
922
|
* @returns {Mat4x4}
|
|
680
923
|
*/
|
|
681
|
-
static rotationFromAngles(
|
|
682
|
-
let
|
|
924
|
+
static rotationFromAngles(anglesOrXY, xzOrTarget, yz, xw, yw, zw, target) {
|
|
925
|
+
let xy = 0, xz = 0;
|
|
926
|
+
let _yz = 0, _xw = 0, _yw = 0, _zw = 0;
|
|
927
|
+
let out = null;
|
|
928
|
+
|
|
929
|
+
if (typeof anglesOrXY === 'number') {
|
|
930
|
+
// Signature: (xy, xz, yz, xw, yw, zw, target)
|
|
931
|
+
xy = anglesOrXY;
|
|
932
|
+
xz = typeof xzOrTarget === 'number' ? xzOrTarget : 0;
|
|
933
|
+
_yz = yz || 0;
|
|
934
|
+
_xw = xw || 0;
|
|
935
|
+
_yw = yw || 0;
|
|
936
|
+
_zw = zw || 0;
|
|
937
|
+
out = target || null;
|
|
938
|
+
} else {
|
|
939
|
+
// Signature: (angles, target)
|
|
940
|
+
const angles = anglesOrXY || {};
|
|
941
|
+
xy = angles.xy || 0;
|
|
942
|
+
xz = angles.xz || 0;
|
|
943
|
+
_yz = angles.yz || 0;
|
|
944
|
+
_xw = angles.xw || 0;
|
|
945
|
+
_yw = angles.yw || 0;
|
|
946
|
+
_zw = angles.zw || 0;
|
|
947
|
+
// The second argument is the target in this case
|
|
948
|
+
// Use duck typing or check constructor name to avoid circular dependency issues if any
|
|
949
|
+
if (xzOrTarget && typeof xzOrTarget === 'object' && xzOrTarget.data) {
|
|
950
|
+
out = xzOrTarget;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const result = out || new Mat4x4(); // Default constructor is identity
|
|
955
|
+
if (out) result.identity(); // Reset if reused
|
|
683
956
|
|
|
684
|
-
if (
|
|
685
|
-
if (
|
|
686
|
-
if (
|
|
687
|
-
if (
|
|
688
|
-
if (
|
|
689
|
-
if (
|
|
957
|
+
if (xy) result.rotateXY(xy);
|
|
958
|
+
if (xz) result.rotateXZ(xz);
|
|
959
|
+
if (_yz) result.rotateYZ(_yz);
|
|
960
|
+
if (_xw) result.rotateXW(_xw);
|
|
961
|
+
if (_yw) result.rotateYW(_yw);
|
|
962
|
+
if (_zw) result.rotateZW(_zw);
|
|
690
963
|
|
|
691
964
|
return result;
|
|
692
965
|
}
|
|
@@ -715,12 +988,13 @@ export class Mat4x4 {
|
|
|
715
988
|
* @returns {Mat4x4}
|
|
716
989
|
*/
|
|
717
990
|
static uniformScale(s) {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
]
|
|
991
|
+
const out = new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
992
|
+
const r = out.data;
|
|
993
|
+
r[0] = s;
|
|
994
|
+
r[5] = s;
|
|
995
|
+
r[10] = s;
|
|
996
|
+
r[15] = s;
|
|
997
|
+
return out;
|
|
724
998
|
}
|
|
725
999
|
|
|
726
1000
|
/**
|
|
@@ -732,12 +1006,13 @@ export class Mat4x4 {
|
|
|
732
1006
|
* @returns {Mat4x4}
|
|
733
1007
|
*/
|
|
734
1008
|
static scale(sx, sy, sz, sw = 1) {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
]
|
|
1009
|
+
const out = new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
1010
|
+
const r = out.data;
|
|
1011
|
+
r[0] = sx;
|
|
1012
|
+
r[5] = sy;
|
|
1013
|
+
r[10] = sz;
|
|
1014
|
+
r[15] = sw;
|
|
1015
|
+
return out;
|
|
741
1016
|
}
|
|
742
1017
|
|
|
743
1018
|
/**
|
|
@@ -753,12 +1028,13 @@ export class Mat4x4 {
|
|
|
753
1028
|
static translation(tx, ty, tz, tw = 0) {
|
|
754
1029
|
// For true 4D translation, you need 5D homogeneous coordinates
|
|
755
1030
|
// This is a placeholder that adds the translation to the W column
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
]
|
|
1031
|
+
const out = new Mat4x4(Mat4x4.UNINITIALIZED);
|
|
1032
|
+
const r = out.data;
|
|
1033
|
+
r[0] = 1;
|
|
1034
|
+
r[5] = 1;
|
|
1035
|
+
r[10] = 1;
|
|
1036
|
+
r[12] = tx; r[13] = ty; r[14] = tz; r[15] = 1 + tw;
|
|
1037
|
+
return out;
|
|
762
1038
|
}
|
|
763
1039
|
}
|
|
764
1040
|
|