@vib3code/sdk 2.0.3-canary.75a3290 → 2.0.3-canary.ef8d292

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.
@@ -132,28 +132,28 @@ export class HolographicVisualizer {
132
132
  const finalName = geometryName + suffixes[variationLevel];
133
133
 
134
134
  const geometryConfigs = {
135
- 0: { density: 0.8 + variationLevel * 0.2, speed: 0.3 + variationLevel * 0.1, chaos: variationLevel * 0.1, morph: 0.0 + variationLevel * 0.2 },
136
- 1: { density: 1.0 + variationLevel * 0.3, speed: 0.5 + variationLevel * 0.1, chaos: variationLevel * 0.15, morph: variationLevel * 0.2 },
137
- 2: { density: 1.2 + variationLevel * 0.4, speed: 0.4 + variationLevel * 0.2, chaos: 0.1 + variationLevel * 0.1, morph: 0.3 + variationLevel * 0.2 },
138
- 3: { density: 0.9 + variationLevel * 0.3, speed: 0.6 + variationLevel * 0.2, chaos: 0.2 + variationLevel * 0.2, morph: 0.5 + variationLevel * 0.1 },
139
- 4: { density: 1.4 + variationLevel * 0.5, speed: 0.7 + variationLevel * 0.1, chaos: 0.3 + variationLevel * 0.2, morph: 0.7 + variationLevel * 0.1 },
140
- 5: { density: 1.8 + variationLevel * 0.3, speed: 0.5 + variationLevel * 0.3, chaos: 0.5 + variationLevel * 0.2, morph: 0.8 + variationLevel * 0.05 },
141
- 6: { density: 0.6 + variationLevel * 0.4, speed: 0.8 + variationLevel * 0.4, chaos: 0.4 + variationLevel * 0.3, morph: 0.6 + variationLevel * 0.2 },
142
- 7: { density: 1.6 + variationLevel * 0.2, speed: 0.2 + variationLevel * 0.1, chaos: 0.1 + variationLevel * 0.1, morph: 0.2 + variationLevel * 0.2 }
135
+ 0: { gridDensity: 0.8 + variationLevel * 0.2, speed: 0.3 + variationLevel * 0.1, chaos: variationLevel * 0.1, morphFactor: 0.0 + variationLevel * 0.2 },
136
+ 1: { gridDensity: 1.0 + variationLevel * 0.3, speed: 0.5 + variationLevel * 0.1, chaos: variationLevel * 0.15, morphFactor: variationLevel * 0.2 },
137
+ 2: { gridDensity: 1.2 + variationLevel * 0.4, speed: 0.4 + variationLevel * 0.2, chaos: 0.1 + variationLevel * 0.1, morphFactor: 0.3 + variationLevel * 0.2 },
138
+ 3: { gridDensity: 0.9 + variationLevel * 0.3, speed: 0.6 + variationLevel * 0.2, chaos: 0.2 + variationLevel * 0.2, morphFactor: 0.5 + variationLevel * 0.1 },
139
+ 4: { gridDensity: 1.4 + variationLevel * 0.5, speed: 0.7 + variationLevel * 0.1, chaos: 0.3 + variationLevel * 0.2, morphFactor: 0.7 + variationLevel * 0.1 },
140
+ 5: { gridDensity: 1.8 + variationLevel * 0.3, speed: 0.5 + variationLevel * 0.3, chaos: 0.5 + variationLevel * 0.2, morphFactor: 0.8 + variationLevel * 0.05 },
141
+ 6: { gridDensity: 0.6 + variationLevel * 0.4, speed: 0.8 + variationLevel * 0.4, chaos: 0.4 + variationLevel * 0.3, morphFactor: 0.6 + variationLevel * 0.2 },
142
+ 7: { gridDensity: 1.6 + variationLevel * 0.2, speed: 0.2 + variationLevel * 0.1, chaos: 0.1 + variationLevel * 0.1, morphFactor: 0.2 + variationLevel * 0.2 }
143
143
  };
144
-
144
+
145
145
  const config = geometryConfigs[baseGeometry];
146
-
146
+
147
147
  return {
148
- geometryType: baseGeometry,
148
+ geometry: baseGeometry,
149
149
  name: finalName,
150
- density: config.density,
150
+ gridDensity: config.gridDensity,
151
151
  speed: config.speed,
152
152
  hue: (variant * 12.27) % 360,
153
- saturation: 0.8 + (variationLevel * 0.05), // Add saturation parameter
153
+ saturation: 0.8 + (variationLevel * 0.05),
154
154
  intensity: 0.5 + (variationLevel * 0.1),
155
155
  chaos: config.chaos,
156
- morph: config.morph
156
+ morphFactor: config.morphFactor
157
157
  };
158
158
  }
