@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.
Files changed (80) hide show
  1. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +2 -0
  2. package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
  3. package/DOCS/ARCHITECTURE.md +1 -0
  4. package/DOCS/CI_TESTING.md +2 -0
  5. package/DOCS/CLI_ONBOARDING.md +2 -0
  6. package/DOCS/CONTROL_REFERENCE.md +2 -0
  7. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +2 -0
  8. package/DOCS/ENV_SETUP.md +2 -0
  9. package/DOCS/EPIC_SCROLL_EVENTS.md +2 -0
  10. package/DOCS/EXPANSION_DESIGN.md +979 -0
  11. package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
  12. package/DOCS/EXPORT_FORMATS.md +2 -0
  13. package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
  14. package/DOCS/HANDOFF_LANDING_PAGE.md +2 -0
  15. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +2 -0
  16. package/DOCS/LICENSING_TIERS.md +2 -0
  17. package/DOCS/MASTER_PLAN_2026-01-31.md +2 -0
  18. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +3 -1
  19. package/DOCS/OBS_SETUP_GUIDE.md +2 -0
  20. package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
  21. package/DOCS/PRODUCT_STRATEGY.md +2 -0
  22. package/DOCS/PROJECT_SETUP.md +2 -0
  23. package/DOCS/README.md +5 -3
  24. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +2 -0
  25. package/DOCS/RENDERER_LIFECYCLE.md +2 -0
  26. package/DOCS/REPO_MANIFEST.md +2 -0
  27. package/DOCS/ROADMAP.md +2 -0
  28. package/DOCS/SCROLL_TIMELINE_v3.md +2 -0
  29. package/DOCS/SITE_REFACTOR_PLAN.md +2 -0
  30. package/DOCS/STATUS.md +2 -0
  31. package/DOCS/SYSTEM_INVENTORY.md +2 -0
  32. package/DOCS/TELEMETRY_EXPORTS.md +2 -0
  33. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +2 -0
  34. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +2 -0
  35. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +2 -0
  36. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +2 -0
  37. package/DOCS/WEBGPU_STATUS.md +2 -0
  38. package/DOCS/XR_BENCHMARKS.md +2 -0
  39. package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -34
  40. package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -80
  41. package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -42
  42. package/DOCS/archive/SESSION_014_PLAN.md +1 -195
  43. package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -56
  44. package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -72
  45. package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -741
  46. package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -38
  47. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-01-31.md +2 -0
  48. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +2 -0
  49. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +2 -0
  50. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +2 -0
  51. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +2 -0
  52. package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
  53. package/DOCS/dev-tracks/README.md +2 -0
  54. package/package.json +2 -4
  55. package/src/cli/index.js +59 -5
  56. package/src/experimental/GameLoop.js +72 -0
  57. package/src/experimental/LatticePhysics.js +100 -0
  58. package/src/experimental/LiveDirector.js +143 -0
  59. package/src/experimental/PlayerController4D.js +154 -0
  60. package/src/experimental/VIB3Actor.js +138 -0
  61. package/src/experimental/VIB3Compositor.js +117 -0
  62. package/src/experimental/VIB3Link.js +122 -0
  63. package/src/experimental/VIB3Orchestrator.js +146 -0
  64. package/src/experimental/VIB3Universe.js +109 -0
  65. package/src/experimental/demos/CrystalLabyrinth.js +202 -0
  66. package/src/export/SVGExporter.js +9 -5
  67. package/src/features/CollectionManager.js +27 -9
  68. package/src/gallery/CollectionManager.js +27 -9
  69. package/src/geometry/generators/Crystal.js +2 -2
  70. package/src/geometry/warp/HypersphereCore.js +53 -24
  71. package/src/math/Mat4x4.js +418 -142
  72. package/src/math/Projection.js +57 -7
  73. package/src/math/Rotor4D.js +102 -73
  74. package/src/math/Vec4.js +265 -111
  75. package/src/quantum/QuantumVisualizer.js +28 -0
  76. package/src/scene/Node4D.js +74 -24
  77. package/src/testing/ProjectionClass.test.js +38 -0
  78. package/src/variations/VariationManager.js +6 -1
  79. package/src/wasm/WasmLoader.js +11 -6
  80. package/tools/update_projection.py +109 -0
