@vib3code/sdk 2.0.3-canary.3b3ca18 → 2.0.3-canary.4e0dace

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 (62) 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 +2 -0
  11. package/DOCS/EXPANSION_DESIGN_ULTRA.md +2 -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 +1 -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 +2 -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/geometry/warp/HypersphereCore.js +53 -24
  57. package/src/math/Mat4x4.js +86 -72
  58. package/src/math/Projection.js +39 -4
  59. package/src/math/Rotor4D.js +31 -1
  60. package/src/scene/Node4D.js +74 -24
  61. package/src/testing/ProjectionClass.test.js +38 -0
  62. package/tools/update_projection.py +109 -0
@@ -1,38 +1 @@
1
- # WebGPU status and testing requirements
2
-
3
- This document records the current WebGPU backend state, what is implemented, and what is required
4
- to validate it in local development or CI.
5
-
6
- ## Current status
7
- - **Backend scaffold:** `WebGPUBackend` initializes adapter/device, configures the canvas, manages
8
- resize, and supports a clear-pass `renderFrame()` path.
9
- - **Async context creation:** `createRenderContextAsync()` can instantiate WebGPU contexts using
10
- `{ backend: 'webgpu' }`.
11
- - **Resource tracking:** depth textures are registered in the shared `RenderResourceRegistry`.
12
-
13
- ## What is still needed
14
- 1. **Pipeline parity:** implement basic shader pipelines (vertex/fragment) and buffer binding that
15
- match the WebGL backend command flow.
16
- 2. **Command buffer bridge:** map existing render commands to WebGPU render passes.
17
- 3. **Feature gating:** add host-app controls to toggle WebGPU via feature flags.
18
- 4. **Diagnostics:** add per-frame stats and resource delta reporting for WebGPU.
19
-
20
- ## Testing requirements
21
- ### Local smoke test
22
- Prerequisites:
23
- - A browser with WebGPU enabled (Chrome/Edge with `chrome://flags/#enable-unsafe-webgpu`, or a
24
- Chromium build with WebGPU support).
25
- - A device with WebGPU-capable GPU drivers.
26
-
27
- Suggested smoke flow:
28
- 1. Create a canvas and call `createRenderContextAsync(canvas, { backend: 'webgpu' })`.
29
- 2. Call `backend.renderFrame({ clearColor: [0.1, 0.1, 0.2, 1] })` and confirm the canvas clears.
30
- 3. Resize the canvas and ensure the clear pass still succeeds.
31
-
32
- ### CI validation
33
- - WebGPU cannot be reliably validated in headless CI without GPU support.
34
- - CI should instead run WebGL tests and lint/static checks; keep a manual WebGPU smoke checklist.
35
-
36
- ## File locations
37
- - `src/render/backends/WebGPUBackend.js`
38
- - `src/render/index.js` (`createRenderContextAsync`)
1
+ Last reviewed: 2026-02-17
@@ -1,3 +1,5 @@
1
+ Last reviewed: 2026-02-17
2
+
1
3
  # Dev Track Session — January 31, 2026
2
4
 
3
5
  **Branch**: `claude/review-project-status-BwVbr`
@@ -1,3 +1,5 @@
1
+ Last reviewed: 2026-02-17
2
+
1
3
  # Development Session — 2026-02-06
2
4
 
3
5
  **Session type**: Full codebase audit + hygiene + MCP server + agent docs + testing
@@ -1,3 +1,5 @@
1
+ Last reviewed: 2026-02-17
2
+
1
3
  # Development Session — 2026-02-13
2
4
 
3
5
  **Session type**: Agent Harness Implementation — MCP tools, ChoreographyPlayer, aesthetic mapping, headless rendering
@@ -1,3 +1,5 @@
1
+ Last reviewed: 2026-02-17
2
+
1
3
  # Development Session — 2026-02-15
2
4
 