159
159
 
@@ -169,20 +169,20 @@ export class HolographicVisualizer {
169
169
  densityMult: 0.8, speedMult: 0.3, colorShift: 180.0, intensity: 0.4,
170
170
  mouseReactivity: 0.5, clickReactivity: 0.3
171
171
  },
172
- 'content': {
173
- densityMult: vp.density, speedMult: vp.speed,
172
+ 'content': {
173
+ densityMult: vp.gridDensity, speedMult: vp.speed,
174
174
  colorShift: vp.hue, intensity: vp.intensity,
175
- mouseReactivity: 1.0, clickReactivity: 0.8
175
+ mouseReactivity: 1.0, clickReactivity: 0.8
176
176
  },
177
- 'highlight': {
178
- densityMult: 1.5 + (vp.density * 0.3), speedMult: 0.8 + (vp.speed * 0.2),
177
+ 'highlight': {
178
+ densityMult: 1.5 + (vp.gridDensity * 0.3), speedMult: 0.8 + (vp.speed * 0.2),
179
179
  colorShift: vp.hue + 60.0, intensity: 0.6 + (vp.intensity * 0.2),
180
- mouseReactivity: 1.2, clickReactivity: 1.0
180
+ mouseReactivity: 1.2, clickReactivity: 1.0
181
181
  },
182
- 'accent': {
183
- densityMult: 2.5 + (vp.density * 0.5), speedMult: 0.4 + (vp.speed * 0.1),
182
+ 'accent': {
183
+ densityMult: 2.5 + (vp.gridDensity * 0.5), speedMult: 0.4 + (vp.speed * 0.1),
184
184
  colorShift: vp.hue + 300.0, intensity: 0.3 + (vp.intensity * 0.1),
185
- mouseReactivity: 1.5, clickReactivity: 1.2
185
+ mouseReactivity: 1.5, clickReactivity: 1.2
186
186
  }
187
187
  };
188
188
 
@@ -207,7 +207,7 @@ export class HolographicVisualizer {
207
207
  uniform float u_time;
208
208
  uniform vec2 u_mouse;
209
209
  uniform float u_geometry;
210
- uniform float u_density;
210
+ uniform float u_gridDensity;
211
211
  uniform float u_speed;
212
212
  uniform vec3 u_color;
213
213
  uniform float u_intensity;
@@ -218,9 +218,8 @@ export class HolographicVisualizer {
218
218
  uniform float u_mouseIntensity;
219
219
  uniform float u_clickIntensity;
220
220
  uniform float u_densityVariation;
221
- uniform float u_geometryType;
222
221
  uniform float u_chaos;
223
- uniform float u_morph;
222
+ uniform float u_morphFactor;
224
223
  uniform float u_touchMorph;
225
224
  uniform float u_touchChaos;
226
225
  uniform float u_scrollParallax;
@@ -293,7 +292,7 @@ export class HolographicVisualizer {
293
292
  // ========================================
294
293
  vec3 warpHypersphereCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
295
294
  float radius = length(p);
296
- float morphBlend = clamp(u_morph * 0.6 + 0.3, 0.0, 2.0);
295
+ float morphBlend = clamp(u_morphFactor * 0.6 + 0.3, 0.0, 2.0);
297
296
  float w = sin(radius * (1.3 + float(geometryIndex) * 0.12) + u_time * 0.0008 * u_speed);
298
297
  w *= (0.4 + morphBlend * 0.45);
299
298
 
@@ -315,7 +314,7 @@ export class HolographicVisualizer {
315
314
  vec3 c3 = normalize(vec3(-1.0, 1.0, -1.0));
316
315
  vec3 c4 = normalize(vec3(1.0, -1.0, -1.0));
317
316
 
318
- float morphBlend = clamp(u_morph * 0.8 + 0.2, 0.0, 2.0);
317
+ float morphBlend = clamp(u_morphFactor * 0.8 + 0.2, 0.0, 2.0);
319
318
  float basisMix = dot(p, c1) * 0.14 + dot(p, c2) * 0.1 + dot(p, c3) * 0.08;
320
319
  float w = sin(basisMix * 5.5 + u_time * 0.0009 * u_speed);
321
320
  w *= cos(dot(p, c4) * 4.2 - u_time * 0.0007 * u_speed);
@@ -551,12 +550,12 @@ export class HolographicVisualizer {
551
550
  float audioDensityMod = 1.0 + u_audioDensityBoost * 0.5;
552
551
  // Controlled density calculation - breathing modulation added
553
552
  float breathDensityMod = 1.0 + u_breath * 0.1;
554
- float baseDensity = u_density * u_roleDensity * breathDensityMod;
553
+ float baseDensity = u_gridDensity * u_roleDensity * breathDensityMod;
555
554
 
556
555
  float densityVariations = (u_densityVariation * 0.3 + (scrollDensityMod - 1.0) * 0.4 + (audioDensityMod - 1.0) * 0.2);
557
556
  float roleDensity = baseDensity + densityVariations;
558
557
 
559
- float morphedGeometry = u_geometryType + u_morph * 3.0 + u_touchMorph * 2.0 + u_audioMorphBoost * 1.5;
558
+ float morphedGeometry = u_geometry + u_morphFactor * 3.0 + u_touchMorph * 2.0 + u_audioMorphBoost * 1.5;
560
559
  float lattice = getDynamicGeometry(p, roleDensity, morphedGeometry);
561
560
 
562
561
  // Enhanced holographic color processing
@@ -590,9 +589,9 @@ export class HolographicVisualizer {
590
589
  color = rgbGlitch(color, uv, enhancedChaos);
591
590
 
592
591
  // Apply morph distortion to position
593
- vec2 morphDistortion = vec2(sin(uv.y * 10.0 + u_time * 0.001) * u_morph * 0.1,
594
- cos(uv.x * 10.0 + u_time * 0.001) * u_morph * 0.1);
595
- color = mix(color, color * (1.0 + length(morphDistortion)), u_morph * 0.5);
592
+ vec2 morphDistortion = vec2(sin(uv.y * 10.0 + u_time * 0.001) * u_morphFactor * 0.1,
593
+ cos(uv.x * 10.0 + u_time * 0.001) * u_morphFactor * 0.1);
594
+ color = mix(color, color * (1.0 + length(morphDistortion)), u_morphFactor * 0.5);
596
595
 
597
596
  // Enhanced holographic interaction effects
598
597
  float mouseDist = length(uv - (u_mouse - 0.5) * vec2(aspectRatio, 1.0));
@@ -621,7 +620,7 @@ export class HolographicVisualizer {
621
620
  time: this.gl.getUniformLocation(this.program, 'u_time'),
622
621
  mouse: this.gl.getUniformLocation(this.program, 'u_mouse'),
623
622
  geometry: this.gl.getUniformLocation(this.program, 'u_geometry'),
624
- density: this.gl.getUniformLocation(this.program, 'u_density'),
623
+ gridDensity: this.gl.getUniformLocation(this.program, 'u_gridDensity'),
625
624
  speed: this.gl.getUniformLocation(this.program, 'u_speed'),
626
625
  color: this.gl.getUniformLocation(this.program, 'u_color'),
627
626
  intensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
@@ -632,9 +631,8 @@ export class HolographicVisualizer {
632
631
  mouseIntensity: this.gl.getUniformLocation(this.program, 'u_mouseIntensity'),
633
632
  clickIntensity: this.gl.getUniformLocation(this.program, 'u_clickIntensity'),
634
633
  densityVariation: this.gl.getUniformLocation(this.program, 'u_densityVariation'),
635
- geometryType: this.gl.getUniformLocation(this.program, 'u_geometryType'),
636
634
  chaos: this.gl.getUniformLocation(this.program, 'u_chaos'),
637
- morph: this.gl.getUniformLocation(this.program, 'u_morph'),
635
+ morphFactor: this.gl.getUniformLocation(this.program, 'u_morphFactor'),
638
636
  touchMorph: this.gl.getUniformLocation(this.program, 'u_touchMorph'),
639
637
  touchChaos: this.gl.getUniformLocation(this.program, 'u_touchChaos'),
640
638
  scrollParallax: this.gl.getUniformLocation(this.program, 'u_scrollParallax'),
@@ -894,11 +892,11 @@ export class HolographicVisualizer {
894
892
  this.gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
895
893
  this.gl.uniform1f(this.uniforms.time, time);
896
894
  this.gl.uniform2f(this.uniforms.mouse, this.mouseX, this.mouseY);
897
- this.gl.uniform1f(this.uniforms.geometryType, this.variantParams.geometryType || 0);
898
- this.gl.uniform1f(this.uniforms.density, this.variantParams.density || 1.0);
899
- // FIX: Controlled speed calculation - base speed controls main movement, audio provides subtle boost
900
- const baseSpeed = (this.variantParams.speed || 0.5) * 0.2; // Much slower base speed
901
- const audioBoost = (this.audioSpeedBoost || 0.0) * 0.1; // Subtle audio boost only
895
+ this.gl.uniform1f(this.uniforms.geometry, this.variantParams.geometry !== undefined ? this.variantParams.geometry : this.variant || 0);
896
+ this.gl.uniform1f(this.uniforms.gridDensity, this.variantParams.gridDensity || 1.0);
897
+ // Controlled speed calculation - base speed controls main movement, audio provides subtle boost
898
+ const baseSpeed = (this.variantParams.speed || 0.5) * 0.2;
899
+ const audioBoost = (this.audioSpeedBoost || 0.0) * 0.1;
902
900
  this.gl.uniform1f(this.uniforms.speed, baseSpeed + audioBoost);
903
901
  this.gl.uniform3fv(this.uniforms.color, new Float32Array(rgbColor));
904
902
  this.gl.uniform1f(this.uniforms.intensity, (this.variantParams.intensity || 0.5) * this.roleParams.intensity);
@@ -909,9 +907,8 @@ export class HolographicVisualizer {
909
907
  this.gl.uniform1f(this.uniforms.mouseIntensity, this.mouseIntensity);
910
908
  this.gl.uniform1f(this.uniforms.clickIntensity, this.clickIntensity);
911
909
  this.gl.uniform1f(this.uniforms.densityVariation, this.densityVariation);
912
- this.gl.uniform1f(this.uniforms.geometryType, this.variantParams.geometryType !== undefined ? this.variantParams.geometryType : this.variant || 0);
913
910
  this.gl.uniform1f(this.uniforms.chaos, this.variantParams.chaos || 0.0);
914
- this.gl.uniform1f(this.uniforms.morph, this.variantParams.morph || 0.0);
911
+ this.gl.uniform1f(this.uniforms.morphFactor, this.variantParams.morphFactor || 0.0);
915
912
 
916
913
  // Touch and scroll uniforms
917
914
  this.gl.uniform1f(this.uniforms.touchMorph, this.touchMorph);
@@ -1001,62 +998,34 @@ export class HolographicVisualizer {
1001
998
  }
1002
999
 
1003
1000
  /**
1004
- * CRITICAL FIX: Update visualization parameters with immediate re-render
1005
- * This method was missing and causing parameter sliders to not work in holographic system
1001
+ * Update visualization parameters from SDK global parameter names.
1002
+ * Parameters are written directly to variantParams no name mapping needed
1003
+ * since shader uniforms now use SDK-standard names.
1006
1004
  */
1007
1005
  updateParameters(params) {
1008
1006
  if (!params || typeof params !== 'object') return;
1009
- // Update variant parameters with proper mapping and scaling
1010
1007
  if (this.variantParams) {
1011
1008
  Object.keys(params).forEach(param => {
1012
- const mappedParam = this.mapParameterName(param);
1013
- if (mappedParam !== null) {
1014
- let scaledValue = params[param];
1015
- // Guard against NaN/Infinity reaching GPU uniforms
1016
- if (typeof scaledValue !== 'number' || !Number.isFinite(scaledValue)) return;
1017
-
1018
- // FIX: Scale gridDensity to reasonable holographic density range (back to normal levels)
1019
- if (param === 'gridDensity') {
1020
- // Convert gridDensity (5-100) to holographic density (0.3-2.5) - reasonable range
1021
- // Formula: density = 0.3 + (gridDensity - 5) / (100 - 5) * (2.5 - 0.3)
1022
- scaledValue = 0.3 + (parseFloat(params[param]) - 5) / 95 * 2.2;
1023
- console.log(`🔧 Density scaling: gridDensity=${params[param]} density=${scaledValue.toFixed(3)} (normal range)`);
1024
- }
1025
-
1026
- this.variantParams[mappedParam] = scaledValue;
1027
-
1028
- // Handle special parameter types
1029
- if (mappedParam === 'geometryType') {
1030
- // Regenerate role params with new geometry
1031
- this.roleParams = this.generateRoleParams(this.role);
1032
- }
1009
+ let scaledValue = params[param];
1010
+ // Guard against NaN/Infinity reaching GPU uniforms
1011
+ if (typeof scaledValue !== 'number' || !Number.isFinite(scaledValue)) return;
1012
+
1013
+ // Scale gridDensity (5-100) to holographic density range (0.3-2.5)
1014
+ if (param === 'gridDensity') {
1015
+ scaledValue = 0.3 + (parseFloat(params[param]) - 5) / 95 * 2.2;
1016
+ }
1017
+
1018
+ this.variantParams[param] = scaledValue;
1019
+
1020
+ // Regenerate role params when geometry changes
1021
+ if (param === 'geometry') {
1022
+ this.roleParams = this.generateRoleParams(this.role);
1033
1023
  }
1034
1024
  });
1035
1025
  }
1036
-
1026
+
1037
1027
  // Don't call render() here - engine will call it to prevent infinite loop
1038
1028
  }
1039
-
1040
- /**
1041
- * Map global parameter names to holographic system parameter names
1042
- */
1043
- mapParameterName(globalParam) {
1044
- const paramMap = {
1045
- 'gridDensity': 'density',
1046
- 'morphFactor': 'morph',
1047
- 'rot4dXW': 'rot4dXW',
1048
- 'rot4dYW': 'rot4dYW',
1049
- 'rot4dZW': 'rot4dZW',
1050
- 'hue': 'hue',
1051
- 'intensity': 'intensity',
1052
- 'saturation': 'saturation',
1053
- 'chaos': 'chaos',
1054
- 'speed': 'speed',
1055
- 'geometry': 'geometryType',
1056
- 'breath': 'breath'
1057
- };
1058
- return paramMap[globalParam] || globalParam;
1059
- }
1060
1029
 
1061
1030
  /**
1062
1031
  * Clean up all WebGL resources and event listeners
@@ -160,21 +160,42 @@ export class Mat4x4 {
160
160
  * @returns {Mat4x4} New matrix = this * m
161
161
  */
162
162
  multiply(m) {
163
+ const out = new Mat4x4();
164
+ const r = out.data;
163
165
  const a = this.data;
164
166
  const b = m.data;
165
- const result = new Float32Array(16);
166
167
 
167
- for (let col = 0; col < 4; col++) {
168
- for (let row = 0; row < 4; row++) {
169
- let sum = 0;
170
- for (let k = 0; k < 4; k++) {
171
- sum += a[k * 4 + row] * b[col * 4 + k];
172
- }
173
- result[col * 4 + row] = sum;
174
- }
175
- }
168
+ const a00 = a[0], a01 = a[4], a02 = a[8], a03 = a[12];
169
+ const a10 = a[1], a11 = a[5], a12 = a[9], a13 = a[13];
170
+ const a20 = a[2], a21 = a[6], a22 = a[10], a23 = a[14];
171
+ const a30 = a[3], a31 = a[7], a32 = a[11], a33 = a[15];
176
172
 
177
- return new Mat4x4(result);
173
+ const b00 = b[0], b01 = b[4], b02 = b[8], b03 = b[12];
174
+ const b10 = b[1], b11 = b[5], b12 = b[9], b13 = b[13];
175
+ const b20 = b[2], b21 = b[6], b22 = b[10], b23 = b[14];
176
+ const b30 = b[3], b31 = b[7], b32 = b[11], b33 = b[15];
177
+
178
+ r[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
179
+ r[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
180
+ r[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
181
+ r[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
182
+
183
+ r[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
184
+ r[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
185
+ r[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
186
+ r[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
187
+
188
+ r[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
189
+ r[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
190
+ r[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
191
+ r[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
192
+
193
+ r[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
194
+ r[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
195
+ r[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
196
+ r[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
197
+
198
+ return out;
178
199
  }
179
200
 
180
201
  /**
@@ -183,8 +204,44 @@ export class Mat4x4 {
183
204
  * @returns {Mat4x4} this
184
205
  */
185
206
  multiplyInPlace(m) {
186
- const result = this.multiply(m);
187
- this.data.set(result.data);
207
+ const a = this.data;
208
+ const b = m.data;
209
+
210
+ // Cache values to avoid aliasing issues and repeated array access
211
+ const a00 = a[0], a01 = a[4], a02 = a[8], a03 = a[12];
212
+ const a10 = a[1], a11 = a[5], a12 = a[9], a13 = a[13];
213
+ const a20 = a[2], a21 = a[6], a22 = a[10], a23 = a[14];
214
+ const a30 = a[3], a31 = a[7], a32 = a[11], a33 = a[15];
215
+
216
+ const b00 = b[0], b01 = b[4], b02 = b[8], b03 = b[12];
217
+ const b10 = b[1], b11 = b[5], b12 = b[9], b13 = b[13];
218
+ const b20 = b[2], b21 = b[6], b22 = b[10], b23 = b[14];
219
+ const b30 = b[3], b31 = b[7], b32 = b[11], b33 = b[15];
220
+
221
+ // Column 0
222
+ a[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
223
+ a[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
224
+ a[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
225
+ a[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
226
+
227
+ // Column 1
228
+ a[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
229
+ a[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
230
+ a[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
231
+ a[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
232
+
233
+ // Column 2
234
+ a[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
235
+ a[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
236
+ a[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
237
+ a[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
238
+
239
+ // Column 3
240
+ a[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
241
+ a[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
242
+ a[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
243
+ a[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
244
+
188
245
  return this;
189
246
  }
190
247
 
@@ -324,53 +324,114 @@ export class Rotor4D {
324
324
  * Rotate a 4D vector using sandwich product: v' = R v R†
325
325
  *
326
326
  * @param {Vec4} v - Vector to rotate
327
+ * @param {Vec4} [target] - Optional target vector to write result to
327
328
  * @returns {Vec4} Rotated vector
328
329
  */
329
- rotate(v) {
330
- // For efficiency, we expand the sandwich product directly
331
- // rather than doing two rotor multiplications
330
+ rotate(v, target) {
331
+ // Direct matrix multiplication without allocation
332
332
 
333
- const x = v.x, y = v.y, z = v.z, w = v.w;
334
-
335
- // Compute R v (rotor times vector)
336
- // Vector in GA is: x*e1 + y*e2 + z*e3 + w*e4
337
- // This produces a mixed multivector
338
-
339
- // Then multiply by R† (reverse of rotor)
340
- // Extract the vector part of the result
333
+ // Normalize components for stability (same as toMatrix)
334
+ const n = this.norm();
335
+ const invN = n > 1e-10 ? 1 / n : 1;
341
336
 
342
- // Pre-compute some common terms
343
- const s = this.s;
344
- const xy = this.xy, xz = this.xz, yz = this.yz;
345
- const xw = this.xw, yw = this.yw, zw = this.zw;
346
- const xyzw = this.xyzw;
337
+ const s = this.s * invN;
338
+ const xy = this.xy * invN;
339
+ const xz = this.xz * invN;
340
+ const yz = this.yz * invN;
341
+ const xw = this.xw * invN;
342
+ const yw = this.yw * invN;
343
+ const zw = this.zw * invN;
344
+ const xyzw = this.xyzw * invN;
347
345
 
348
- // Squared terms for the rotation formula
346
+ // Pre-compute products
349
347
  const s2 = s * s;
350
- const xy2 = xy * xy, xz2 = xz * xz, yz2 = yz * yz;
351
- const xw2 = xw * xw, yw2 = yw * yw, zw2 = zw * zw;
348
+ const xy2 = xy * xy;
349
+ const xz2 = xz * xz;
350
+ const yz2 = yz * yz;
351
+ const xw2 = xw * xw;
352
+ const yw2 = yw * yw;
353
+ const zw2 = zw * zw;
352
354
  const xyzw2 = xyzw * xyzw;
353
355
 
354
- // The full rotation formula derived from R v R†
355
- const newX =
356
- x * (s2 + xy2 + xz2 - yz2 + xw2 - yw2 - zw2 - xyzw2) +
357
- 2 * y * (s * xy + xz * yz + xw * yw - s * xyzw * zw + xy * s - xyzw * zw) +
358
- 2 * z * (s * xz - xy * yz + xw * zw + xyzw * yw) +
359
- 2 * w * (s * xw - xy * yw - xz * zw - xyzw * yz);
360
-
361
- // Simplified rotation using matrix form
362
- // This is equivalent but clearer
363
-
364
- // Actually, let's use the direct matrix multiplication approach
365
- // which is more numerically stable
366
-
367
- const m = this.toMatrix();
368
- return new Vec4(
369
- m[0] * x + m[4] * y + m[8] * z + m[12] * w,
370
- m[1] * x + m[5] * y + m[9] * z + m[13] * w,
371
- m[2] * x + m[6] * y + m[10] * z + m[14] * w,
372
- m[3] * x + m[7] * y + m[11] * z + m[15] * w
373
- );
356
+ // Cross terms
357
+ const sxy = 2 * s * xy;
358
+ const sxz = 2 * s * xz;
359
+ const syz = 2 * s * yz;
360
+ const sxw = 2 * s * xw;
361
+ const syw = 2 * s * yw;
362
+ const szw = 2 * s * zw;
363
+ // const sxyzw = 2 * s * xyzw; // Unused in rotation matrix
364
+
365
+ const xyxz = 2 * xy * xz;
366
+ const xyyz = 2 * xy * yz;
367
+ const xyxw = 2 * xy * xw;
368
+ const xyyw = 2 * xy * yw;
369
+ // const xyzw_c = 2 * xy * zw; // Unused in rotation matrix
370
+
371
+ const xzyz = 2 * xz * yz;
372
+ const xzxw = 2 * xz * xw;
373
+ const xzyw = 2 * xz * yw;
374
+ const xzzw = 2 * xz * zw;
375
+
376
+ const yzxw = 2 * yz * xw;
377
+ const yzyw = 2 * yz * yw;
378
+ const yzzw = 2 * yz * zw;
379
+
380
+ const xwyw = 2 * xw * yw;
381
+ const xwzw = 2 * xw * zw;
382
+ const ywzw = 2 * yw * zw;
383
+
384
+ const xyxyzw = 2 * xy * xyzw;
385
+ const xzxyzw = 2 * xz * xyzw;
386
+ const yzxyzw = 2 * yz * xyzw;
387
+ const xwxyzw = 2 * xw * xyzw;
388
+ const ywxyzw = 2 * yw * xyzw;
389
+ const zwxyzw = 2 * zw * xyzw;
390
+
391
+ // Matrix elements
392
+ // Col 0
393
+ const m00 = s2 - xy2 - xz2 + yz2 - xw2 + yw2 + zw2 - xyzw2;
394
+ const m01 = sxy + xzyz + xwyw - zwxyzw;
395
+ const m02 = sxz - xyyz + xwzw + ywxyzw;
396
+ const m03 = sxw - xyyw - xzzw - yzxyzw;
397
+
398
+ // Col 1
399
+ const m10 = -sxy + xzyz + xwyw + zwxyzw;
400
+ const m11 = s2 - xy2 + xz2 - yz2 + xw2 - yw2 + zw2 - xyzw2;
401
+ const m12 = syz + xyxz + ywzw - xwxyzw;
402
+ const m13 = syw + xyxw - yzzw + xzxyzw;
403
+
404
+ // Col 2
405
+ const m20 = -sxz - xyyz + xwzw - ywxyzw;
406
+ const m21 = -syz + xyxz + ywzw + xwxyzw;
407
+ const m22 = s2 + xy2 - xz2 - yz2 + xw2 + yw2 - zw2 - xyzw2;
408
+ const m23 = szw + xzxw + yzyw - xyxyzw;
409
+
410
+ // Col 3
411
+ const m30 = -sxw - xyyw - xzzw + yzxyzw;
412
+ const m31 = -syw + xyxw - yzzw - xzxyzw;
413
+ const m32 = -szw + xzxw + yzyw + xyxyzw;
414
+ const m33 = s2 + xy2 + xz2 + yz2 - xw2 - yw2 - zw2 - xyzw2;
415
+
416
+ const x = v.x;
417
+ const y = v.y;
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;
425
+
426
+ if (target) {
427
+ target.x = rx;
428
+ target.y = ry;
429
+ target.z = rz;
430
+ target.w = rw;
431
+ return target;
432
+ }
433
+
434
+ return new Vec4(rx, ry, rz, rw);
374
435
  }
375
436
 
376
437
  /**
@@ -6,6 +6,17 @@
6
6
 
7
7
  import { GeometryLibrary } from '../geometry/GeometryLibrary.js';
8
8
 
9
+ // Role-specific intensity values for 5-layer canvas architecture.
10
+ // IMPORTANT: Must stay in sync with shader epsilon comparisons in the fragment shader
11
+ // at the "LAYER-BY-LAYER COLOR SYSTEM" section (search for layerIndex).
12
+ const ROLE_INTENSITIES = {
13
+ 'background': 0.4,
14
+ 'shadow': 0.6,
15
+ 'content': 1.0,
16
+ 'highlight': 1.3,
17
+ 'accent': 1.6
18
+ };
19
+
9
20
  export class QuantumHolographicVisualizer {
10
21
  constructor(canvasIdOrElement, role, reactivity, variant) {
11
22
  this.canvas = (canvasIdOrElement instanceof HTMLCanvasElement)
@@ -14,6 +25,7 @@ export class QuantumHolographicVisualizer {
14
25
  this.role = role;
15
26
  this.reactivity = reactivity;
16
27
  this.variant = variant;
28
+ this._canvasLabel = typeof canvasIdOrElement === 'string' ? canvasIdOrElement : canvasIdOrElement?.id || 'unknown';
17
29
 
18
30
  // CRITICAL FIX: Define contextOptions as instance property to match SmartCanvasPool
19
31
  this.contextOptions = {
@@ -34,9 +46,9 @@ export class QuantumHolographicVisualizer {
34
46
  this.canvas.getContext('experimental-webgl', this.contextOptions);
35
47
 
36
48
  if (!this.gl) {
37
- console.error(`WebGL not supported for ${canvasId}`);
49
+ console.error(`WebGL not supported for ${this._canvasLabel}`);
38
50
  if (window.mobileDebug) {
39
- window.mobileDebug.log(`❌ ${canvasId}: WebGL context creation failed`);
51
+ window.mobileDebug.log(`❌ ${this._canvasLabel}: WebGL context creation failed`);
40
52
  }
41
53
  // Show user-friendly error instead of white screen
42
54
  this.showWebGLError();
@@ -44,7 +56,7 @@ export class QuantumHolographicVisualizer {
44
56
  } else {
45
57
  if (window.mobileDebug) {
46
58
  const version = this.gl.getParameter(this.gl.VERSION);
47
- window.mobileDebug.log(`✅ ${canvasId}: WebGL context created - ${version}`);
59
+ window.mobileDebug.log(`✅ ${this._canvasLabel}: WebGL context created - ${version}`);
48
60
  }
49
61
  }
50
62
 
@@ -59,15 +71,15 @@ export class QuantumHolographicVisualizer {
59
71
  this._onContextLost = (e) => {
60
72
  e.preventDefault();
61
73
  this._contextLost = true;
62
- console.warn(`WebGL context lost for ${canvasId}`);
74
+ console.warn(`WebGL context lost for ${this._canvasLabel}`);
63
75
  };
64
76
  this._onContextRestored = () => {
65
- console.log(`WebGL context restored for ${canvasId}`);
77
+ console.log(`WebGL context restored for ${this._canvasLabel}`);
66
78
  this._contextLost = false;
67
79
  try {
68
80
  this.init();
69
81
  } catch (err) {
70
- console.error(`Failed to reinit after context restore for ${canvasId}:`, err);
82
+ console.error(`Failed to reinit after context restore for ${this._canvasLabel}:`, err);
71
83
  }
72
84
  };
73
85
  this.canvas.addEventListener('webglcontextlost', this._onContextLost);
@@ -688,11 +700,12 @@ void main() {
688
700
 
689
701
  // LAYER-BY-LAYER COLOR SYSTEM with user hue/saturation/intensity controls
690
702
  // Determine canvas layer from role/variant (0=background, 1=shadow, 2=content, 3=highlight, 4=accent)
703
+ // Values must match ROLE_INTENSITIES in JS: bg=0.4, shadow=0.6, content=1.0, highlight=1.3, accent=1.6
691
704
  int layerIndex = 0;
692
- if (u_roleIntensity == 0.7) layerIndex = 1; // shadow layer
693
- else if (u_roleIntensity == 1.0) layerIndex = 2; // content layer
694
- else if (u_roleIntensity == 0.85) layerIndex = 3; // highlight layer
695
- else if (u_roleIntensity == 0.6) layerIndex = 4; // accent layer
705
+ if (abs(u_roleIntensity - 0.6) < 0.05) layerIndex = 1; // shadow layer
706
+ else if (abs(u_roleIntensity - 1.0) < 0.05) layerIndex = 2; // content layer
707
+ else if (abs(u_roleIntensity - 1.3) < 0.05) layerIndex = 3; // highlight layer
708
+ else if (abs(u_roleIntensity - 1.6) < 0.05) layerIndex = 4; // accent layer
696
709
 
697
710
  // Get layer-specific base color using user hue/saturation controls
698
711
  float colorTime = timeSpeed * 2.0 + value * 3.0;
@@ -1016,15 +1029,6 @@ void main() {
1016
1029
  this._renderParamsLogged = true;
1017
1030
  }
1018
1031
 
1019
- // Role-specific intensity for quantum effects
1020
- const roleIntensities = {
1021
- 'background': 0.4,
1022
- 'shadow': 0.6,
1023
- 'content': 1.0,
1024
- 'highlight': 1.3,
1025
- 'accent': 1.6
1026
- };
1027
-
1028
1032
  const time = Date.now() - this.startTime;
1029
1033
 
1030
1034
  // Set uniforms
@@ -1068,7 +1072,7 @@ void main() {
1068
1072
  this.gl.uniform1f(this.uniforms.rot4dZW, this.params.rot4dZW || 0.0);
1069
1073
  this.gl.uniform1f(this.uniforms.mouseIntensity, this.mouseIntensity);
1070
1074
  this.gl.uniform1f(this.uniforms.clickIntensity, this.clickIntensity);
1071
- this.gl.uniform1f(this.uniforms.roleIntensity, roleIntensities[this.role] || 1.0);
1075
+ this.gl.uniform1f(this.uniforms.roleIntensity, ROLE_INTENSITIES[this.role] || 1.0);
1072
1076
  this.gl.uniform1f(this.uniforms.breath, this.params.breath || 0.0);
1073
1077
 
1074
1078
  this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);