@holoscript/std 6.0.3 → 7.0.1

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 (128) hide show
  1. package/README.md +8 -0
  2. package/dist/chunk-DGUM43GV.js +11 -0
  3. package/dist/chunk-DGUM43GV.js.map +1 -0
  4. package/dist/{chunk-PFX2JM4X.js → chunk-FAMOLKH3.js} +2 -1
  5. package/dist/{chunk-PFX2JM4X.js.map → chunk-FAMOLKH3.js.map} +1 -1
  6. package/dist/{chunk-7HVUYGPS.js → chunk-SOKH6FJ7.js} +37 -5
  7. package/dist/chunk-SOKH6FJ7.js.map +1 -0
  8. package/dist/{chunk-W2Q3LUCM.js → chunk-XJIFG7G3.js} +3 -3
  9. package/dist/chunk-XJIFG7G3.js.map +1 -0
  10. package/dist/collections.cjs +1 -0
  11. package/dist/collections.cjs.map +1 -1
  12. package/dist/collections.js +2 -1
  13. package/dist/fs/fs.d.ts +288 -0
  14. package/dist/fs/fs.d.ts.map +1 -0
  15. package/dist/fs/index.cjs +1049 -0
  16. package/dist/fs/index.cjs.map +1 -0
  17. package/dist/fs/index.d.ts +51 -0
  18. package/dist/fs/index.d.ts.map +1 -0
  19. package/dist/fs/index.js +918 -0
  20. package/dist/fs/index.js.map +1 -0
  21. package/dist/fs/path.d.ts +135 -0
  22. package/dist/fs/path.d.ts.map +1 -0
  23. package/dist/fs/sandbox.d.ts +49 -0
  24. package/dist/fs/sandbox.d.ts.map +1 -0
  25. package/dist/fs/watch.d.ts +133 -0
  26. package/dist/fs/watch.d.ts.map +1 -0
  27. package/dist/index.cjs +54 -7
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.js +19 -4
  30. package/dist/index.js.map +1 -1
  31. package/dist/math.cjs +21 -2
  32. package/dist/math.cjs.map +1 -1
  33. package/dist/math.js +2 -1
  34. package/dist/string.cjs +2 -2
  35. package/dist/string.cjs.map +1 -1
  36. package/dist/string.js +2 -1
  37. package/dist/time.js +1 -0
  38. package/dist/traits/EconomicPrimitives.js +1 -0
  39. package/dist/traits/EconomicTraits.js +1 -0
  40. package/dist/traits/VRRTraits.d.ts +2 -2
  41. package/dist/types.d.ts.map +1 -1
  42. package/package.json +24 -9
  43. package/CHANGELOG.md +0 -7
  44. package/dist/__tests__/EconomicPrimitives.test.d.ts +0 -2
  45. package/dist/__tests__/EconomicPrimitives.test.d.ts.map +0 -1
  46. package/dist/__tests__/EconomicTraits.test.d.ts +0 -2
  47. package/dist/__tests__/EconomicTraits.test.d.ts.map +0 -1
  48. package/dist/__tests__/SimulationLabPrimitives.test.d.ts +0 -2
  49. package/dist/__tests__/SimulationLabPrimitives.test.d.ts.map +0 -1
  50. package/dist/__tests__/collections.test.d.ts +0 -2
  51. package/dist/__tests__/collections.test.d.ts.map +0 -1
  52. package/dist/__tests__/events.test.d.ts +0 -2
  53. package/dist/__tests__/events.test.d.ts.map +0 -1
  54. package/dist/__tests__/index.test.d.ts +0 -2
  55. package/dist/__tests__/index.test.d.ts.map +0 -1
  56. package/dist/__tests__/materials.test.d.ts +0 -2
  57. package/dist/__tests__/materials.test.d.ts.map +0 -1
  58. package/dist/__tests__/math.test.d.ts +0 -2
  59. package/dist/__tests__/math.test.d.ts.map +0 -1
  60. package/dist/__tests__/physics.test.d.ts +0 -2
  61. package/dist/__tests__/physics.test.d.ts.map +0 -1
  62. package/dist/__tests__/spatial.test.d.ts +0 -2
  63. package/dist/__tests__/spatial.test.d.ts.map +0 -1
  64. package/dist/__tests__/standard-library-fundamentals.test.d.ts +0 -2
  65. package/dist/__tests__/standard-library-fundamentals.test.d.ts.map +0 -1
  66. package/dist/__tests__/string-and-time-utilities.test.d.ts +0 -2
  67. package/dist/__tests__/string-and-time-utilities.test.d.ts.map +0 -1
  68. package/dist/__tests__/string-decoupled.test.d.ts +0 -2
  69. package/dist/__tests__/string-decoupled.test.d.ts.map +0 -1
  70. package/dist/__tests__/string.test.d.ts +0 -2
  71. package/dist/__tests__/string.test.d.ts.map +0 -1
  72. package/dist/__tests__/time.test.d.ts +0 -2
  73. package/dist/__tests__/time.test.d.ts.map +0 -1
  74. package/dist/chunk-7HVUYGPS.js.map +0 -1
  75. package/dist/chunk-W2Q3LUCM.js.map +0 -1
  76. package/dist/string.basic.test.d.ts +0 -5
  77. package/dist/string.basic.test.d.ts.map +0 -1
  78. package/dist/string.test.d.ts +0 -5
  79. package/dist/string.test.d.ts.map +0 -1
  80. package/dist/traits/__tests__/ARTraits.test.d.ts +0 -2
  81. package/dist/traits/__tests__/ARTraits.test.d.ts.map +0 -1
  82. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts +0 -2
  83. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts.map +0 -1
  84. package/dist/traits/__tests__/EconomicTraits.test.d.ts +0 -2
  85. package/dist/traits/__tests__/EconomicTraits.test.d.ts.map +0 -1
  86. package/error-utf8.log +0 -6
  87. package/error.log +0 -0
  88. package/src/__tests__/EconomicPrimitives.test.ts +0 -690
  89. package/src/__tests__/EconomicTraits.test.ts +0 -425
  90. package/src/__tests__/SimulationLabPrimitives.test.ts +0 -415
  91. package/src/__tests__/collections.test.ts +0 -182
  92. package/src/__tests__/events.test.ts +0 -135
  93. package/src/__tests__/index.test.ts +0 -14
  94. package/src/__tests__/materials.test.ts +0 -84
  95. package/src/__tests__/math.test.ts +0 -246
  96. package/src/__tests__/physics.test.ts +0 -83
  97. package/src/__tests__/spatial.test.ts +0 -333
  98. package/src/__tests__/standard-library-fundamentals.test.ts +0 -1301
  99. package/src/__tests__/string-and-time-utilities.test.ts +0 -1070
  100. package/src/__tests__/string-decoupled.test.ts +0 -14
  101. package/src/__tests__/string.test.ts +0 -164
  102. package/src/__tests__/time.test.ts +0 -110
  103. package/src/collections.ts +0 -850
  104. package/src/events.ts +0 -88
  105. package/src/index.ts +0 -474
  106. package/src/materials.ts +0 -109
  107. package/src/math.ts +0 -674
  108. package/src/physics.ts +0 -141
  109. package/src/spatial.ts +0 -320
  110. package/src/string.basic.test.ts +0 -14
  111. package/src/string.test.ts +0 -335
  112. package/src/string.ts +0 -531
  113. package/src/time.ts +0 -621
  114. package/src/traits/ARTraits.ts +0 -103
  115. package/src/traits/EconomicPrimitives.ts +0 -755
  116. package/src/traits/EconomicTraits.ts +0 -552
  117. package/src/traits/IoTTraits.ts +0 -102
  118. package/src/traits/SimulationLabPrimitives.ts +0 -650
  119. package/src/traits/SimulationLabTraits.ts +0 -191
  120. package/src/traits/VRRTraits.ts +0 -326
  121. package/src/traits/__tests__/ARTraits.test.ts +0 -14
  122. package/src/traits/__tests__/EconomicPrimitives.test.ts +0 -14
  123. package/src/traits/__tests__/EconomicTraits.test.ts +0 -14
  124. package/src/types.ts +0 -411
  125. package/std_error.log +0 -5
  126. package/tsconfig.json +0 -18
  127. package/tsup.config.ts +0 -17
  128. package/vitest.config.ts +0 -10
