@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/Projection.js
CHANGED
|
@@ -36,16 +36,28 @@ export class Projection {
|
|
|
36
36
|
*
|
|
37
37
|
* @param {Vec4} v - 4D point
|
|
38
38
|
* @param {number} d - Distance parameter (typically 1.5-5)
|
|
39
|
+
* @param {object} [options] - Projection options
|
|
40
|
+
* @param {Vec4} [target] - Optional target vector to write result to
|
|
39
41
|
* @returns {Vec4} Projected point (w=0)
|
|
40
42
|
*/
|
|
41
|
-
static perspective(v, d = 2, options = {}) {
|
|
43
|
+
static perspective(v, d = 2, options = {}, target = null) {
|
|
42
44
|
if (typeof d === 'object') {
|
|
43
45
|
options = d;
|
|
44
46
|
d = options.d ?? 2;
|
|
45
47
|
}
|
|
46
|
-
|
|
48
|
+
|
|
49
|
+
// Handle options overload or direct target argument
|
|
50
|
+
if (!target && options && options.target) {
|
|
51
|
+
target = options.target;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const epsilon = (options && options.epsilon) ?? DEFAULT_EPSILON;
|
|
47
55
|
const denom = clampDenominator(d - v.w, epsilon);
|
|
48
56
|
const scale = 1 / denom;
|
|
57
|
+
|
|
58
|
+
if (target) {
|
|
59
|
+
return target.set(v.x * scale, v.y * scale, v.z * scale, 0);
|
|
60
|
+
}
|
|
49
61
|
return new Vec4(v.x * scale, v.y * scale, v.z * scale, 0);
|
|
50
62
|
}
|
|
51
63
|
|
|
@@ -60,12 +72,23 @@ export class Projection {
|
|
|
60
72
|
* The projection point is at (0, 0, 0, 1) - the "north pole"
|
|
61
73
|
*
|
|
62
74
|
* @param {Vec4} v - 4D point (ideally on unit hypersphere)
|
|
75
|
+
* @param {object|Vec4} [options] - Projection options or target vector
|
|
76
|
+
* @param {Vec4} [target] - Optional target vector to write result to
|
|
63
77
|
* @returns {Vec4} Projected point (w=0)
|
|
64
78
|
*/
|
|
65
|
-
static stereographic(v, options = {}) {
|
|
66
|
-
|
|
79
|
+
static stereographic(v, options = {}, target = null) {
|
|
80
|
+
if (options instanceof Vec4) {
|
|
81
|
+
target = options;
|
|
82
|
+
options = {};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const epsilon = (options && options.epsilon) ?? DEFAULT_EPSILON;
|
|
67
86
|
const denom = clampDenominator(1 - v.w, epsilon);
|
|
68
87
|
const scale = 1 / denom;
|
|
88
|
+
|
|
89
|
+
if (target) {
|
|
90
|
+
return target.set(v.x * scale, v.y * scale, v.z * scale, 0);
|
|
91
|
+
}
|
|
69
92
|
return new Vec4(v.x * scale, v.y * scale, v.z * scale, 0);
|
|
70
93
|
}
|
|
71
94
|
|
|
@@ -95,9 +118,13 @@ export class Projection {
|
|
|
95
118
|
* Parallel projection - no perspective distortion.
|
|
96
119
|
*
|
|
97
120
|
* @param {Vec4} v - 4D point
|
|
121
|
+
* @param {Vec4} [target] - Optional target vector to write result to
|
|
98
122
|
* @returns {Vec4} Projected point (w=0)
|
|
99
123
|
*/
|
|
100
|
-
static orthographic(v) {
|
|
124
|
+
static orthographic(v, target = null) {
|
|
125
|
+
if (target) {
|
|
126
|
+
return target.set(v.x, v.y, v.z, 0);
|
|
127
|
+
}
|
|
101
128
|
return new Vec4(v.x, v.y, v.z, 0);
|
|
102
129
|
}
|
|
103
130
|
|
|
@@ -126,10 +153,33 @@ export class Projection {
|
|
|
126
153
|
* Project array of Vec4s using perspective projection
|
|
127
154
|
* @param {Vec4[]} vectors
|
|
128
155
|
* @param {number} d
|
|
156
|
+
* @param {object} [options]
|
|
157
|
+
* @param {Vec4[]} [target] - Optional target array to write results to
|
|
129
158
|
* @returns {Vec4[]}
|
|
130
159
|
*/
|
|
131
|
-
static perspectiveArray(vectors, d = 2, options = {}) {
|
|
132
|
-
|
|
160
|
+
static perspectiveArray(vectors, d = 2, options = {}, target = null) {
|
|
161
|
+
// Handle options overload for 'd'
|
|
162
|
+
if (typeof d === 'object') {
|
|
163
|
+
options = d;
|
|
164
|
+
d = options.d ?? 2;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (!target) {
|
|
168
|
+
return vectors.map(v => Projection.perspective(v, d, options));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const count = vectors.length;
|
|
172
|
+
// Iterate and reuse
|
|
173
|
+
for (let i = 0; i < count; i++) {
|
|
174
|
+
const out = target[i];
|
|
175
|
+
if (out) {
|
|
176
|
+
Projection.perspective(vectors[i], d, options, out);
|
|
177
|
+
} else {
|
|
178
|
+
target[i] = Projection.perspective(vectors[i], d, options);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return target;
|
|
133
183
|
}
|
|
134
184
|
|
|
135
185
|
/**
|
package/src/math/Rotor4D.js
CHANGED
|
@@ -276,61 +276,70 @@ export class Rotor4D {
|
|
|
276
276
|
* The result applies this rotation, then r's rotation
|
|
277
277
|
*
|
|
278
278
|
* @param {Rotor4D} r - Right operand
|
|
279
|
+
* @param {Rotor4D} [target=null] - Optional target rotor to write result into
|
|
279
280
|
* @returns {Rotor4D} Composed rotor
|
|
280
281
|
*/
|
|
281
|
-
multiply(r) {
|
|
282
|
+
multiply(r, target = null) {
|
|
282
283
|
// Full geometric product of two rotors in 4D
|
|
283
284
|
// This is derived from the geometric algebra product rules
|
|
284
285
|
|
|
285
286
|
const a = this;
|
|
286
287
|
const b = r;
|
|
287
288
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
a.
|
|
291
|
-
a.xw * b.xw - a.yw * b.yw - a.zw * b.zw - a.xyzw * b.xyzw,
|
|
289
|
+
// Compute all components first to ensure safety if target aliases a or b
|
|
290
|
+
const s = a.s * b.s - a.xy * b.xy - a.xz * b.xz - a.yz * b.yz -
|
|
291
|
+
a.xw * b.xw - a.yw * b.yw - a.zw * b.zw - a.xyzw * b.xyzw;
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
a.
|
|
295
|
-
a.xw * b.yw - a.yw * b.xw - a.zw * b.xyzw - a.xyzw * b.zw,
|
|
293
|
+
const xy = a.s * b.xy + a.xy * b.s + a.xz * b.yz - a.yz * b.xz +
|
|
294
|
+
a.xw * b.yw - a.yw * b.xw - a.zw * b.xyzw - a.xyzw * b.zw;
|
|
296
295
|
|
|
297
|
-
|
|
298
|
-
a.
|
|
299
|
-
a.xw * b.zw + a.yw * b.xyzw - a.zw * b.xw + a.xyzw * b.yw,
|
|
296
|
+
const xz = a.s * b.xz + a.xz * b.s - a.xy * b.yz + a.yz * b.xy +
|
|
297
|
+
a.xw * b.zw + a.yw * b.xyzw - a.zw * b.xw + a.xyzw * b.yw;
|
|
300
298
|
|
|
301
|
-
|
|
302
|
-
a.
|
|
303
|
-
a.xw * b.xyzw + a.yw * b.zw - a.zw * b.yw - a.xyzw * b.xw,
|
|
299
|
+
const yz = a.s * b.yz + a.yz * b.s + a.xy * b.xz - a.xz * b.xy -
|
|
300
|
+
a.xw * b.xyzw + a.yw * b.zw - a.zw * b.yw - a.xyzw * b.xw;
|
|
304
301
|
|
|
305
|
-
|
|
306
|
-
a.
|
|
307
|
-
a.yz * b.xyzw + a.yw * b.xy - a.zw * b.xz + a.xyzw * b.yz,
|
|
302
|
+
const xw = a.s * b.xw + a.xw * b.s - a.xy * b.yw + a.xz * b.zw +
|
|
303
|
+
a.yz * b.xyzw + a.yw * b.xy - a.zw * b.xz + a.xyzw * b.yz;
|
|
308
304
|
|
|
309
|
-
|
|
310
|
-
a.
|
|
311
|
-
a.yz * b.zw - a.xw * b.xy + a.zw * b.yz - a.xyzw * b.xz,
|
|
305
|
+
const yw = a.s * b.yw + a.yw * b.s + a.xy * b.xw - a.xz * b.xyzw -
|
|
306
|
+
a.yz * b.zw - a.xw * b.xy + a.zw * b.yz - a.xyzw * b.xz;
|
|
312
307
|
|
|
313
|
-
|
|
314
|
-
a.
|
|
315
|
-
a.yz * b.yw - a.xw * b.xz - a.yw * b.yz + a.xyzw * b.xy,
|
|
308
|
+
const zw = a.s * b.zw + a.zw * b.s + a.xy * b.xyzw + a.xz * b.xw +
|
|
309
|
+
a.yz * b.yw - a.xw * b.xz - a.yw * b.yz + a.xyzw * b.xy;
|
|
316
310
|
|
|
317
|
-
|
|
318
|
-
a.
|
|
319
|
-
|
|
320
|
-
)
|
|
311
|
+
const xyzw = a.s * b.xyzw + a.xyzw * b.s + a.xy * b.zw - a.xz * b.yw +
|
|
312
|
+
a.yz * b.xw + a.xw * b.yz - a.yw * b.xz + a.zw * b.xy;
|
|
313
|
+
|
|
314
|
+
if (target) {
|
|
315
|
+
target.s = s;
|
|
316
|
+
target.xy = xy;
|
|
317
|
+
target.xz = xz;
|
|
318
|
+
target.yz = yz;
|
|
319
|
+
target.xw = xw;
|
|
320
|
+
target.yw = yw;
|
|
321
|
+
target.zw = zw;
|
|
322
|
+
target.xyzw = xyzw;
|
|
323
|
+
return target;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return new Rotor4D(s, xy, xz, yz, xw, yw, zw, xyzw);
|
|
321
327
|
}
|
|
322
328
|
|
|
323
329
|
/**
|
|
324
330
|
* Rotate a 4D vector using sandwich product: v' = R v R†
|
|
325
331
|
*
|
|
332
|
+
* Matrix math is inlined to avoid allocating a temporary Float32Array(16).
|
|
333
|
+
* Pass an optional target Vec4 to eliminate all allocations.
|
|
334
|
+
*
|
|
326
335
|
* @param {Vec4} v - Vector to rotate
|
|
327
|
-
* @param {Vec4} [target] - Optional
|
|
328
|
-
* @returns {Vec4} Rotated vector
|
|
336
|
+
* @param {Vec4} [target] - Optional pre-allocated Vec4 to write result into
|
|
337
|
+
* @returns {Vec4} Rotated vector (target if provided, otherwise new Vec4)
|
|
329
338
|
*/
|
|
330
339
|
rotate(v, target) {
|
|
331
|
-
|
|
340
|
+
const x = v.x, y = v.y, z = v.z, w = v.w;
|
|
332
341
|
|
|
333
|
-
// Normalize
|
|
342
|
+
// Normalize for numerical stability (same as toMatrix)
|
|
334
343
|
const n = this.norm();
|
|
335
344
|
const invN = n > 1e-10 ? 1 / n : 1;
|
|
336
345
|
|
|
@@ -343,7 +352,7 @@ export class Rotor4D {
|
|
|
343
352
|
const zw = this.zw * invN;
|
|
344
353
|
const xyzw = this.xyzw * invN;
|
|
345
354
|
|
|
346
|
-
//
|
|
355
|
+
// Squared terms
|
|
347
356
|
const s2 = s * s;
|
|
348
357
|
const xy2 = xy * xy;
|
|
349
358
|
const xz2 = xz * xz;
|
|
@@ -353,22 +362,20 @@ export class Rotor4D {
|
|
|
353
362
|
const zw2 = zw * zw;
|
|
354
363
|
const xyzw2 = xyzw * xyzw;
|
|
355
364
|
|
|
356
|
-
// Cross terms
|
|
365
|
+
// Cross terms (pre-multiplied by 2)
|
|
357
366
|
const sxy = 2 * s * xy;
|
|
358
367
|
const sxz = 2 * s * xz;
|
|
359
368
|
const syz = 2 * s * yz;
|
|
360
369
|
const sxw = 2 * s * xw;
|
|
361
370
|
const syw = 2 * s * yw;
|
|
362
371
|
const szw = 2 * s * zw;
|
|
363
|
-
// const sxyzw = 2 * s * xyzw; // Unused in rotation matrix
|
|
364
372
|
|
|
365
|
-
const
|
|
373
|
+
const xzyz = 2 * xz * yz;
|
|
366
374
|
const xyyz = 2 * xy * yz;
|
|
375
|
+
const xyxz = 2 * xy * xz;
|
|
367
376
|
const xyxw = 2 * xy * xw;
|
|
368
377
|
const xyyw = 2 * xy * yw;
|
|
369
|
-
// const xyzw_c = 2 * xy * zw; // Unused in rotation matrix
|
|
370
378
|
|
|
371
|
-
const xzyz = 2 * xz * yz;
|
|
372
379
|
const xzxw = 2 * xz * xw;
|
|
373
380
|
const xzyw = 2 * xz * yw;
|
|
374
381
|
const xzzw = 2 * xz * zw;
|
|
@@ -388,40 +395,33 @@ export class Rotor4D {
|
|
|
388
395
|
const ywxyzw = 2 * yw * xyzw;
|
|
389
396
|
const zwxyzw = 2 * zw * xyzw;
|
|
390
397
|
|
|
391
|
-
//
|
|
392
|
-
//
|
|
393
|
-
const
|
|
394
|
-
const
|
|
395
|
-
const
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const
|
|
400
|
-
const
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
const
|
|
417
|
-
const
|
|
418
|
-
const z = v.z;
|
|
419
|
-
const w = v.w;
|
|
420
|
-
|
|
421
|
-
const rx = m00 * x + m10 * y + m20 * z + m30 * w;
|
|
422
|
-
const ry = m01 * x + m11 * y + m21 * z + m31 * w;
|
|
423
|
-
const rz = m02 * x + m12 * y + m22 * z + m32 * w;
|
|
424
|
-
const rw = m03 * x + m13 * y + m23 * z + m33 * w;
|
|
398
|
+
// Column-major 4x4 rotation matrix entries (inlined from toMatrix)
|
|
399
|
+
// Column 0
|
|
400
|
+
const m0 = s2 - xy2 - xz2 + yz2 - xw2 + yw2 + zw2 - xyzw2;
|
|
401
|
+
const m1 = sxy + xzyz + xwyw - zwxyzw;
|
|
402
|
+
const m2 = sxz - xyyz + xwzw + ywxyzw;
|
|
403
|
+
const m3 = sxw - xyyw - xzzw - yzxyzw;
|
|
404
|
+
// Column 1
|
|
405
|
+
const m4 = -sxy + xzyz + xwyw + zwxyzw;
|
|
406
|
+
const m5 = s2 - xy2 + xz2 - yz2 + xw2 - yw2 + zw2 - xyzw2;
|
|
407
|
+
const m6 = syz + xyxz + ywzw - xwxyzw;
|
|
408
|
+
const m7 = syw + xyxw - yzzw + xzxyzw;
|
|
409
|
+
// Column 2
|
|
410
|
+
const m8 = -sxz - xyyz + xwzw - ywxyzw;
|
|
411
|
+
const m9 = -syz + xyxz + ywzw + xwxyzw;
|
|
412
|
+
const m10 = s2 + xy2 - xz2 - yz2 + xw2 + yw2 - zw2 - xyzw2;
|
|
413
|
+
const m11 = szw + xzxw + yzyw - xyxyzw;
|
|
414
|
+
// Column 3
|
|
415
|
+
const m12 = -sxw - xyyw - xzzw + yzxyzw;
|
|
416
|
+
const m13 = -syw + xyxw - yzzw - xzxyzw;
|
|
417
|
+
const m14 = -szw + xzxw + yzyw + xyxyzw;
|
|
418
|
+
const m15 = s2 + xy2 + xz2 + yz2 - xw2 - yw2 - zw2 - xyzw2;
|
|
419
|
+
|
|
420
|
+
// Matrix-vector multiply
|
|
421
|
+
const rx = m0 * x + m4 * y + m8 * z + m12 * w;
|
|
422
|
+
const ry = m1 * x + m5 * y + m9 * z + m13 * w;
|
|
423
|
+
const rz = m2 * x + m6 * y + m10 * z + m14 * w;
|
|
424
|
+
const rw = m3 * x + m7 * y + m11 * z + m15 * w;
|
|
425
425
|
|
|
426
426
|
if (target) {
|
|
427
427
|
target.x = rx;
|
|
@@ -430,15 +430,15 @@ export class Rotor4D {
|
|
|
430
430
|
target.w = rw;
|
|
431
431
|
return target;
|
|
432
432
|
}
|
|
433
|
-
|
|
434
433
|
return new Vec4(rx, ry, rz, rw);
|
|
435
434
|
}
|
|
436
435
|
|
|
437
436
|
/**
|
|
438
437
|
* Convert rotor to 4x4 rotation matrix (column-major for WebGL)
|
|
438
|
+
* @param {Float32Array|Array} [target] - Optional target array to write into
|
|
439
439
|
* @returns {Float32Array} 16-element array in column-major order
|
|
440
440
|
*/
|
|
441
|
-
toMatrix() {
|
|
441
|
+
toMatrix(target = null) {
|
|
442
442
|
// Normalize first for numerical stability
|
|
443
443
|
const n = this.norm();
|
|
444
444
|
const invN = n > 1e-10 ? 1 / n : 1;
|
|
@@ -502,6 +502,35 @@ export class Rotor4D {
|
|
|
502
502
|
// Formula derived from sandwich product R v R†
|
|
503
503
|
// Diagonal: s² minus bivectors containing that axis, plus others
|
|
504
504
|
// Off-diagonal: 2*s*bivector terms for single-plane contributions
|
|
505
|
+
|
|
506
|
+
if (target) {
|
|
507
|
+
// Column 0 (transformed X axis)
|
|
508
|
+
target[0] = s2 - xy2 - xz2 + yz2 - xw2 + yw2 + zw2 - xyzw2;
|
|
509
|
+
target[1] = sxy + xzyz + xwyw - zwxyzw;
|
|
510
|
+
target[2] = sxz - xyyz + xwzw + ywxyzw;
|
|
511
|
+
target[3] = sxw - xyyw - xzzw - yzxyzw;
|
|
512
|
+
|
|
513
|
+
// Column 1 (transformed Y axis)
|
|
514
|
+
target[4] = -sxy + xzyz + xwyw + zwxyzw;
|
|
515
|
+
target[5] = s2 - xy2 + xz2 - yz2 + xw2 - yw2 + zw2 - xyzw2;
|
|
516
|
+
target[6] = syz + xyxz + ywzw - xwxyzw;
|
|
517
|
+
target[7] = syw + xyxw - yzzw + xzxyzw;
|
|
518
|
+
|
|
519
|
+
// Column 2 (transformed Z axis)
|
|
520
|
+
target[8] = -sxz - xyyz + xwzw - ywxyzw;
|
|
521
|
+
target[9] = -syz + xyxz + ywzw + xwxyzw;
|
|
522
|
+
target[10] = s2 + xy2 - xz2 - yz2 + xw2 + yw2 - zw2 - xyzw2;
|
|
523
|
+
target[11] = szw + xzxw + yzyw - xyxyzw;
|
|
524
|
+
|
|
525
|
+
// Column 3 (transformed W axis)
|
|
526
|
+
target[12] = -sxw - xyyw - xzzw + yzxyzw;
|
|
527
|
+
target[13] = -syw + xyxw - yzzw - xzxyzw;
|
|
528
|
+
target[14] = -szw + xzxw + yzyw + xyxyzw;
|
|
529
|
+
target[15] = s2 + xy2 + xz2 + yz2 - xw2 - yw2 - zw2 - xyzw2;
|
|
530
|
+
|
|
531
|
+
return target;
|
|
532
|
+
}
|
|
533
|
+
|
|
505
534
|
return new Float32Array([
|
|
506
535
|
// Column 0 (transformed X axis)
|
|
507
536
|
s2 - xy2 - xz2 + yz2 - xw2 + yw2 + zw2 - xyzw2,
|