3
5
  **Session type**: Layer Architecture Redesign, Codebase Audit, Preset/Reactivity Expansion
@@ -1,3 +1,5 @@
1
+ Last reviewed: 2026-02-17
2
+
1
3
  # Development Session — 2026-02-16
2
4
 
3
5
  **Session type**: Architecture Bug Fixes, Shader Consistency, Documentation Sweep
@@ -1,3 +1,5 @@
1
+ Last reviewed: 2026-02-17
2
+
1
3
  # Performance Upgrade Report — 2026-02-16
2
4
 
3
5
  **Type**: CPU-side math optimization (Rotor4D + Vec4)
@@ -1,3 +1,5 @@
1
+ Last reviewed: 2026-02-17
2
+
1
3
  # Development Track Logs
2
4
 
3
5
  Detailed, session-level implementation notes are stored here.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vib3code/sdk",
3
- "version": "2.0.3-canary.3b3ca18",
3
+ "version": "2.0.3-canary.4e0dace",
4
4
  "description": "VIB3+ 4D Visualization SDK - Unified engine with 6D rotation, MCP agentic integration, and cross-platform support",
5
5
  "type": "module",
6
6
  "main": "src/core/VIB3Engine.js",
@@ -9,9 +9,7 @@
9
9
  "vib3": "./src/cli/index.js",
10
10
  "vib3-mcp": "./src/agent/mcp/stdio-server.js"
11
11
  },