package/src/math/Vec4.js CHANGED
@@ -2,7 +2,8 @@
2
2
  * Vec4 - 4D Vector Class
3
3
  *
4
4
  * Represents a point or direction in 4-dimensional space.
5
- * Uses Float32Array for GPU compatibility and potential SIMD optimization.
5
+ * Uses plain numeric properties internally for minimal allocation overhead.
6
+ * GPU-compatible Float32Array created on demand via toFloat32Array().
6
7
  *
7
8
  * @example
8
9
  * const v = new Vec4(1, 2, 3, 0.5);
@@ -19,26 +20,66 @@ export class Vec4 {
19
20
  * @param {number} w - W component (4th dimension)
20
21
  */
21
22
  constructor(x = 0, y = 0, z = 0, w = 0) {
22
- // Use Float32Array for GPU compatibility
23
- this.data = new Float32Array(4);
24
- this.data[0] = x;
25
- this.data[1] = y;
26
- this.data[2] = z;
27
- this.data[3] = w;
23
+ this._x = x;
24
+ this._y = y;
25
+ this._z = z;
26
+ this._w = w;
28
27
  }
29
28
 
30
- // Property accessors for readability
31
- get x() { return this.data[0]; }
32
- set x(v) { this.data[0] = v; }
29
+ // Property accessors
30
+ get x() { return this._x; }
31
+ set x(v) { this._x = v; }
33
32
 
34
- get y() { return this.data[1]; }
35
- set y(v) { this.data[1] = v; }
33
+ get y() { return this._y; }
34
+ set y(v) { this._y = v; }
36
35
 
37
- get z() { return this.data[2]; }
38
- set z(v) { this.data[2] = v; }
36
+ get z() { return this._z; }
37
+ set z(v) { this._z = v; }
39
38
 
40
- get w() { return this.data[3]; }
41
- set w(v) { this.data[3] = v; }
39
+ get w() { return this._w; }
40
+ set w(v) { this._w = v; }
41
+
42
+ /**
43
+ * Backward-compatible .data getter.
44
+ * Returns a Float32Array snapshot of current values.
45
+ * Note: writes to the returned array do NOT propagate back.
46
+ * Use setComponent(index, value) for index-based mutation.
47
+ * @returns {Float32Array}
48
+ */
49
+ get data() {
50
+ return new Float32Array([this._x, this._y, this._z, this._w]);
51
+ }
52
+
53
+ /**
54
+ * Set a component by index (0=x, 1=y, 2=z, 3=w)
55
+ * @param {number} index - Component index (0-3)
56
+ * @param {number} value - New value
57
+ * @returns {Vec4} this
58
+ */
59
+ setComponent(index, value) {
60
+ switch (index) {
61
+ case 0: this._x = value; break;
62
+ case 1: this._y = value; break;
63
+ case 2: this._z = value; break;
64
+ case 3: this._w = value; break;
65
+ }
66
+ return this;
67
+ }
68
+
69
+ /**
70
+ * Get a component by index (0=x, 1=y, 2=z, 3=w)
71
+ * @param {number} index - Component index (0-3)
72
+ * @returns {number}
73
+ */
74
+ getComponent(index) {
75
+ switch (index) {
76
+ case 0: return this._x;
77
+ case 1: return this._y;
78
+ case 2: return this._z;
79
+ case 3: return this._w;
80
+ default: return 0;
81
+ }
82
+ }
42
83
 
43
84
  /**
44
85
  * Create a Vec4 from an array
@@ -54,7 +95,7 @@ export class Vec4 {
54
95
  * @returns {Vec4}
55
96
  */
56
97
  clone() {
57
- return new Vec4(this.x, this.y, this.z, this.w);
98
+ return new Vec4(this._x, this._y, this._z, this._w);
58
99
  }
59
100
 
60
101
  /**
@@ -63,10 +104,10 @@ export class Vec4 {
63
104
  * @returns {Vec4} this (for chaining)
64
105
  */
65
106
  copy(v) {
66
- this.data[0] = v.data[0];
67
- this.data[1] = v.data[1];
68
- this.data[2] = v.data[2];
69
- this.data[3] = v.data[3];
107
+ this._x = v._x;
108
+ this._y = v._y;
109
+ this._z = v._z;
110
+ this._w = v._w;
70
111
  return this;
71
112
  }
72
113
 
@@ -79,24 +120,32 @@ export class Vec4 {
79
120
  * @returns {Vec4} this
80
121
  */
81
122
  set(x, y, z, w) {
82
- this.data[0] = x;
83
- this.data[1] = y;
84
- this.data[2] = z;
85
- this.data[3] = w;
123
+ this._x = x;
124
+ this._y = y;
125
+ this._z = z;
126
+ this._w = w;
86
127
  return this;
87
128
  }
88
129
 
89
130
  /**
90
- * Add another vector (immutable)
131
+ * Add another vector (immutable unless target provided)
91
132
  * @param {Vec4} v
92
- * @returns {Vec4} New vector
93
- */
94
- add(v) {
133
+ * @param {Vec4} [target=null] - Optional target vector
134
+ * @returns {Vec4} New vector or target
135
+ */
136
+ add(v, target = null) {
137
+ if (target) {
138
+ target._x = this._x + v._x;
139
+ target._y = this._y + v._y;
140
+ target._z = this._z + v._z;
141
+ target._w = this._w + v._w;
142
+ return target;
143
+ }
95
144
  return new Vec4(
96
- this.x + v.x,
97
- this.y + v.y,
98
- this.z + v.z,
99
- this.w + v.w
145
+ this._x + v._x,
146
+ this._y + v._y,
147
+ this._z + v._z,
148
+ this._w + v._w
100
149
  );
101
150
  }
102
151
 
@@ -106,24 +155,32 @@ export class Vec4 {
106
155
  * @returns {Vec4} this
107
156
  */
108
157
  addInPlace(v) {
109
- this.data[0] += v.data[0];
110
- this.data[1] += v.data[1];
111
- this.data[2] += v.data[2];
112
- this.data[3] += v.data[3];
158
+ this._x += v._x;
159
+ this._y += v._y;
160
+ this._z += v._z;
161
+ this._w += v._w;
113
162
  return this;
114
163
  }
115
164
 
116
165
  /**
117
- * Subtract another vector (immutable)
166
+ * Subtract another vector (immutable unless target provided)
118
167
  * @param {Vec4} v
119
- * @returns {Vec4} New vector
120
- */
121
- sub(v) {
168
+ * @param {Vec4} [target=null] - Optional target vector
169
+ * @returns {Vec4} New vector or target
170
+ */
171
+ sub(v, target = null) {
172
+ if (target) {
173
+ target._x = this._x - v._x;
174
+ target._y = this._y - v._y;
175
+ target._z = this._z - v._z;
176
+ target._w = this._w - v._w;
177
+ return target;
178
+ }
122
179
  return new Vec4(
123
- this.x - v.x,
124
- this.y - v.y,
125
- this.z - v.z,
126
- this.w - v.w
180
+ this._x - v._x,
181
+ this._y - v._y,
182
+ this._z - v._z,
183
+ this._w - v._w
127
184
  );
128
185
  }
129
186
 
@@ -133,24 +190,32 @@ export class Vec4 {
133
190
  * @returns {Vec4} this
134
191
  */
135
192
  subInPlace(v) {
136
- this.data[0] -= v.data[0];
137
- this.data[1] -= v.data[1];
138
- this.data[2] -= v.data[2];
139
- this.data[3] -= v.data[3];
193
+ this._x -= v._x;
194
+ this._y -= v._y;
195
+ this._z -= v._z;
196
+ this._w -= v._w;
140
197
  return this;
141
198
  }
142
199
 
143
200
  /**
144
- * Multiply by scalar (immutable)
201
+ * Multiply by scalar (immutable unless target provided)
145
202
  * @param {number} s
146
- * @returns {Vec4} New vector
147
- */
148
- scale(s) {
203
+ * @param {Vec4} [target=null] - Optional target vector
204
+ * @returns {Vec4} New vector or target
205
+ */
206
+ scale(s, target = null) {
207
+ if (target) {
208
+ target._x = this._x * s;
209
+ target._y = this._y * s;
210
+ target._z = this._z * s;
211
+ target._w = this._w * s;
212
+ return target;
213
+ }
149
214
  return new Vec4(
150
- this.x * s,
151
- this.y * s,
152
- this.z * s,
153
- this.w * s
215
+ this._x * s,
216
+ this._y * s,
217
+ this._z * s,
218
+ this._w * s
154
219
  );
155
220
  }
156
221
 
@@ -160,33 +225,49 @@ export class Vec4 {
160
225
  * @returns {Vec4} this
161
226
  */
162
227
  scaleInPlace(s) {
163
- this.data[0] *= s;
164
- this.data[1] *= s;
165
- this.data[2] *= s;
166
- this.data[3] *= s;
228
+ this._x *= s;
229
+ this._y *= s;
230
+ this._z *= s;
231
+ this._w *= s;
167
232
  return this;
168
233
  }
169
234
 
170
235
  /**
171
236
  * Component-wise multiply (Hadamard product)
172
237
  * @param {Vec4} v
173
- * @returns {Vec4} New vector
174
- */
175
- multiply(v) {
238
+ * @param {Vec4} [target=null] - Optional target vector
239
+ * @returns {Vec4} New vector or target
240
+ */
241
+ multiply(v, target = null) {
242
+ if (target) {
243
+ target._x = this._x * v._x;
244
+ target._y = this._y * v._y;
245
+ target._z = this._z * v._z;
246
+ target._w = this._w * v._w;
247
+ return target;
248
+ }
176
249
  return new Vec4(
177
- this.x * v.x,
178
- this.y * v.y,
179
- this.z * v.z,
180
- this.w * v.w
250
+ this._x * v._x,
251
+ this._y * v._y,
252
+ this._z * v._z,
253
+ this._w * v._w
181
254
  );
182
255
  }
183
256
 
184
257
  /**
185
- * Negate vector (immutable)
186
- * @returns {Vec4} New vector
258
+ * Negate vector (immutable unless target provided)
259
+ * @param {Vec4} [target=null] - Optional target vector
260
+ * @returns {Vec4} New vector or target
187
261
  */
188
- negate() {
189
- return new Vec4(-this.x, -this.y, -this.z, -this.w);
262
+ negate(target = null) {
263
+ if (target) {
264
+ target._x = -this._x;
265
+ target._y = -this._y;
266
+ target._z = -this._z;
267
+ target._w = -this._w;
268
+ return target;
269
+ }
270
+ return new Vec4(-this._x, -this._y, -this._z, -this._w);
190
271
  }
191
272
 
192
273
  /**
@@ -194,10 +275,10 @@ export class Vec4 {
194
275
  * @returns {Vec4} this
195
276
  */
196
277
  negateInPlace() {
197
- this.data[0] = -this.data[0];
198
- this.data[1] = -this.data[1];
199
- this.data[2] = -this.data[2];
200
- this.data[3] = -this.data[3];
278
+ this._x = -this._x;
279
+ this._y = -this._y;
280
+ this._z = -this._z;
281
+ this._w = -this._w;
201
282
  return this;
202
283
  }
203
284
 
@@ -207,7 +288,7 @@ export class Vec4 {
207
288
  * @returns {number}
208
289
  */
209
290
  dot(v) {
210
- return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
291
+ return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
211
292
  }
212
293
 
213
294
  /**
@@ -215,7 +296,7 @@ export class Vec4 {
215
296
  * @returns {number}
216
297
  */
217
298
  lengthSquared() {
218
- return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
299
+ return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
219
300
  }
220
301
 
221
302
  /**
@@ -232,7 +313,11 @@ export class Vec4 {
232
313
  * @returns {number}
233
314
  */
234
315
  distanceTo(v) {
235
- return this.sub(v).length();
316
+ const dx = this._x - v._x;
317
+ const dy = this._y - v._y;
318
+ const dz = this._z - v._z;
319
+ const dw = this._w - v._w;
320
+ return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
236
321
  }
237
322
 
238
323
  /**
@@ -241,19 +326,31 @@ export class Vec4 {
241
326
  * @returns {number}
242
327
  */
243
328
  distanceToSquared(v) {
244
- return this.sub(v).lengthSquared();
329
+ const dx = this._x - v._x;
330
+ const dy = this._y - v._y;
331
+ const dz = this._z - v._z;
332
+ const dw = this._w - v._w;
333
+ return dx * dx + dy * dy + dz * dz + dw * dw;
245
334
  }
246
335
 
247
336
  /**
248
- * Normalize to unit length (immutable)
249
- * @returns {Vec4} New normalized vector
337
+ * Normalize to unit length (immutable unless target provided)
338
+ * @param {Vec4} [target=null] - Optional target vector
339
+ * @returns {Vec4} New normalized vector or target
250
340
  */
251
- normalize() {
341
+ normalize(target = null) {
252
342
  const len = this.length();
253
343
  if (len < 1e-10) {
344
+ if (target) {
345
+ target._x = 0;
346
+ target._y = 0;
347
+ target._z = 0;
348
+ target._w = 0;
349
+ return target;
350
+ }
254
351
  return new Vec4(0, 0, 0, 0);
255
352
  }
256
- return this.scale(1 / len);
353
+ return this.scale(1 / len, target);
257
354
  }
258
355
 
259
356
  /**
@@ -273,14 +370,22 @@ export class Vec4 {
273
370
  * Linear interpolation to another vector
274
371
  * @param {Vec4} v - Target vector
275
372
  * @param {number} t - Interpolation factor (0-1)
276
- * @returns {Vec4} New interpolated vector
277
- */
278
- lerp(v, t) {
373
+ * @param {Vec4} [target=null] - Optional target vector
374
+ * @returns {Vec4} New interpolated vector or target
375
+ */
376
+ lerp(v, t, target = null) {
377
+ if (target) {
378
+ target._x = this._x + (v._x - this._x) * t;
379
+ target._y = this._y + (v._y - this._y) * t;
380
+ target._z = this._z + (v._z - this._z) * t;
381
+ target._w = this._w + (v._w - this._w) * t;
382
+ return target;
383
+ }
279
384
  return new Vec4(
280
- this.x + (v.x - this.x) * t,
281
- this.y + (v.y - this.y) * t,
282
- this.z + (v.z - this.z) * t,
283
- this.w + (v.w - this.w) * t
385
+ this._x + (v._x - this._x) * t,
386
+ this._y + (v._y - this._y) * t,
387
+ this._z + (v._z - this._z) * t,
388
+ this._w + (v._w - this._w) * t
284
389
  );
285
390
  }
286
391
 
@@ -292,10 +397,10 @@ export class Vec4 {
292
397
  */
293
398
  equals(v, epsilon = 1e-6) {
294
399
  return (
295
- Math.abs(this.x - v.x) < epsilon &&
296
- Math.abs(this.y - v.y) < epsilon &&
297
- Math.abs(this.z - v.z) < epsilon &&
298
- Math.abs(this.w - v.w) < epsilon
400
+ Math.abs(this._x - v._x) < epsilon &&
401
+ Math.abs(this._y - v._y) < epsilon &&
402
+ Math.abs(this._z - v._z) < epsilon &&
403
+ Math.abs(this._w - v._w) < epsilon
299
404
  );
300
405
  }
301
406
 
@@ -311,43 +416,92 @@ export class Vec4 {
311
416
  /**
312
417
  * Project 4D point to 3D using perspective projection
313
418
  * Projects from 4D to 3D by dividing by (d - w)
314
- * @param {number} d - Distance parameter (usually 2-5)
315
- * @param {object} [options] - Projection options (epsilon, distance)
419
+ * @param {number|object} d - Distance parameter (usually 2-5) or options object
420
+ * @param {object|Vec4} [options] - Projection options or target vector
421
+ * @param {Vec4} [target] - Target vector to store result
316
422
  * @returns {Vec4} Projected point (w component is 0)
317
423
  */
318
- projectPerspective(d = 2, options = {}) {
424
+ projectPerspective(d = 2, options = {}, target = null) {
319
425
  if (typeof d === 'object') {
426
+ // usage: projectPerspective({ distance: 2, ... }, target?)
427
+ if (options instanceof Vec4) {
428
+ target = options;
429
+ }
320
430
  options = d;
321
431
  d = options.distance ?? options.d ?? 2;
432
+ } else {
433
+ // usage: projectPerspective(d, options?, target?)
434
+ // usage: projectPerspective(d, target?)
435
+ if (options instanceof Vec4) {
436
+ target = options;
437
+ options = {};
438
+ }
322
439
  }
440
+
441
+ options = options || {};
442
+
323
443
  const epsilon = options.epsilon ?? 1e-5;
324
- const denom = d - this.w;
444
+ const denom = d - this._w;
325
445
  const clamped = Math.abs(denom) < epsilon ? (denom >= 0 ? epsilon : -epsilon) : denom;
326
446
  const scale = 1 / clamped;
327
- return new Vec4(this.x * scale, this.y * scale, this.z * scale, 0);
447
+
448
+ if (target) {
449
+ target._x = this._x * scale;
450
+ target._y = this._y * scale;
451
+ target._z = this._z * scale;
452
+ target._w = 0;
453
+ return target;
454
+ }
455
+
456
+ return new Vec4(this._x * scale, this._y * scale, this._z * scale, 0);
328
457
  }
329
458
 
330
459
  /**
331
460
  * Project 4D point to 3D using stereographic projection
332
461
  * Maps 4D hypersphere to 3D space
333
- * @param {object} [options] - Projection options (epsilon)
462
+ * @param {object|Vec4} [options] - Projection options or target vector
463
+ * @param {Vec4} [target] - Target vector to store result
334
464
  * @returns {Vec4} Projected point (w component is 0)
335
465
  */
336
- projectStereographic(options = {}) {
466
+ projectStereographic(options = {}, target = null) {
467
+ if (options instanceof Vec4) {
468
+ target = options;
469
+ options = {};
470
+ }
471
+
472
+ options = options || {};
473
+
337
474
  const epsilon = options.epsilon ?? 1e-5;
338
- const denom = 1 - this.w;
475
+ const denom = 1 - this._w;
339
476
  const clamped = Math.abs(denom) < epsilon ? (denom >= 0 ? epsilon : -epsilon) : denom;
340
477
  const scale = 1 / clamped;
341
- return new Vec4(this.x * scale, this.y * scale, this.z * scale, 0);
478
+
479
+ if (target) {
480
+ target._x = this._x * scale;
481
+ target._y = this._y * scale;
482
+ target._z = this._z * scale;
483
+ target._w = 0;
484
+ return target;
485
+ }
486
+
487
+ return new Vec4(this._x * scale, this._y * scale, this._z * scale, 0);
342
488
  }
343
489
 
344
490
  /**
345
491
  * Project 4D point to 3D using orthographic projection
346
492
  * Simply drops the W component
493
+ * @param {Vec4} [target=null] - Optional target vector
347
494
  * @returns {Vec4} Projected point (w component is 0)
348
495
  */
349
- projectOrthographic() {
350
- return new Vec4(this.x, this.y, this.z, 0);
496
+ projectOrthographic(target = null) {
497
+ if (target) {
498
+ target._x = this._x;
499
+ target._y = this._y;
500
+ target._z = this._z;
501
+ target._w = 0;
502
+ return target;
503
+ }
504
+ return new Vec4(this._x, this._y, this._z, 0);
351
505
  }
352
506
 
353
507
  /**
@@ -355,7 +509,7 @@ export class Vec4 {
355
509
  * @returns {number[]}
356
510
  */
357
511
  toArray() {
358
- return [this.x, this.y, this.z, this.w];
512
+ return [this._x, this._y, this._z, this._w];
359
513
  }
360
514
 
361
515
  /**
@@ -363,7 +517,7 @@ export class Vec4 {
363
517
  * @returns {Float32Array}
364
518
  */
365
519
  toFloat32Array() {
366
- return new Float32Array(this.data);
520
+ return new Float32Array([this._x, this._y, this._z, this._w]);
367
521
  }
368
522
 
369
523
  /**
@@ -371,7 +525,7 @@ export class Vec4 {
371
525
  * @returns {number[]}
372
526
  */
373
527
  toArray3() {
374
- return [this.x, this.y, this.z];
528
+ return [this._x, this._y, this._z];
375
529
  }
376
530
 
377
531
  /**
@@ -380,7 +534,7 @@ export class Vec4 {
380
534
  * @returns {string}
381
535
  */
382
536
  toString(precision = 3) {
383
- return `Vec4(${this.x.toFixed(precision)}, ${this.y.toFixed(precision)}, ${this.z.toFixed(precision)}, ${this.w.toFixed(precision)})`;
537
+ return `Vec4(${this._x.toFixed(precision)}, ${this._y.toFixed(precision)}, ${this._z.toFixed(precision)}, ${this._w.toFixed(precision)})`;
384
538
  }
385
539
 
386
540
  /**
@@ -388,7 +542,7 @@ export class Vec4 {
388
542
  * @returns {object}
389
543
  */
390
544
  toJSON() {
391
- return { x: this.x, y: this.y, z: this.z, w: this.w };
545
+ return { x: this._x, y: this._y, z: this._z, w: this._w };
392
546
  }
393
547
 
394
548
  // Static factory methods for common vectors
@@ -787,6 +787,11 @@ void main() {
787
787
  }`;
788
788
 
789
789
  this.program = this.createProgram(vertexShaderSource, fragmentShaderSource);
790
+
791
+ if (!this.program) {
792
+ return;
793
+ }
794
+
790
795
  this.uniforms = {
791
796
  resolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
792
797
  time: this.gl.getUniformLocation(this.program, 'u_time'),
@@ -817,6 +822,18 @@ void main() {
817
822
  * Create WebGL program from shaders
818
823
  */
819
824
  createProgram(vertexSource, fragmentSource) {
825
+ // CRITICAL FIX: Check WebGL context state before shader operations
826
+ if (!this.gl) {
827
+ console.error('❌ Cannot create program: WebGL context is null');
828
+ return null;
829
+ }
830
+
831
+ if (this.gl.isContextLost()) {
832
+ console.error('❌ Cannot create program: WebGL context is lost');
833
+ this._contextLost = true;
834
+ return null;
835
+ }
836
+
820
837
  const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
821
838
  const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
822
839
 
@@ -860,6 +877,7 @@ void main() {
860
877
 
861
878
  if (this.gl.isContextLost()) {
862
879
  console.error('❌ Cannot create shader: WebGL context is lost');
880
+ this._contextLost = true;
863
881
  if (window.mobileDebug) {
864
882
  window.mobileDebug.log(`❌ ${this.canvas?.id}: Cannot create shader - WebGL context is lost`);
865
883
  }
@@ -924,6 +942,11 @@ void main() {
924
942
  * Initialize vertex buffers
925
943
  */
926
944
  initBuffers() {
945
+ // CRITICAL FIX: Check WebGL context state before buffer operations
946
+ if (!this.gl || this.gl.isContextLost()) {
947
+ return;
948
+ }
949
+
927
950
  const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
928
951
 
929
952
  this.buffer = this.gl.createBuffer();
@@ -939,6 +962,11 @@ void main() {
939
962
  * Resize canvas and viewport
940
963
  */
941
964
  resize() {
965
+ // CRITICAL FIX: Check WebGL context state before viewport operations
966
+ if (!this.gl || this.gl.isContextLost()) {
967
+ return;
968
+ }
969
+
942
970
  // Mobile-optimized canvas sizing
943
971
  const dpr = Math.min(window.devicePixelRatio || 1, 2); // Cap at 2x for mobile performance
944
972
  const width = this.canvas.clientWidth;