@vib3code/sdk 2.0.3-canary.0c55e5a → 2.0.3-canary.20f0435
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/EXPANSION_DESIGN.md +977 -0
- package/DOCS/EXPANSION_DESIGN_ULTRA.md +387 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +2 -2
- package/DOCS/OPTIMIZATION_PLAN_MATH.md +118 -0
- package/DOCS/SYSTEM_INVENTORY.md +2 -2
- package/DOCS/WEBGPU_STATUS.md +119 -38
- package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +38 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +108 -0
- package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +308 -0
- package/docs/webgpu-live.html +1 -1
- package/package.json +1 -1
- package/src/agent/mcp/MCPServer.js +195 -136
- package/src/agent/mcp/tools.js +45 -32
- 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/faceted/FacetedSystem.js +19 -6
- package/src/geometry/generators/Crystal.js +2 -2
- package/src/holograms/HolographicVisualizer.js +58 -89
- package/src/math/Mat4x4.js +122 -6
- package/src/math/Rotor4D.js +38 -45
- package/src/math/Vec4.js +119 -78
- package/src/quantum/QuantumVisualizer.js +24 -20
- package/src/render/ShaderLoader.js +38 -0
- package/src/render/ShaderProgram.js +4 -4
- package/src/render/UnifiedRenderBridge.js +1 -1
- package/src/render/backends/WebGPUBackend.js +8 -4
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +4 -4
- package/src/shaders/common/rotation4d.wgsl +2 -2
- package/src/shaders/common/uniforms.wgsl +15 -8
- package/src/shaders/faceted/faceted.frag.wgsl +19 -6
- package/src/shaders/holographic/holographic.frag.wgsl +7 -5
- package/src/shaders/quantum/quantum.frag.wgsl +7 -5
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
- package/tools/shader-sync-verify.js +6 -4
|
@@ -132,28 +132,28 @@ export class HolographicVisualizer {
|
|
|
132
132
|
const finalName = geometryName + suffixes[variationLevel];
|
|
133
133
|
|
|
134
134
|
const geometryConfigs = {
|
|
135
|
-
0: {
|
|
136
|
-
1: {
|
|
137
|
-
2: {
|
|
138
|
-
3: {
|
|
139
|
-
4: {
|
|
140
|
-
5: {
|
|
141
|
-
6: {
|
|
142
|
-
7: {
|
|
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
|
-
|
|
148
|
+
geometry: baseGeometry,
|
|
149
149
|
name: finalName,
|
|
150
|
-
|
|
150
|
+
gridDensity: config.gridDensity,
|
|
151
151
|
speed: config.speed,
|
|
152
152
|
hue: (variant * 12.27) % 360,
|
|
153
|
-
saturation: 0.8 + (variationLevel * 0.05),
|
|
153
|
+
saturation: 0.8 + (variationLevel * 0.05),
|
|
154
154
|
intensity: 0.5 + (variationLevel * 0.1),
|
|
155
155
|
chaos: config.chaos,
|
|
156
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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) *
|
|
594
|
-
cos(uv.x * 10.0 + u_time * 0.001) *
|
|
595
|
-
color = mix(color, color * (1.0 + length(morphDistortion)),
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
898
|
-
this.gl.uniform1f(this.uniforms.
|
|
899
|
-
//
|
|
900
|
-
const baseSpeed = (this.variantParams.speed || 0.5) * 0.2;
|
|
901
|
-
const audioBoost = (this.audioSpeedBoost || 0.0) * 0.1;
|
|
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.
|
|
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
|
-
*
|
|
1005
|
-
*
|
|
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
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
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
|
package/src/math/Mat4x4.js
CHANGED
|
@@ -547,6 +547,122 @@ export class Mat4x4 {
|
|
|
547
547
|
return new Mat4x4(json.data);
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
+
// ========== IN-PLACE ROTATIONS ==========
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Rotate in XY plane in place
|
|
554
|
+
* @param {number} angle
|
|
555
|
+
* @returns {Mat4x4} this
|
|
556
|
+
*/
|
|
557
|
+
rotateXY(angle) {
|
|
558
|
+
const c = Math.cos(angle);
|
|
559
|
+
const s = Math.sin(angle);
|
|
560
|
+
const m = this.data;
|
|
561
|
+
|
|
562
|
+
for (let i = 0; i < 4; i++) {
|
|
563
|
+
const a0 = m[i]; // Col 0
|
|
564
|
+
const a1 = m[i + 4]; // Col 1
|
|
565
|
+
m[i] = a0 * c + a1 * s;
|
|
566
|
+
m[i + 4] = -a0 * s + a1 * c;
|
|
567
|
+
}
|
|
568
|
+
return this;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Rotate in XZ plane in place
|
|
573
|
+
* @param {number} angle
|
|
574
|
+
* @returns {Mat4x4} this
|
|
575
|
+
*/
|
|
576
|
+
rotateXZ(angle) {
|
|
577
|
+
const c = Math.cos(angle);
|
|
578
|
+
const s = Math.sin(angle);
|
|
579
|
+
const m = this.data;
|
|
580
|
+
|
|
581
|
+
for (let i = 0; i < 4; i++) {
|
|
582
|
+
const a0 = m[i]; // Col 0
|
|
583
|
+
const a2 = m[i + 8]; // Col 2
|
|
584
|
+
m[i] = a0 * c - a2 * s;
|
|
585
|
+
m[i + 8] = a0 * s + a2 * c;
|
|
586
|
+
}
|
|
587
|
+
return this;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Rotate in YZ plane in place
|
|
592
|
+
* @param {number} angle
|
|
593
|
+
* @returns {Mat4x4} this
|
|
594
|
+
*/
|
|
595
|
+
rotateYZ(angle) {
|
|
596
|
+
const c = Math.cos(angle);
|
|
597
|
+
const s = Math.sin(angle);
|
|
598
|
+
const m = this.data;
|
|
599
|
+
|
|
600
|
+
for (let i = 0; i < 4; i++) {
|
|
601
|
+
const a1 = m[i + 4]; // Col 1
|
|
602
|
+
const a2 = m[i + 8]; // Col 2
|
|
603
|
+
m[i + 4] = a1 * c + a2 * s;
|
|
604
|
+
m[i + 8] = -a1 * s + a2 * c;
|
|
605
|
+
}
|
|
606
|
+
return this;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Rotate in XW plane in place
|
|
611
|
+
* @param {number} angle
|
|
612
|
+
* @returns {Mat4x4} this
|
|
613
|
+
*/
|
|
614
|
+
rotateXW(angle) {
|
|
615
|
+
const c = Math.cos(angle);
|
|
616
|
+
const s = Math.sin(angle);
|
|
617
|
+
const m = this.data;
|
|
618
|
+
|
|
619
|
+
for (let i = 0; i < 4; i++) {
|
|
620
|
+
const a0 = m[i]; // Col 0
|
|
621
|
+
const a3 = m[i + 12]; // Col 3
|
|
622
|
+
m[i] = a0 * c + a3 * s;
|
|
623
|
+
m[i + 12] = -a0 * s + a3 * c;
|
|
624
|
+
}
|
|
625
|
+
return this;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Rotate in YW plane in place
|
|
630
|
+
* @param {number} angle
|
|
631
|
+
* @returns {Mat4x4} this
|
|
632
|
+
*/
|
|
633
|
+
rotateYW(angle) {
|
|
634
|
+
const c = Math.cos(angle);
|
|
635
|
+
const s = Math.sin(angle);
|
|
636
|
+
const m = this.data;
|
|
637
|
+
|
|
638
|
+
for (let i = 0; i < 4; i++) {
|
|
639
|
+
const a1 = m[i + 4]; // Col 1
|
|
640
|
+
const a3 = m[i + 12]; // Col 3
|
|
641
|
+
m[i + 4] = a1 * c + a3 * s;
|
|
642
|
+
m[i + 12] = -a1 * s + a3 * c;
|
|
643
|
+
}
|
|
644
|
+
return this;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Rotate in ZW plane in place
|
|
649
|
+
* @param {number} angle
|
|
650
|
+
* @returns {Mat4x4} this
|
|
651
|
+
*/
|
|
652
|
+
rotateZW(angle) {
|
|
653
|
+
const c = Math.cos(angle);
|
|
654
|
+
const s = Math.sin(angle);
|
|
655
|
+
const m = this.data;
|
|
656
|
+
|
|
657
|
+
for (let i = 0; i < 4; i++) {
|
|
658
|
+
const a2 = m[i + 8]; // Col 2
|
|
659
|
+
const a3 = m[i + 12]; // Col 3
|
|
660
|
+
m[i + 8] = a2 * c + a3 * s;
|
|
661
|
+
m[i + 12] = -a2 * s + a3 * c;
|
|
662
|
+
}
|
|
663
|
+
return this;
|
|
664
|
+
}
|
|
665
|
+
|
|
550
666
|
// ========== ROTATION MATRICES FOR ALL 6 PLANES ==========
|
|
551
667
|
|
|
552
668
|
/**
|
|
@@ -681,12 +797,12 @@ export class Mat4x4 {
|
|
|
681
797
|
static rotationFromAngles(angles) {
|
|
682
798
|
let result = Mat4x4.identity();
|
|
683
799
|
|
|
684
|
-
if (angles.xy) result
|
|
685
|
-
if (angles.xz) result
|
|
686
|
-
if (angles.yz) result
|
|
687
|
-
if (angles.xw) result
|
|
688
|
-
if (angles.yw) result
|
|
689
|
-
if (angles.zw) result
|
|
800
|
+
if (angles.xy) result.rotateXY(angles.xy);
|
|
801
|
+
if (angles.xz) result.rotateXZ(angles.xz);
|
|
802
|
+
if (angles.yz) result.rotateYZ(angles.yz);
|
|
803
|
+
if (angles.xw) result.rotateXW(angles.xw);
|
|
804
|
+
if (angles.yw) result.rotateYW(angles.yw);
|
|
805
|
+
if (angles.zw) result.rotateZW(angles.zw);
|
|
690
806
|
|
|
691
807
|
return result;
|
|
692
808
|
}
|
package/src/math/Rotor4D.js
CHANGED
|
@@ -323,14 +323,17 @@ export class Rotor4D {
|
|
|
323
323
|
/**
|
|
324
324
|
* Rotate a 4D vector using sandwich product: v' = R v R†
|
|
325
325
|
*
|
|
326
|
+
* Matrix math is inlined to avoid allocating a temporary Float32Array(16).
|
|
327
|
+
* Pass an optional target Vec4 to eliminate all allocations.
|
|
328
|
+
*
|
|
326
329
|
* @param {Vec4} v - Vector to rotate
|
|
327
|
-
* @param {Vec4} [target] - Optional
|
|
328
|
-
* @returns {Vec4} Rotated vector
|
|
330
|
+
* @param {Vec4} [target] - Optional pre-allocated Vec4 to write result into
|
|
331
|
+
* @returns {Vec4} Rotated vector (target if provided, otherwise new Vec4)
|
|
329
332
|
*/
|
|
330
333
|
rotate(v, target) {
|
|
331
|
-
|
|
334
|
+
const x = v.x, y = v.y, z = v.z, w = v.w;
|
|
332
335
|
|
|
333
|
-
// Normalize
|
|
336
|
+
// Normalize for numerical stability (same as toMatrix)
|
|
334
337
|
const n = this.norm();
|
|
335
338
|
const invN = n > 1e-10 ? 1 / n : 1;
|
|
336
339
|
|
|
@@ -343,7 +346,7 @@ export class Rotor4D {
|
|
|
343
346
|
const zw = this.zw * invN;
|
|
344
347
|
const xyzw = this.xyzw * invN;
|
|
345
348
|
|
|
346
|
-
//
|
|
349
|
+
// Squared terms
|
|
347
350
|
const s2 = s * s;
|
|
348
351
|
const xy2 = xy * xy;
|
|
349
352
|
const xz2 = xz * xz;
|
|
@@ -353,22 +356,20 @@ export class Rotor4D {
|
|
|
353
356
|
const zw2 = zw * zw;
|
|
354
357
|
const xyzw2 = xyzw * xyzw;
|
|
355
358
|
|
|
356
|
-
// Cross terms
|
|
359
|
+
// Cross terms (pre-multiplied by 2)
|
|
357
360
|
const sxy = 2 * s * xy;
|
|
358
361
|
const sxz = 2 * s * xz;
|
|
359
362
|
const syz = 2 * s * yz;
|
|
360
363
|
const sxw = 2 * s * xw;
|
|
361
364
|
const syw = 2 * s * yw;
|
|
362
365
|
const szw = 2 * s * zw;
|
|
363
|
-
// const sxyzw = 2 * s * xyzw; // Unused in rotation matrix
|
|
364
366
|
|
|
365
|
-
const
|
|
367
|
+
const xzyz = 2 * xz * yz;
|
|
366
368
|
const xyyz = 2 * xy * yz;
|
|
369
|
+
const xyxz = 2 * xy * xz;
|
|
367
370
|
const xyxw = 2 * xy * xw;
|
|
368
371
|
const xyyw = 2 * xy * yw;
|
|
369
|
-
// const xyzw_c = 2 * xy * zw; // Unused in rotation matrix
|
|
370
372
|
|
|
371
|
-
const xzyz = 2 * xz * yz;
|
|
372
373
|
const xzxw = 2 * xz * xw;
|
|
373
374
|
const xzyw = 2 * xz * yw;
|
|
374
375
|
const xzzw = 2 * xz * zw;
|
|
@@ -388,40 +389,33 @@ export class Rotor4D {
|
|
|
388
389
|
const ywxyzw = 2 * yw * xyzw;
|
|
389
390
|
const zwxyzw = 2 * zw * xyzw;
|
|
390
391
|
|
|
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;
|
|
392
|
+
// Column-major 4x4 rotation matrix entries (inlined from toMatrix)
|
|
393
|
+
// Column 0
|
|
394
|
+
const m0 = s2 - xy2 - xz2 + yz2 - xw2 + yw2 + zw2 - xyzw2;
|
|
395
|
+
const m1 = sxy + xzyz + xwyw - zwxyzw;
|
|
396
|
+
const m2 = sxz - xyyz + xwzw + ywxyzw;
|
|
397
|
+
const m3 = sxw - xyyw - xzzw - yzxyzw;
|
|
398
|
+
// Column 1
|
|
399
|
+
const m4 = -sxy + xzyz + xwyw + zwxyzw;
|
|
400
|
+
const m5 = s2 - xy2 + xz2 - yz2 + xw2 - yw2 + zw2 - xyzw2;
|
|
401
|
+
const m6 = syz + xyxz + ywzw - xwxyzw;
|
|
402
|
+
const m7 = syw + xyxw - yzzw + xzxyzw;
|
|
403
|
+
// Column 2
|
|
404
|
+
const m8 = -sxz - xyyz + xwzw - ywxyzw;
|
|
405
|
+
const m9 = -syz + xyxz + ywzw + xwxyzw;
|
|
406
|
+
const m10 = s2 + xy2 - xz2 - yz2 + xw2 + yw2 - zw2 - xyzw2;
|
|
407
|
+
const m11 = szw + xzxw + yzyw - xyxyzw;
|
|
408
|
+
// Column 3
|
|
409
|
+
const m12 = -sxw - xyyw - xzzw + yzxyzw;
|
|
410
|
+
const m13 = -syw + xyxw - yzzw - xzxyzw;
|
|
411
|
+
const m14 = -szw + xzxw + yzyw + xyxyzw;
|
|
412
|
+
const m15 = s2 + xy2 + xz2 + yz2 - xw2 - yw2 - zw2 - xyzw2;
|
|
413
|
+
|
|
414
|
+
// Matrix-vector multiply
|
|
415
|
+
const rx = m0 * x + m4 * y + m8 * z + m12 * w;
|
|
416
|
+
const ry = m1 * x + m5 * y + m9 * z + m13 * w;
|
|
417
|
+
const rz = m2 * x + m6 * y + m10 * z + m14 * w;
|
|
418
|
+
const rw = m3 * x + m7 * y + m11 * z + m15 * w;
|
|
425
419
|
|
|
426
420
|
if (target) {
|
|
427
421
|
target.x = rx;
|
|
@@ -430,7 +424,6 @@ export class Rotor4D {
|
|
|
430
424
|
target.w = rw;
|
|
431
425
|
return target;
|
|
432
426
|
}
|
|
433
|
-
|
|
434
427
|
return new Vec4(rx, ry, rz, rw);
|
|
435
428
|
}
|
|
436
429
|
|