12
- "sideEffects": [
13
- "./src/geometry/builders/*.js"
14
- ],
12
+ "sideEffects": false,
15
13
  "exports": {
16
14
  ".": {
17
15
  "types": "./types/adaptive-sdk.d.ts",
package/src/cli/index.js CHANGED
@@ -5,9 +5,34 @@
5
5
  */
6
6
 
7
7
  import { performance } from 'node:perf_hooks';
8
+ import path from 'node:path';
8
9
  import { mcpServer, toolDefinitions } from '../agent/index.js';
9
10
  import { schemaRegistry } from '../schemas/index.js';
10
11
 
12
+ /**
13
+ * Resolves a file path and ensures it is within the current working directory.
14
+ * @param {string} filePath The path to validate
15
+ * @returns {string} The resolved absolute path
16
+ * @throws {Error} If the path is outside the allowed directory
17
+ */
18
+ function getSafePath(filePath) {
19
+ if (!filePath) return filePath;
20
+
21
+ const cwd = process.cwd();
22
+ const resolvedPath = path.resolve(cwd, filePath);
23
+ const relative = path.relative(cwd, resolvedPath);
24
+
25
+ const isOutside = relative.startsWith('..') || path.isAbsolute(relative);
26
+
27
+ if (isOutside) {
28
+ const error = new Error('Security Error: Path traversal detected. Access denied.');
29
+ error.code = 'EACCES';
30
+ throw error;
31
+ }
32
+
33
+ return resolvedPath;
34
+ }
35
+
11
36
  /**
12
37
  * CLI Configuration
13
38
  */
@@ -446,7 +471,7 @@ async function handleTools(parsed, startTime) {
446
471
  */
447
472
  async function handleValidate(parsed, startTime) {
448
473
  const subcommand = parsed.subcommand || 'pack';
449
- const filePath = parsed.options.file || parsed.options.f || parsed.positional[0];
474
+ let filePath = parsed.options.file || parsed.options.f || parsed.positional[0];
450
475
 
451
476
  if (!filePath && subcommand !== 'schema') {
452
477
  return wrapResponse('validate', {
@@ -460,6 +485,10 @@ async function handleValidate(parsed, startTime) {
460
485
  }
461
486
 
462
487
  try {
488
+ if (filePath) {
489
+ filePath = getSafePath(filePath);
490
+ }
491
+
463
492
  switch (subcommand) {
464
493
  case 'pack': {
465
494
  // Validate a .vib3 scene pack file
@@ -533,6 +562,17 @@ async function handleValidate(parsed, startTime) {
533
562
  }, false, performance.now() - startTime);
534
563
  }
535
564
  } catch (error) {
565
+ if (error.code === 'EACCES') {
566
+ return wrapResponse('validate', {
567
+ error: {
568
+ type: 'SecurityError',
569
+ code: 'ACCESS_DENIED',
570
+ message: error.message,
571
+ suggestion: 'Ensure the file path is within the project directory'
572
+ }
573
+ }, false, performance.now() - startTime);
574
+ }
575
+
536
576
  if (error.code === 'ENOENT') {
537
577
  return wrapResponse('validate', {
538
578
  error: {
@@ -659,7 +699,6 @@ async function main() {
659
699
  */
660
700
  async function handleInit(parsed, startTime) {
661
701
  const { writeFileSync, mkdirSync, existsSync } = await import('node:fs');
662
- const { join } = await import('node:path');
663
702
 
664
703
  const projectName = parsed.subcommand || parsed.positional[0] || 'my-vib3-app';
665
704
  const template = parsed.options.template || parsed.options.t || 'vanilla';
@@ -677,7 +716,22 @@ async function handleInit(parsed, startTime) {
677
716
  }, false, performance.now() - startTime);
678
717
  }
679
718
 
680
- const projectDir = join(process.cwd(), projectName);
719
+ let projectDir;
720
+ try {
721
+ projectDir = getSafePath(projectName);
722
+ } catch (error) {
723
+ if (error.code === 'EACCES') {
724
+ return wrapResponse('init', {
725
+ error: {
726
+ type: 'SecurityError',
727
+ code: 'ACCESS_DENIED',
728
+ message: error.message,
729
+ suggestion: 'Choose a project name that results in a valid subdirectory'
730
+ }
731
+ }, false, performance.now() - startTime);
732
+ }
733
+ throw error;
734
+ }
681
735
 
682
736
  if (existsSync(projectDir)) {
683
737
  return wrapResponse('init', {
@@ -695,8 +749,8 @@ async function handleInit(parsed, startTime) {
695
749
  const files = getTemplateFiles(template, projectName);
696
750
 
697
751
  for (const [filename, content] of Object.entries(files)) {
698
- const filepath = join(projectDir, filename);
699
- const dir = join(projectDir, filename.split('/').slice(0, -1).join('/'));
752
+ const filepath = path.join(projectDir, filename);
753
+ const dir = path.join(projectDir, filename.split('/').slice(0, -1).join('/'));
700
754
  if (dir !== projectDir) {
701
755
  mkdirSync(dir, { recursive: true });
702
756
  }
@@ -16,13 +16,14 @@ import { Vec4 } from '../../math/Vec4.js';
16
16
  * @param {number} radius - Hypersphere radius
17
17
  * @returns {Vec4} Point on hypersphere
18
18
  */
19
- export function projectToHypersphere(point, radius = 1) {
19
+ export function projectToHypersphere(point, radius = 1, target = null) {
20
20
  const len = point.length();
21
21
  if (len < 0.0001) {
22
22
  // Handle origin - project to north pole
23
+ if (target) return target.set(0, 0, 0, radius);
23
24
  return new Vec4(0, 0, 0, radius);
24
25
  }
25
- return point.scale(radius / len);
26
+ return point.scale(radius / len, target);
26
27
  }
27
28
 
28
29
  /**
@@ -30,9 +31,10 @@ export function projectToHypersphere(point, radius = 1) {
30
31
  * Maps all of 3D space onto the 4D hypersphere
31
32
  * @param {Vec4} point - Input point (uses x, y, z)
32
33
  * @param {number} radius - Hypersphere radius
34
+ * @param {Vec4} [target=null] - Optional target vector
33
35
  * @returns {Vec4} Point on hypersphere
34
36
  */
35
- export function stereographicToHypersphere(point, radius = 1) {
37
+ export function stereographicToHypersphere(point, radius = 1, target = null) {
36
38
  const x = point.x;
37
39
  const y = point.y;
38
40
  const z = point.z;
@@ -40,6 +42,15 @@ export function stereographicToHypersphere(point, radius = 1) {
40
42
  const sumSq = x * x + y * y + z * z;
41
43
  const denom = sumSq + 1;
42
44
 
45
+ if (target) {
46
+ return target.set(
47
+ (2 * x) / denom * radius,
48
+ (2 * y) / denom * radius,
49
+ (2 * z) / denom * radius,
50
+ (sumSq - 1) / denom * radius
51
+ );
52
+ }
53
+
43
54
  return new Vec4(
44
55
  (2 * x) / denom * radius,
45
56
  (2 * y) / denom * radius,
@@ -56,12 +67,22 @@ export function stereographicToHypersphere(point, radius = 1) {
56
67
  * @param {number} phi - Azimuth on base S² (0 to 2π)
57
68
  * @param {number} psi - Fiber angle (0 to 2π)
58
69
  * @param {number} radius - Hypersphere radius
70
+ * @param {Vec4} [target=null] - Optional target vector
59
71
  * @returns {Vec4} Point on hypersphere
60
72
  */
61
- export function hopfFibration(theta, phi, psi, radius = 1) {
73
+ export function hopfFibration(theta, phi, psi, radius = 1, target = null) {
62
74
  const cosTheta2 = Math.cos(theta / 2);
63
75
  const sinTheta2 = Math.sin(theta / 2);
64
76
 
77
+ if (target) {
78
+ return target.set(
79
+ cosTheta2 * Math.cos((phi + psi) / 2) * radius,
80
+ cosTheta2 * Math.sin((phi + psi) / 2) * radius,
81
+ sinTheta2 * Math.cos((phi - psi) / 2) * radius,
82
+ sinTheta2 * Math.sin((phi - psi) / 2) * radius
83
+ );
84
+ }
85
+
65
86
  return new Vec4(
66
87
  cosTheta2 * Math.cos((phi + psi) / 2) * radius,
67
88
  cosTheta2 * Math.sin((phi + psi) / 2) * radius,
@@ -78,8 +99,9 @@ export function hopfFibration(theta, phi, psi, radius = 1) {
78
99
  * @returns {Vec4[]} Warped vertices
79
100
  */
80
101
  export function warpRadial(vertices, radius = 1, blendFactor = 1) {
102
+ const onSphere = new Vec4();
81
103
  return vertices.map(v => {
82
- const onSphere = projectToHypersphere(v, radius);
104
+ projectToHypersphere(v, radius, onSphere);
83
105
  return v.lerp(onSphere, blendFactor);
84
106
  });
85
107
  }
@@ -93,8 +115,9 @@ export function warpRadial(vertices, radius = 1, blendFactor = 1) {
93
115
  * @returns {Vec4[]} Warped vertices
94
116
  */
95
117
  export function warpStereographic(vertices, radius = 1, scale = 1) {
118
+ const scaled = new Vec4();
96
119
  return vertices.map(v => {
97
- const scaled = v.scale(scale);
120
+ v.scale(scale, scaled);
98
121
  return stereographicToHypersphere(scaled, radius);
99
122
  });
100
123
  }
@@ -146,25 +169,31 @@ export function warpHypersphereCore(geometry, options = {}) {
146
169
  twist = 1
147
170
  } = options;
148
171
 
149
- let warpedVertices;
150
-
151
- // Pre-scale vertices
152
- const scaledVertices = geometry.vertices.map(v => v.scale(scale));
153
-
154
- switch (method) {
155
- case 'stereographic':
156
- warpedVertices = warpStereographic(scaledVertices, radius, 1);
157
- break;
158
-
159
- case 'hopf':
160
- warpedVertices = warpHopf(scaledVertices, radius, twist);
161
- break;
172
+ const temp = new Vec4();
173
+ const warpedVertices = geometry.vertices.map(v => {
174
+ // Combined scaling and warping to minimize allocations
175
+ const result = v.scale(scale);
176
+
177
+ if (method === 'stereographic') {
178
+ stereographicToHypersphere(result, radius, result);
179
+ } else if (method === 'hopf') {
180
+ const r = result.length();
181
+ if (r < 0.0001) {
182
+ result.set(0, 0, 0, radius);
183
+ } else {
184
+ const theta = Math.acos(result.z / r);
185
+ const phi = Math.atan2(result.y, result.x);
186
+ const psi = result.w * twist + phi * 0.5;
187
+ hopfFibration(theta, phi, psi, radius, result);
188
+ }
189
+ } else {
190
+ // Radial (default)
191
+ projectToHypersphere(result, radius, temp);
192
+ result.lerp(temp, blend, result);
193
+ }
162
194
 
163
- case 'radial':
164
- default:
165
- warpedVertices = warpRadial(scaledVertices, radius, blend);
166
- break;
167
- }
195
+ return result;
196
+ });
168
197
 
169
198
  return {
170
199
  ...geometry,
@@ -18,6 +18,12 @@
18
18
  import { Vec4 } from './Vec4.js';
19
19
 
20
20
  export class Mat4x4 {
21
+ /**
22
+ * Internal token to skip initialization during construction
23
+ * @private
24
+ */
25
+ static UNINITIALIZED = {};
26
+
21
27
  /**
22
28
  * Create a new 4x4 matrix
23
29
  * Default is identity matrix
@@ -26,6 +32,8 @@ export class Mat4x4 {
26
32
  constructor(elements = null) {
27
33
  this.data = new Float32Array(16);
28
34
 
35
+ if (elements === Mat4x4.UNINITIALIZED) return;
36
+
29
37
  if (elements) {
30
38
  if (elements.length !== 16) {
31
39
  throw new Error('Mat4x4 requires exactly 16 elements');
@@ -45,12 +53,7 @@ export class Mat4x4 {
45
53
  * @returns {Mat4x4}
46
54
  */
47
55
  static identity() {
48
- return new Mat4x4([
49
- 1, 0, 0, 0,
50
- 0, 1, 0, 0,
51
- 0, 0, 1, 0,
52
- 0, 0, 0, 1
53
- ]);
56
+ return new Mat4x4();
54
57
  }
55
58
 
56
59
  /**
@@ -58,7 +61,7 @@ export class Mat4x4 {
58
61
  * @returns {Mat4x4}
59
62
  */
60
63
  static zero() {
61
- return new Mat4x4(new Float32Array(16));
64
+ return new Mat4x4(Mat4x4.UNINITIALIZED);
62
65
  }
63
66
 
64
67
  /**
@@ -161,7 +164,7 @@ export class Mat4x4 {
161
164
  * @returns {Mat4x4} New matrix = this * m
162
165
  */
163
166
  multiply(m, target = null) {
164
- const out = target || new Mat4x4();
167
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
165
168
  const r = out.data;
166
169
  const a = this.data;
167
170
  const b = m.data;
@@ -321,7 +324,7 @@ export class Mat4x4 {
321
324
  * @returns {Mat4x4} New matrix
322
325
  */
323
326
  add(m, target = null) {
324
- const out = target || new Mat4x4();
327
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
325
328
  const r = out.data;
326
329
  const a = this.data;
327
330
  const b = m.data;
@@ -339,7 +342,7 @@ export class Mat4x4 {
339
342
  * @returns {Mat4x4} New matrix
340
343
  */
341
344
  scale(s, target = null) {
342
- const out = target || new Mat4x4();
345
+ const out = target || new Mat4x4(Mat4x4.UNINITIALIZED);
343
346
  const r = out.data;
344
347
  const a = this.data;
345
348
 
@@ -355,12 +358,13 @@ export class Mat4x4 {
355
358
  */
356
359
  transpose() {
357
360
  const m = this.data;
358
- return new Mat4x4([
359
- m[0], m[4], m[8], m[12],
360
- m[1], m[5], m[9], m[13],
361
- m[2], m[6], m[10], m[14],
362
- m[3], m[7], m[11], m[15]
363
- ]);
361
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
362
+ const r = out.data;
363
+ r[0] = m[0]; r[4] = m[1]; r[8] = m[2]; r[12] = m[3];
364
+ r[1] = m[4]; r[5] = m[5]; r[9] = m[6]; r[13] = m[7];
365
+ r[2] = m[8]; r[6] = m[9]; r[10] = m[10]; r[14] = m[11];
366
+ r[3] = m[12]; r[7] = m[13]; r[11] = m[14]; r[15] = m[15];
367
+ return out;
364
368
  }
365
369
 
366
370
  /**
@@ -415,7 +419,8 @@ export class Mat4x4 {
415
419
  */
416
420
  inverse() {
417
421
  const m = this.data;
418
- const inv = new Float32Array(16);
422
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
423
+ const inv = out.data;
419
424
 
420
425
  inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] +
421
426
  m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
@@ -476,7 +481,7 @@ export class Mat4x4 {
476
481
  inv[i] *= invDet;
477
482
  }
478
483
 
479
- return new Mat4x4(inv);
484
+ return out;
480
485
  }
481
486
 
482
487
  /**
@@ -689,12 +694,13 @@ export class Mat4x4 {
689
694
  static rotationXY(angle) {
690
695
  const c = Math.cos(angle);
691
696
  const s = Math.sin(angle);
692
- return new Mat4x4([
693
- c, s, 0, 0,
694
- -s, c, 0, 0,
695
- 0, 0, 1, 0,
696
- 0, 0, 0, 1
697
- ]);
697
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
698
+ const r = out.data;
699
+ r[0] = c; r[1] = s;
700
+ r[4] = -s; r[5] = c;
701
+ r[10] = 1;
702
+ r[15] = 1;
703
+ return out;
698
704
  }
699
705
 
700
706
  /**
@@ -705,12 +711,13 @@ export class Mat4x4 {
705
711
  static rotationXZ(angle) {
706
712
  const c = Math.cos(angle);
707
713
  const s = Math.sin(angle);
708
- return new Mat4x4([
709
- c, 0, -s, 0,
710
- 0, 1, 0, 0,
711
- s, 0, c, 0,
712
- 0, 0, 0, 1
713
- ]);
714
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
715
+ const r = out.data;
716
+ r[0] = c; r[2] = -s;
717
+ r[5] = 1;
718
+ r[8] = s; r[10] = c;
719
+ r[15] = 1;
720
+ return out;
714
721
  }
715
722
 
716
723
  /**
@@ -721,12 +728,13 @@ export class Mat4x4 {
721
728
  static rotationYZ(angle) {
722
729
  const c = Math.cos(angle);
723
730
  const s = Math.sin(angle);
724
- return new Mat4x4([
725
- 1, 0, 0, 0,
726
- 0, c, s, 0,
727
- 0, -s, c, 0,
728
- 0, 0, 0, 1
729
- ]);
731
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
732
+ const r = out.data;
733
+ r[0] = 1;
734
+ r[5] = c; r[6] = s;
735
+ r[9] = -s; r[10] = c;
736
+ r[15] = 1;
737
+ return out;
730
738
  }
731
739
 
732
740
  /**
@@ -738,12 +746,13 @@ export class Mat4x4 {
738
746
  static rotationXW(angle) {
739
747
  const c = Math.cos(angle);
740
748
  const s = Math.sin(angle);
741
- return new Mat4x4([
742
- c, 0, 0, s,
743
- 0, 1, 0, 0,
744
- 0, 0, 1, 0,
745
- -s, 0, 0, c
746
- ]);
749
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
750
+ const r = out.data;
751
+ r[0] = c; r[3] = s;
752
+ r[5] = 1;
753
+ r[10] = 1;
754
+ r[12] = -s; r[15] = c;
755
+ return out;
747
756
  }
748
757
 
749
758
  /**
@@ -754,12 +763,13 @@ export class Mat4x4 {
754
763
  static rotationYW(angle) {
755
764
  const c = Math.cos(angle);
756
765
  const s = Math.sin(angle);
757
- return new Mat4x4([
758
- 1, 0, 0, 0,
759
- 0, c, 0, s,
760
- 0, 0, 1, 0,
761
- 0, -s, 0, c
762
- ]);
766
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
767
+ const r = out.data;
768
+ r[0] = 1;
769
+ r[5] = c; r[7] = s;
770
+ r[10] = 1;
771
+ r[13] = -s; r[15] = c;
772
+ return out;
763
773
  }
764
774
 
765
775
  /**
@@ -770,12 +780,13 @@ export class Mat4x4 {
770
780
  static rotationZW(angle) {
771
781
  const c = Math.cos(angle);
772
782
  const s = Math.sin(angle);
773
- return new Mat4x4([
774
- 1, 0, 0, 0,
775
- 0, 1, 0, 0,
776
- 0, 0, c, s,
777
- 0, 0, -s, c
778
- ]);
783
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
784
+ const r = out.data;
785
+ r[0] = 1;
786
+ r[5] = 1;
787
+ r[10] = c; r[11] = s;
788
+ r[14] = -s; r[15] = c;
789
+ return out;
779
790
  }
780
791
 
781
792
  /**
@@ -847,12 +858,13 @@ export class Mat4x4 {
847
858
  * @returns {Mat4x4}
848
859
  */
849
860
  static uniformScale(s) {
850
- return new Mat4x4([
851
- s, 0, 0, 0,
852
- 0, s, 0, 0,
853
- 0, 0, s, 0,
854
- 0, 0, 0, s
855
- ]);
861
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
862
+ const r = out.data;
863
+ r[0] = s;
864
+ r[5] = s;
865
+ r[10] = s;
866
+ r[15] = s;
867
+ return out;
856
868
  }
857
869
 
858
870
  /**
@@ -864,12 +876,13 @@ export class Mat4x4 {
864
876
  * @returns {Mat4x4}
865
877
  */
866
878
  static scale(sx, sy, sz, sw = 1) {
867
- return new Mat4x4([
868
- sx, 0, 0, 0,
869
- 0, sy, 0, 0,
870
- 0, 0, sz, 0,
871
- 0, 0, 0, sw
872
- ]);
879
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
880
+ const r = out.data;
881
+ r[0] = sx;
882
+ r[5] = sy;
883
+ r[10] = sz;
884
+ r[15] = sw;
885
+ return out;
873
886
  }
874
887
 
875
888
  /**
@@ -885,12 +898,13 @@ export class Mat4x4 {
885
898
  static translation(tx, ty, tz, tw = 0) {
886
899
  // For true 4D translation, you need 5D homogeneous coordinates
887
900
  // This is a placeholder that adds the translation to the W column
888
- return new Mat4x4([
889
- 1, 0, 0, 0,
890
- 0, 1, 0, 0,
891
- 0, 0, 1, 0,
892
- tx, ty, tz, 1 + tw
893
- ]);
901
+ const out = new Mat4x4(Mat4x4.UNINITIALIZED);
902
+ const r = out.data;
903
+ r[0] = 1;
904
+ r[5] = 1;
905
+ r[10] = 1;
906
+ r[12] = tx; r[13] = ty; r[14] = tz; r[15] = 1 + tw;
907
+ return out;
894
908
  }
895
909
  }
896
910