package/src/math.ts DELETED
@@ -1,674 +0,0 @@
1
- /**
2
- * Math utilities for HoloScript
3
- *
4
- * Vector math, quaternion operations, interpolation, and noise functions.
5
- */
6
-
7
- import type { Vec2, Vec3, Quat, EulerAngles, AABB } from './types.js';
8
- import { vec3, quat } from './types.js';
9
-
10
- // =============================================================================
11
- // CONSTANTS
12
- // =============================================================================
13
-
14
- export const PI = Math.PI;
15
- export const TAU = Math.PI * 2;
16
- export const HALF_PI = Math.PI / 2;
17
- export const DEG_TO_RAD = Math.PI / 180;
18
- export const RAD_TO_DEG = 180 / Math.PI;
19
- export const EPSILON = 1e-6;
20
-
21
- // =============================================================================
22
- // BASIC MATH
23
- // =============================================================================
24
-
25
- export function clamp(value: number, min: number, max: number): number {
26
- return Math.max(min, Math.min(max, value));
27
- }
28
-
29
- export function lerp(a: number, b: number, t: number): number {
30
- return a + (b - a) * t;
31
- }
32
-
33
- export function inverseLerp(a: number, b: number, value: number): number {
34
- return (value - a) / (b - a);
35
- }
36
-
37
- export function remap(
38
- value: number,
39
- inMin: number,
40
- inMax: number,
41
- outMin: number,
42
- outMax: number
43
- ): number {
44
- return lerp(outMin, outMax, inverseLerp(inMin, inMax, value));
45
- }
46
-
47
- export function smoothstep(edge0: number, edge1: number, x: number): number {
48
- const t = clamp((x - edge0) / (edge1 - edge0), 0, 1);
49
- return t * t * (3 - 2 * t);
50
- }
51
-
52
- export function smootherstep(edge0: number, edge1: number, x: number): number {
53
- const t = clamp((x - edge0) / (edge1 - edge0), 0, 1);
54
- return t * t * t * (t * (t * 6 - 15) + 10);
55
- }
56
-
57
- export function degToRad(degrees: number): number {
58
- return degrees * DEG_TO_RAD;
59
- }
60
-
61
- export function radToDeg(radians: number): number {
62
- return radians * RAD_TO_DEG;
63
- }
64
-
65
- export function mod(n: number, m: number): number {
66
- return ((n % m) + m) % m;
67
- }
68
-
69
- export function fract(x: number): number {
70
- return x - Math.floor(x);
71
- }
72
-
73
- export function sign(x: number): number {
74
- return x > 0 ? 1 : x < 0 ? -1 : 0;
75
- }
76
-
77
- export function step(edge: number, x: number): number {
78
- return x < edge ? 0 : 1;
79
- }
80
-
81
- // =============================================================================
82
- // VEC2 OPERATIONS
83
- // =============================================================================
84
-
85
- export const vec2Math = {
86
- add: (a: Vec2, b: Vec2): Vec2 => ({ x: a.x + b.x, y: a.y + b.y }),
87
- sub: (a: Vec2, b: Vec2): Vec2 => ({ x: a.x - b.x, y: a.y - b.y }),
88
- mul: (a: Vec2, s: number): Vec2 => ({ x: a.x * s, y: a.y * s }),
89
- div: (a: Vec2, s: number): Vec2 => ({ x: a.x / s, y: a.y / s }),
90
- dot: (a: Vec2, b: Vec2): number => a.x * b.x + a.y * b.y,
91
- length: (v: Vec2): number => Math.sqrt(v.x * v.x + v.y * v.y),
92
- lengthSq: (v: Vec2): number => v.x * v.x + v.y * v.y,
93
- normalize: (v: Vec2): Vec2 => {
94
- const len = vec2Math.length(v);
95
- return len > 0 ? vec2Math.div(v, len) : { x: 0, y: 0 };
96
- },
97
- distance: (a: Vec2, b: Vec2): number => vec2Math.length(vec2Math.sub(a, b)),
98
- lerp: (a: Vec2, b: Vec2, t: number): Vec2 => ({
99
- x: lerp(a.x, b.x, t),
100
- y: lerp(a.y, b.y, t),
101
- }),
102
- rotate: (v: Vec2, angle: number): Vec2 => {
103
- const c = Math.cos(angle);
104
- const s = Math.sin(angle);
105
- return { x: v.x * c - v.y * s, y: v.x * s + v.y * c };
106
- },
107
- angle: (v: Vec2): number => Math.atan2(v.y, v.x),
108
- angleBetween: (a: Vec2, b: Vec2): number => {
109
- return Math.acos(clamp(vec2Math.dot(vec2Math.normalize(a), vec2Math.normalize(b)), -1, 1));
110
- },
111
- };
112
-
113
- // =============================================================================
114
- // VEC3 OPERATIONS
115
- // =============================================================================
116
-
117
- export const vec3Math = {
118
- zero: (): Vec3 => vec3(0, 0, 0),
119
- one: (): Vec3 => vec3(1, 1, 1),
120
- up: (): Vec3 => vec3(0, 1, 0),
121
- down: (): Vec3 => vec3(0, -1, 0),
122
- forward: (): Vec3 => vec3(0, 0, -1),
123
- back: (): Vec3 => vec3(0, 0, 1),
124
- left: (): Vec3 => vec3(-1, 0, 0),
125
- right: (): Vec3 => vec3(1, 0, 0),
126
-
127
- add: (a: Vec3, b: Vec3): Vec3 => ({ x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }),
128
- sub: (a: Vec3, b: Vec3): Vec3 => ({ x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }),
129
- mul: (a: Vec3, s: number): Vec3 => ({ x: a.x * s, y: a.y * s, z: a.z * s }),
130
- div: (a: Vec3, s: number): Vec3 => ({ x: a.x / s, y: a.y / s, z: a.z / s }),
131
- mulVec: (a: Vec3, b: Vec3): Vec3 => ({ x: a.x * b.x, y: a.y * b.y, z: a.z * b.z }),
132
-
133
- dot: (a: Vec3, b: Vec3): number => a.x * b.x + a.y * b.y + a.z * b.z,
134
-
135
- cross: (a: Vec3, b: Vec3): Vec3 => ({
136
- x: a.y * b.z - a.z * b.y,
137
- y: a.z * b.x - a.x * b.z,
138
- z: a.x * b.y - a.y * b.x,
139
- }),
140
-
141
- length: (v: Vec3): number => Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z),
142
- lengthSq: (v: Vec3): number => v.x * v.x + v.y * v.y + v.z * v.z,
143
-
144
- normalize: (v: Vec3): Vec3 => {
145
- const len = vec3Math.length(v);
146
- return len > EPSILON ? vec3Math.div(v, len) : vec3(0, 0, 0);
147
- },
148
-
149
- distance: (a: Vec3, b: Vec3): number => vec3Math.length(vec3Math.sub(a, b)),
150
- distanceSq: (a: Vec3, b: Vec3): number => vec3Math.lengthSq(vec3Math.sub(a, b)),
151
-
152
- lerp: (a: Vec3, b: Vec3, t: number): Vec3 => ({
153
- x: lerp(a.x, b.x, t),
154
- y: lerp(a.y, b.y, t),
155
- z: lerp(a.z, b.z, t),
156
- }),
157
-
158
- slerp: (a: Vec3, b: Vec3, t: number): Vec3 => {
159
- const dot = clamp(vec3Math.dot(a, b), -1, 1);
160
- const theta = Math.acos(dot) * t;
161
- const relative = vec3Math.normalize(vec3Math.sub(b, vec3Math.mul(a, dot)));
162
- return vec3Math.add(vec3Math.mul(a, Math.cos(theta)), vec3Math.mul(relative, Math.sin(theta)));
163
- },
164
-
165
- negate: (v: Vec3): Vec3 => ({ x: -v.x, y: -v.y, z: -v.z }),
166
-
167
- abs: (v: Vec3): Vec3 => ({ x: Math.abs(v.x), y: Math.abs(v.y), z: Math.abs(v.z) }),
168
-
169
- min: (a: Vec3, b: Vec3): Vec3 => ({
170
- x: Math.min(a.x, b.x),
171
- y: Math.min(a.y, b.y),
172
- z: Math.min(a.z, b.z),
173
- }),
174
-
175
- max: (a: Vec3, b: Vec3): Vec3 => ({
176
- x: Math.max(a.x, b.x),
177
- y: Math.max(a.y, b.y),
178
- z: Math.max(a.z, b.z),
179
- }),
180
-
181
- clamp: (v: Vec3, min: Vec3, max: Vec3): Vec3 => ({
182
- x: clamp(v.x, min.x, max.x),
183
- y: clamp(v.y, min.y, max.y),
184
- z: clamp(v.z, min.z, max.z),
185
- }),
186
-
187
- floor: (v: Vec3): Vec3 => ({
188
- x: Math.floor(v.x),
189
- y: Math.floor(v.y),
190
- z: Math.floor(v.z),
191
- }),
192
-
193
- ceil: (v: Vec3): Vec3 => ({
194
- x: Math.ceil(v.x),
195
- y: Math.ceil(v.y),
196
- z: Math.ceil(v.z),
197
- }),
198
-
199
- round: (v: Vec3): Vec3 => ({
200
- x: Math.round(v.x),
201
- y: Math.round(v.y),
202
- z: Math.round(v.z),
203
- }),
204
-
205
- reflect: (v: Vec3, normal: Vec3): Vec3 => {
206
- const dot = vec3Math.dot(v, normal);
207
- return vec3Math.sub(v, vec3Math.mul(normal, 2 * dot));
208
- },
209
-
210
- project: (v: Vec3, onto: Vec3): Vec3 => {
211
- const dot = vec3Math.dot(v, onto);
212
- const lenSq = vec3Math.lengthSq(onto);
213
- return vec3Math.mul(onto, dot / lenSq);
214
- },
215
-
216
- angle: (a: Vec3, b: Vec3): number => {
217
- const dot = vec3Math.dot(vec3Math.normalize(a), vec3Math.normalize(b));
218
- return Math.acos(clamp(dot, -1, 1));
219
- },
220
-
221
- equals: (a: Vec3, b: Vec3, epsilon: number = EPSILON): boolean => {
222
- return (
223
- Math.abs(a.x - b.x) < epsilon &&
224
- Math.abs(a.y - b.y) < epsilon &&
225
- Math.abs(a.z - b.z) < epsilon
226
- );
227
- },
228
- };
229
-
230
- // =============================================================================
231
- // QUATERNION OPERATIONS
232
- // =============================================================================
233
-
234
- export const quatMath = {
235
- identity: (): Quat => quat(0, 0, 0, 1),
236
-
237
- fromAxisAngle: (axis: Vec3, angle: number): Quat => {
238
- const halfAngle = angle / 2;
239
- const s = Math.sin(halfAngle);
240
- const normalized = vec3Math.normalize(axis);
241
- return {
242
- x: normalized.x * s,
243
- y: normalized.y * s,
244
- z: normalized.z * s,
245
- w: Math.cos(halfAngle),
246
- };
247
- },
248
-
249
- fromEuler: (euler: EulerAngles): Quat => {
250
- const { x, y, z } = euler;
251
- const c1 = Math.cos(degToRad(x) / 2);
252
- const c2 = Math.cos(degToRad(y) / 2);
253
- const c3 = Math.cos(degToRad(z) / 2);
254
- const s1 = Math.sin(degToRad(x) / 2);
255
- const s2 = Math.sin(degToRad(y) / 2);
256
- const s3 = Math.sin(degToRad(z) / 2);
257
-
258
- return {
259
- x: s1 * c2 * c3 + c1 * s2 * s3,
260
- y: c1 * s2 * c3 - s1 * c2 * s3,
261
- z: c1 * c2 * s3 + s1 * s2 * c3,
262
- w: c1 * c2 * c3 - s1 * s2 * s3,
263
- };
264
- },
265
-
266
- toEuler: (q: Quat): EulerAngles => {
267
- const sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
268
- const cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
269
- const x = Math.atan2(sinr_cosp, cosr_cosp);
270
-
271
- const sinp = 2 * (q.w * q.y - q.z * q.x);
272
- let y: number;
273
- if (Math.abs(sinp) >= 1) {
274
- y = (Math.PI / 2) * Math.sign(sinp);
275
- } else {
276
- y = Math.asin(sinp);
277
- }
278
-
279
- const siny_cosp = 2 * (q.w * q.z + q.x * q.y);
280
- const cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
281
- const z = Math.atan2(siny_cosp, cosy_cosp);
282
-
283
- return {
284
- x: radToDeg(x),
285
- y: radToDeg(y),
286
- z: radToDeg(z),
287
- };
288
- },
289
-
290
- multiply: (a: Quat, b: Quat): Quat => ({
291
- x: a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
292
- y: a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
293
- z: a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
294
- w: a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
295
- }),
296
-
297
- conjugate: (q: Quat): Quat => ({ x: -q.x, y: -q.y, z: -q.z, w: q.w }),
298
-
299
- inverse: (q: Quat): Quat => {
300
- const lenSq = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
301
- return {
302
- x: -q.x / lenSq,
303
- y: -q.y / lenSq,
304
- z: -q.z / lenSq,
305
- w: q.w / lenSq,
306
- };
307
- },
308
-
309
- normalize: (q: Quat): Quat => {
310
- const len = Math.sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
311
- return { x: q.x / len, y: q.y / len, z: q.z / len, w: q.w / len };
312
- },
313
-
314
- dot: (a: Quat, b: Quat): number => a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w,
315
-
316
- slerp: (a: Quat, b: Quat, t: number): Quat => {
317
- let dot = quatMath.dot(a, b);
318
-
319
- // If dot is negative, negate one quaternion to take shorter path
320
- let bAdjusted = b;
321
- if (dot < 0) {
322
- bAdjusted = { x: -b.x, y: -b.y, z: -b.z, w: -b.w };
323
- dot = -dot;
324
- }
325
-
326
- if (dot > 0.9995) {
327
- // Linear interpolation for very close quaternions
328
- return quatMath.normalize({
329
- x: lerp(a.x, bAdjusted.x, t),
330
- y: lerp(a.y, bAdjusted.y, t),
331
- z: lerp(a.z, bAdjusted.z, t),
332
- w: lerp(a.w, bAdjusted.w, t),
333
- });
334
- }
335
-
336
- const theta0 = Math.acos(dot);
337
- const theta = theta0 * t;
338
- const sinTheta = Math.sin(theta);
339
- const sinTheta0 = Math.sin(theta0);
340
-
341
- const s0 = Math.cos(theta) - (dot * sinTheta) / sinTheta0;
342
- const s1 = sinTheta / sinTheta0;
343
-
344
- return {
345
- x: a.x * s0 + bAdjusted.x * s1,
346
- y: a.y * s0 + bAdjusted.y * s1,
347
- z: a.z * s0 + bAdjusted.z * s1,
348
- w: a.w * s0 + bAdjusted.w * s1,
349
- };
350
- },
351
-
352
- rotateVec3: (q: Quat, v: Vec3): Vec3 => {
353
- const qv = { x: q.x, y: q.y, z: q.z };
354
- const uv = vec3Math.cross(qv, v);
355
- const uuv = vec3Math.cross(qv, uv);
356
- return vec3Math.add(v, vec3Math.add(vec3Math.mul(uv, 2 * q.w), vec3Math.mul(uuv, 2)));
357
- },
358
-
359
- lookAt: (forward: Vec3, up: Vec3 = vec3(0, 1, 0)): Quat => {
360
- const f = vec3Math.normalize(forward);
361
- const r = vec3Math.normalize(vec3Math.cross(up, f));
362
- const u = vec3Math.cross(f, r);
363
-
364
- const trace = r.x + u.y + f.z;
365
- let q: Quat;
366
-
367
- if (trace > 0) {
368
- const s = 0.5 / Math.sqrt(trace + 1);
369
- q = {
370
- w: 0.25 / s,
371
- x: (u.z - f.y) * s,
372
- y: (f.x - r.z) * s,
373
- z: (r.y - u.x) * s,
374
- };
375
- } else if (r.x > u.y && r.x > f.z) {
376
- const s = 2 * Math.sqrt(1 + r.x - u.y - f.z);
377
- q = {
378
- w: (u.z - f.y) / s,
379
- x: 0.25 * s,
380
- y: (u.x + r.y) / s,
381
- z: (f.x + r.z) / s,
382
- };
383
- } else if (u.y > f.z) {
384
- const s = 2 * Math.sqrt(1 + u.y - r.x - f.z);
385
- q = {
386
- w: (f.x - r.z) / s,
387
- x: (u.x + r.y) / s,
388
- y: 0.25 * s,
389
- z: (f.y + u.z) / s,
390
- };
391
- } else {
392
- const s = 2 * Math.sqrt(1 + f.z - r.x - u.y);
393
- q = {
394
- w: (r.y - u.x) / s,
395
- x: (f.x + r.z) / s,
396
- y: (f.y + u.z) / s,
397
- z: 0.25 * s,
398
- };
399
- }
400
-
401
- return quatMath.normalize(q);
402
- },
403
- };
404
-
405
- // =============================================================================
406
- // AABB OPERATIONS
407
- // =============================================================================
408
-
409
- export const aabbMath = {
410
- contains: (aabb: AABB, point: Vec3): boolean => {
411
- return (
412
- point.x >= aabb.min.x &&
413
- point.x <= aabb.max.x &&
414
- point.y >= aabb.min.y &&
415
- point.y <= aabb.max.y &&
416
- point.z >= aabb.min.z &&
417
- point.z <= aabb.max.z
418
- );
419
- },
420
-
421
- intersects: (a: AABB, b: AABB): boolean => {
422
- return (
423
- a.min.x <= b.max.x &&
424
- a.max.x >= b.min.x &&
425
- a.min.y <= b.max.y &&
426
- a.max.y >= b.min.y &&
427
- a.min.z <= b.max.z &&
428
- a.max.z >= b.min.z
429
- );
430
- },
431
-
432
- center: (aabb: AABB): Vec3 => vec3Math.mul(vec3Math.add(aabb.min, aabb.max), 0.5),
433
-
434
- size: (aabb: AABB): Vec3 => vec3Math.sub(aabb.max, aabb.min),
435
-
436
- expand: (aabb: AABB, point: Vec3): AABB => ({
437
- min: vec3Math.min(aabb.min, point),
438
- max: vec3Math.max(aabb.max, point),
439
- }),
440
-
441
- merge: (a: AABB, b: AABB): AABB => ({
442
- min: vec3Math.min(a.min, b.min),
443
- max: vec3Math.max(a.max, b.max),
444
- }),
445
- };
446
-
447
- // =============================================================================
448
- // NOISE FUNCTIONS
449
- // =============================================================================
450
-
451
- // Simple permutation table for noise
452
- const perm = new Uint8Array(512);
453
- for (let i = 0; i < 256; i++) perm[i] = perm[i + 256] = i;
454
- for (let i = 255; i > 0; i--) {
455
- const j = Math.floor(Math.random() * (i + 1));
456
- [perm[i], perm[j]] = [perm[j], perm[i]];
457
- perm[i + 256] = perm[i];
458
- }
459
-
460
- function fade(t: number): number {
461
- return t * t * t * (t * (t * 6 - 15) + 10);
462
- }
463
-
464
- function grad(hash: number, x: number, y: number, z: number): number {
465
- const h = hash & 15;
466
- const u = h < 8 ? x : y;
467
- const v = h < 4 ? y : h === 12 || h === 14 ? x : z;
468
- return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
469
- }
470
-
471
- export const noise = {
472
- /**
473
- * 3D Perlin noise (-1 to 1)
474
- */
475
- perlin3d: (x: number, y: number, z: number): number => {
476
- const X = Math.floor(x) & 255;
477
- const Y = Math.floor(y) & 255;
478
- const Z = Math.floor(z) & 255;
479
-
480
- x -= Math.floor(x);
481
- y -= Math.floor(y);
482
- z -= Math.floor(z);
483
-
484
- const u = fade(x);
485
- const v = fade(y);
486
- const w = fade(z);
487
-
488
- const A = perm[X] + Y;
489
- const AA = perm[A] + Z;
490
- const AB = perm[A + 1] + Z;
491
- const B = perm[X + 1] + Y;
492
- const BA = perm[B] + Z;
493
- const BB = perm[B + 1] + Z;
494
-
495
- return lerp(
496
- lerp(
497
- lerp(grad(perm[AA], x, y, z), grad(perm[BA], x - 1, y, z), u),
498
- lerp(grad(perm[AB], x, y - 1, z), grad(perm[BB], x - 1, y - 1, z), u),
499
- v
500
- ),
501
- lerp(
502
- lerp(grad(perm[AA + 1], x, y, z - 1), grad(perm[BA + 1], x - 1, y, z - 1), u),
503
- lerp(grad(perm[AB + 1], x, y - 1, z - 1), grad(perm[BB + 1], x - 1, y - 1, z - 1), u),
504
- v
505
- ),
506
- w
507
- );
508
- },
509
-
510
- /**
511
- * 2D Perlin noise (-1 to 1)
512
- */
513
- perlin2d: (x: number, y: number): number => {
514
- return noise.perlin3d(x, y, 0);
515
- },
516
-
517
- /**
518
- * Fractal Brownian Motion (fBm)
519
- */
520
- fbm: (
521
- x: number,
522
- y: number,
523
- z: number,
524
- octaves: number = 6,
525
- lacunarity: number = 2,
526
- gain: number = 0.5
527
- ): number => {
528
- let value = 0;
529
- let amplitude = 1;
530
- let frequency = 1;
531
- let maxValue = 0;
532
-
533
- for (let i = 0; i < octaves; i++) {
534
- value += amplitude * noise.perlin3d(x * frequency, y * frequency, z * frequency);
535
- maxValue += amplitude;
536
- amplitude *= gain;
537
- frequency *= lacunarity;
538
- }
539
-
540
- return value / maxValue;
541
- },
542
-
543
- /**
544
- * Simplex-like noise (approximation using perlin)
545
- */
546
- simplex: (x: number, y: number): number => {
547
- return noise.perlin2d(x * 1.2, y * 1.2);
548
- },
549
-
550
- /**
551
- * Worley/Cellular noise
552
- */
553
- worley: (x: number, y: number, z: number): number => {
554
- const xi = Math.floor(x);
555
- const yi = Math.floor(y);
556
- const zi = Math.floor(z);
557
-
558
- let minDist = Infinity;
559
-
560
- for (let i = -1; i <= 1; i++) {
561
- for (let j = -1; j <= 1; j++) {
562
- for (let k = -1; k <= 1; k++) {
563
- const cellX = xi + i;
564
- const cellY = yi + j;
565
- const cellZ = zi + k;
566
-
567
- // Pseudo-random point in cell
568
- const hash = perm[(perm[(perm[cellX & 255] + cellY) & 255] + cellZ) & 255];
569
- const px = cellX + hash / 255;
570
- const py = cellY + ((hash * 7) % 255) / 255;
571
- const pz = cellZ + ((hash * 13) % 255) / 255;
572
-
573
- const dist = (x - px) * (x - px) + (y - py) * (y - py) + (z - pz) * (z - pz);
574
- minDist = Math.min(minDist, dist);
575
- }
576
- }
577
- }
578
-
579
- return Math.sqrt(minDist);
580
- },
581
- };
582
-
583
- // =============================================================================
584
- // RANDOM
585
- // =============================================================================
586
-
587
- export const random = {
588
- /**
589
- * Random float between 0 and 1
590
- */
591
- float: (): number => Math.random(),
592
-
593
- /**
594
- * Random float in range [min, max)
595
- */
596
- range: (min: number, max: number): number => min + Math.random() * (max - min),
597
-
598
- /**
599
- * Random integer in range [min, max]
600
- */
601
- int: (min: number, max: number): number => Math.floor(min + Math.random() * (max - min + 1)),
602
-
603
- /**
604
- * Random boolean with probability
605
- */
606
- bool: (probability: number = 0.5): boolean => Math.random() < probability,
607
-
608
- /**
609
- * Random element from array
610
- */
611
- pick: <T>(array: T[]): T => array[Math.floor(Math.random() * array.length)],
612
-
613
- /**
614
- * Shuffle array (Fisher-Yates)
615
- */
616
- shuffle: <T>(array: T[]): T[] => {
617
- const result = [...array];
618
- for (let i = result.length - 1; i > 0; i--) {
619
- const j = Math.floor(Math.random() * (i + 1));
620
- [result[i], result[j]] = [result[j], result[i]];
621
- }
622
- return result;
623
- },
624
-
625
- /**
626
- * Random Vec3 in unit sphere
627
- */
628
- insideUnitSphere: (): Vec3 => {
629
- const theta = Math.random() * TAU;
630
- const phi = Math.acos(2 * Math.random() - 1);
631
- const r = Math.cbrt(Math.random());
632
- return {
633
- x: r * Math.sin(phi) * Math.cos(theta),
634
- y: r * Math.sin(phi) * Math.sin(theta),
635
- z: r * Math.cos(phi),
636
- };
637
- },
638
-
639
- /**
640
- * Random Vec3 on unit sphere surface
641
- */
642
- onUnitSphere: (): Vec3 => {
643
- const theta = Math.random() * TAU;
644
- const phi = Math.acos(2 * Math.random() - 1);
645
- return {
646
- x: Math.sin(phi) * Math.cos(theta),
647
- y: Math.sin(phi) * Math.sin(theta),
648
- z: Math.cos(phi),
649
- };
650
- },
651
-
652
- /**
653
- * Random Vec2 in unit circle
654
- */
655
- insideUnitCircle: (): Vec2 => {
656
- const theta = Math.random() * TAU;
657
- const r = Math.sqrt(Math.random());
658
- return {
659
- x: r * Math.cos(theta),
660
- y: r * Math.sin(theta),
661
- };
662
- },
663
-
664
- /**
665
- * Seeded random number generator
666
- */
667
- seeded: (seed: number) => {
668
- let s = seed;
669
- return () => {
670
- s = (s * 1103515245 + 12345) & 0x7fffffff;
671
- return s / 0x7fffffff;
672
- };
673
- },
674
- };