@holoscript/std 2.1.0 → 3.1.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.
- package/README.md +197 -0
- package/dist/__tests__/EconomicPrimitives.test.d.ts.map +1 -0
- package/dist/__tests__/EconomicTraits.test.d.ts.map +1 -0
- package/dist/__tests__/SimulationLabPrimitives.test.d.ts.map +1 -0
- package/dist/__tests__/Sprint33.test.d.ts.map +1 -0
- package/dist/__tests__/Sprint56.test.d.ts.map +1 -0
- package/dist/__tests__/collections.test.d.ts.map +1 -0
- package/dist/__tests__/events.test.d.ts.map +1 -0
- package/dist/__tests__/materials.test.d.ts.map +1 -0
- package/dist/__tests__/math.test.d.ts.map +1 -0
- package/dist/__tests__/physics.test.d.ts.map +1 -0
- package/dist/__tests__/spatial.test.d.ts.map +1 -0
- package/dist/__tests__/string-decoupled.test.d.ts.map +1 -0
- package/dist/__tests__/string.test.d.ts.map +1 -0
- package/dist/__tests__/time.test.d.ts.map +1 -0
- package/dist/collections.d.ts.map +1 -1
- package/dist/events.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -9
- package/dist/materials.d.ts.map +1 -0
- package/dist/math.d.ts.map +1 -1
- package/dist/physics.d.ts.map +1 -0
- package/dist/spatial.d.ts.map +1 -0
- package/dist/string.d.ts.map +1 -1
- package/dist/time.d.ts.map +1 -1
- package/dist/traits/ARTraits.d.ts.map +1 -0
- package/dist/traits/EconomicPrimitives.d.ts.map +1 -0
- package/dist/traits/EconomicTraits.d.ts.map +1 -0
- package/dist/traits/IoTTraits.d.ts.map +1 -0
- package/dist/traits/SimulationLabPrimitives.d.ts.map +1 -0
- package/dist/traits/SimulationLabTraits.d.ts.map +1 -0
- package/dist/traits/VRRTraits.d.ts.map +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +17 -6
- package/src/__tests__/EconomicPrimitives.test.ts +690 -0
- package/src/__tests__/EconomicTraits.test.ts +425 -0
- package/src/__tests__/SimulationLabPrimitives.test.ts +415 -0
- package/src/__tests__/Sprint33.test.ts +1301 -0
- package/src/__tests__/Sprint56.test.ts +1070 -0
- package/src/__tests__/collections.test.ts +182 -0
- package/src/__tests__/events.test.ts +135 -0
- package/src/__tests__/materials.test.ts +84 -0
- package/src/__tests__/math.test.ts +246 -0
- package/src/__tests__/physics.test.ts +83 -0
- package/src/__tests__/spatial.test.ts +333 -0
- package/src/__tests__/string-decoupled.test.ts +16 -0
- package/src/__tests__/string.test.ts +164 -0
- package/src/__tests__/time.test.ts +110 -0
- package/src/collections.ts +8 -2
- package/src/events.ts +88 -0
- package/src/index.ts +161 -11
- package/src/materials.ts +109 -0
- package/src/math.ts +30 -14
- package/src/physics.ts +141 -0
- package/src/spatial.ts +320 -0
- package/src/string.basic.test.ts +14 -0
- package/src/string.test.ts +335 -0
- package/src/string.ts +19 -2
- package/src/time.ts +9 -10
- package/src/traits/ARTraits.ts +103 -0
- package/src/traits/EconomicPrimitives.ts +755 -0
- package/src/traits/EconomicTraits.ts +552 -0
- package/src/traits/IoTTraits.ts +102 -0
- package/src/traits/SimulationLabPrimitives.ts +650 -0
- package/src/traits/SimulationLabTraits.ts +191 -0
- package/src/traits/VRRTraits.ts +326 -0
- package/src/types.ts +47 -12
- package/vitest.config.ts +10 -0
- package/dist/collections.d.ts +0 -177
- package/dist/collections.js +0 -720
- package/dist/collections.js.map +0 -1
- package/dist/index.d.ts +0 -89
- package/dist/index.js.map +0 -1
- package/dist/math.d.ts +0 -162
- package/dist/math.js +0 -539
- package/dist/math.js.map +0 -1
- package/dist/string.d.ts +0 -208
- package/dist/string.js +0 -443
- package/dist/string.js.map +0 -1
- package/dist/time.d.ts +0 -215
- package/dist/time.js +0 -530
- package/dist/time.js.map +0 -1
- package/dist/types.d.ts +0 -193
- package/dist/types.js +0 -198
- package/dist/types.js.map +0 -1
package/src/collections.ts
CHANGED
|
@@ -825,10 +825,16 @@ export class PriorityQueue<T> {
|
|
|
825
825
|
const rightChild = 2 * index + 2;
|
|
826
826
|
let smallest = index;
|
|
827
827
|
|
|
828
|
-
if (
|
|
828
|
+
if (
|
|
829
|
+
leftChild < this.heap.length &&
|
|
830
|
+
this.compareFn(this.heap[leftChild].priority, this.heap[smallest].priority) < 0
|
|
831
|
+
) {
|
|
829
832
|
smallest = leftChild;
|
|
830
833
|
}
|
|
831
|
-
if (
|
|
834
|
+
if (
|
|
835
|
+
rightChild < this.heap.length &&
|
|
836
|
+
this.compareFn(this.heap[rightChild].priority, this.heap[smallest].priority) < 0
|
|
837
|
+
) {
|
|
832
838
|
smallest = rightChild;
|
|
833
839
|
}
|
|
834
840
|
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/std — Events Module
|
|
3
|
+
*
|
|
4
|
+
* Provides a typed event bus for HoloScript compositions.
|
|
5
|
+
* Supports emit, on, once, off, and wildcard listeners.
|
|
6
|
+
*
|
|
7
|
+
* @version 0.2.0
|
|
8
|
+
* @module @holoscript/std/events
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export type EventHandler<T = any> = (data: T) => void;
|
|
12
|
+
|
|
13
|
+
interface Listener {
|
|
14
|
+
handler: EventHandler;
|
|
15
|
+
once: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class EventBus {
|
|
19
|
+
private listeners: Map<string, Listener[]> = new Map();
|
|
20
|
+
private wildcardListeners: Listener[] = [];
|
|
21
|
+
|
|
22
|
+
/** Register an event listener. */
|
|
23
|
+
on<T = any>(event: string, handler: EventHandler<T>): () => void {
|
|
24
|
+
if (!this.listeners.has(event)) this.listeners.set(event, []);
|
|
25
|
+
const listener: Listener = { handler, once: false };
|
|
26
|
+
this.listeners.get(event)!.push(listener);
|
|
27
|
+
return () => this.off(event, handler);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Register a one-time event listener. */
|
|
31
|
+
once<T = any>(event: string, handler: EventHandler<T>): () => void {
|
|
32
|
+
if (!this.listeners.has(event)) this.listeners.set(event, []);
|
|
33
|
+
const listener: Listener = { handler, once: true };
|
|
34
|
+
this.listeners.get(event)!.push(listener);
|
|
35
|
+
return () => this.off(event, handler);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Remove an event listener. */
|
|
39
|
+
off(event: string, handler: EventHandler): void {
|
|
40
|
+
const list = this.listeners.get(event);
|
|
41
|
+
if (!list) return;
|
|
42
|
+
this.listeners.set(
|
|
43
|
+
event,
|
|
44
|
+
list.filter((l) => l.handler !== handler)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Emit an event to all registered listeners. */
|
|
49
|
+
emit<T = any>(event: string, data?: T): void {
|
|
50
|
+
// Fire specific listeners
|
|
51
|
+
const list = this.listeners.get(event);
|
|
52
|
+
if (list) {
|
|
53
|
+
const remaining: Listener[] = [];
|
|
54
|
+
for (const l of list) {
|
|
55
|
+
l.handler(data);
|
|
56
|
+
if (!l.once) remaining.push(l);
|
|
57
|
+
}
|
|
58
|
+
this.listeners.set(event, remaining);
|
|
59
|
+
}
|
|
60
|
+
// Fire wildcard listeners
|
|
61
|
+
for (const l of this.wildcardListeners) {
|
|
62
|
+
l.handler({ event, data });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Listen to all events. */
|
|
67
|
+
onAny(handler: EventHandler<{ event: string; data: any }>): () => void {
|
|
68
|
+
const listener: Listener = { handler, once: false };
|
|
69
|
+
this.wildcardListeners.push(listener);
|
|
70
|
+
return () => {
|
|
71
|
+
this.wildcardListeners = this.wildcardListeners.filter((l) => l !== listener);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Remove all listeners. */
|
|
76
|
+
clear(): void {
|
|
77
|
+
this.listeners.clear();
|
|
78
|
+
this.wildcardListeners = [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Get count of listeners for an event (or all events). */
|
|
82
|
+
listenerCount(event?: string): number {
|
|
83
|
+
if (event) return (this.listeners.get(event) || []).length;
|
|
84
|
+
let total = this.wildcardListeners.length;
|
|
85
|
+
for (const [, list] of this.listeners) total += list.length;
|
|
86
|
+
return total;
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,25 +2,62 @@
|
|
|
2
2
|
* @holoscript/std - Standard Library for HoloScript Plus
|
|
3
3
|
*
|
|
4
4
|
* Provides core types, math utilities, collections, string operations,
|
|
5
|
-
*
|
|
5
|
+
* time management, spatial math, physics primitives, materials, and events
|
|
6
|
+
* for HoloScript Plus programs.
|
|
6
7
|
*
|
|
7
8
|
* @example
|
|
8
9
|
* ```hsplus
|
|
9
|
-
* import { Vec3,
|
|
10
|
+
* import { Vec3, createPBRMaterial, EventBus } from "@holoscript/std";
|
|
10
11
|
*
|
|
11
12
|
* let position = Vec3(0, 1, 0);
|
|
12
|
-
* let
|
|
13
|
-
*
|
|
14
|
-
* async fn main() {
|
|
15
|
-
* await sleep(1000);
|
|
16
|
-
* print("Done!");
|
|
17
|
-
* }
|
|
13
|
+
* let steel = createPBRMaterial("Steel", "metal");
|
|
14
|
+
* let bus = new EventBus();
|
|
18
15
|
* ```
|
|
19
16
|
*/
|
|
20
17
|
|
|
21
18
|
// Re-export everything from types.js
|
|
22
19
|
export * from './types.js';
|
|
23
20
|
|
|
21
|
+
// Spatial math (v4.2)
|
|
22
|
+
export {
|
|
23
|
+
Vec3,
|
|
24
|
+
Quaternion,
|
|
25
|
+
Transform,
|
|
26
|
+
Ray,
|
|
27
|
+
AABB,
|
|
28
|
+
distance,
|
|
29
|
+
lerp as spatialLerp,
|
|
30
|
+
clamp as spatialClamp,
|
|
31
|
+
degToRad as spatialDegToRad,
|
|
32
|
+
radToDeg as spatialRadToDeg,
|
|
33
|
+
} from './spatial.js';
|
|
34
|
+
|
|
35
|
+
// Physics primitives (v4.2)
|
|
36
|
+
export {
|
|
37
|
+
createBoxCollider,
|
|
38
|
+
createSphereCollider,
|
|
39
|
+
createCapsuleCollider,
|
|
40
|
+
createRigidbody,
|
|
41
|
+
} from './physics.js';
|
|
42
|
+
export type {
|
|
43
|
+
ColliderConfig,
|
|
44
|
+
ColliderShapeType,
|
|
45
|
+
RigidbodyConfig,
|
|
46
|
+
ForceFieldConfig,
|
|
47
|
+
ForceFieldType,
|
|
48
|
+
JointConfig,
|
|
49
|
+
JointType,
|
|
50
|
+
RaycastHit,
|
|
51
|
+
} from './physics.js';
|
|
52
|
+
|
|
53
|
+
// Materials (v4.2)
|
|
54
|
+
export { MATERIAL_PRESETS, createPBRMaterial } from './materials.js';
|
|
55
|
+
export type { PBRMaterial, UnlitMaterial, TextureMapType, TextureConfig } from './materials.js';
|
|
56
|
+
|
|
57
|
+
// Events (v4.2)
|
|
58
|
+
export { EventBus } from './events.js';
|
|
59
|
+
export type { EventHandler } from './events.js';
|
|
60
|
+
|
|
24
61
|
// Math utilities - export objects from math.ts
|
|
25
62
|
export {
|
|
26
63
|
// Constants
|
|
@@ -120,8 +157,114 @@ export {
|
|
|
120
157
|
wordWrap,
|
|
121
158
|
levenshtein,
|
|
122
159
|
similarity,
|
|
160
|
+
extractTraits,
|
|
123
161
|
} from './string.js';
|
|
124
162
|
|
|
163
|
+
// Economic primitives (v4.3)
|
|
164
|
+
export {
|
|
165
|
+
// Tradeable
|
|
166
|
+
generateTxHash,
|
|
167
|
+
executeTrade,
|
|
168
|
+
// Depreciation
|
|
169
|
+
calculateDepreciation,
|
|
170
|
+
depreciatedValue,
|
|
171
|
+
isDestroyed,
|
|
172
|
+
calculateRepairCost,
|
|
173
|
+
DEFAULT_DEPRECIATION,
|
|
174
|
+
// Bonding curves
|
|
175
|
+
bondingCurvePrice,
|
|
176
|
+
bondingCurveBuyCost,
|
|
177
|
+
bondingCurveSellRefund,
|
|
178
|
+
spatialPrice,
|
|
179
|
+
DEFAULT_BONDING_CURVE,
|
|
180
|
+
// Wealth taxation
|
|
181
|
+
calculateTaxRate,
|
|
182
|
+
calculateTaxAmount,
|
|
183
|
+
calculateRedistribution,
|
|
184
|
+
DEFAULT_WEALTH_TAX,
|
|
185
|
+
// PID control
|
|
186
|
+
createPIDState,
|
|
187
|
+
updatePID,
|
|
188
|
+
createDualLoopPIDState,
|
|
189
|
+
updateDualLoopPID,
|
|
190
|
+
DEFAULT_PID,
|
|
191
|
+
// Faucet-sink tracking
|
|
192
|
+
createFaucetSinkMetrics,
|
|
193
|
+
recordFaucet,
|
|
194
|
+
recordSink,
|
|
195
|
+
resetMetricsPeriod,
|
|
196
|
+
} from './traits/EconomicPrimitives.js';
|
|
197
|
+
export type {
|
|
198
|
+
Currency,
|
|
199
|
+
AgentID,
|
|
200
|
+
EconomicResult,
|
|
201
|
+
EconomicError,
|
|
202
|
+
EconomicPermission,
|
|
203
|
+
OwnershipRecord,
|
|
204
|
+
TransferRecord,
|
|
205
|
+
DepreciationConfig,
|
|
206
|
+
BondingCurveType,
|
|
207
|
+
BondingCurveConfig,
|
|
208
|
+
WealthTaxConfig,
|
|
209
|
+
PIDConfig,
|
|
210
|
+
PIDState,
|
|
211
|
+
DualLoopPIDConfig,
|
|
212
|
+
DualLoopPIDState,
|
|
213
|
+
FaucetSinkMetrics,
|
|
214
|
+
} from './traits/EconomicPrimitives.js';
|
|
215
|
+
|
|
216
|
+
// Economic traits (v4.3)
|
|
217
|
+
export {
|
|
218
|
+
EconomicTraits,
|
|
219
|
+
getEconomicTraitNames,
|
|
220
|
+
getEconomicTrait,
|
|
221
|
+
validateTraitComposition,
|
|
222
|
+
getRequiredPermissions,
|
|
223
|
+
} from './traits/EconomicTraits.js';
|
|
224
|
+
export type { EconomicTraitDefinition } from './traits/EconomicTraits.js';
|
|
225
|
+
|
|
226
|
+
// SimulationLab primitives (v4.3)
|
|
227
|
+
export {
|
|
228
|
+
// Statistics
|
|
229
|
+
mean,
|
|
230
|
+
variance,
|
|
231
|
+
standardDeviation,
|
|
232
|
+
standardError,
|
|
233
|
+
cohensD,
|
|
234
|
+
// Statistical tests
|
|
235
|
+
tTest,
|
|
236
|
+
oneSampleTTest,
|
|
237
|
+
mannWhitneyU,
|
|
238
|
+
chiSquaredTest,
|
|
239
|
+
// Parameter sweeps
|
|
240
|
+
expandSweep,
|
|
241
|
+
generateSweepCombinations,
|
|
242
|
+
isParameterRange,
|
|
243
|
+
// Metric aggregation
|
|
244
|
+
extractMetric,
|
|
245
|
+
groupByParameter,
|
|
246
|
+
summarizeMetrics,
|
|
247
|
+
} from './traits/SimulationLabPrimitives.js';
|
|
248
|
+
export type {
|
|
249
|
+
Hypothesis,
|
|
250
|
+
HypothesisDirection,
|
|
251
|
+
SimulationStatus,
|
|
252
|
+
ParameterRange,
|
|
253
|
+
ParameterSet,
|
|
254
|
+
ParameterSweep,
|
|
255
|
+
SimulationMetrics,
|
|
256
|
+
StatisticalResult,
|
|
257
|
+
ExperimentResult,
|
|
258
|
+
} from './traits/SimulationLabPrimitives.js';
|
|
259
|
+
|
|
260
|
+
// SimulationLab traits (v4.3)
|
|
261
|
+
export {
|
|
262
|
+
SimulationLabTraits,
|
|
263
|
+
getSimulationTraitNames,
|
|
264
|
+
getSimulationTrait,
|
|
265
|
+
} from './traits/SimulationLabTraits.js';
|
|
266
|
+
export type { SimulationTraitDefinition } from './traits/SimulationLabTraits.js';
|
|
267
|
+
|
|
125
268
|
// Time utilities
|
|
126
269
|
export {
|
|
127
270
|
now,
|
|
@@ -178,7 +321,10 @@ export function assert(condition: boolean, message?: string): asserts condition
|
|
|
178
321
|
/**
|
|
179
322
|
* Assert a value is not null or undefined
|
|
180
323
|
*/
|
|
181
|
-
export function assertDefined<T>(
|
|
324
|
+
export function assertDefined<T>(
|
|
325
|
+
value: T | null | undefined,
|
|
326
|
+
message?: string
|
|
327
|
+
): asserts value is T {
|
|
182
328
|
if (value === null || value === undefined) {
|
|
183
329
|
throw new Error(message ?? 'Value is null or undefined');
|
|
184
330
|
}
|
|
@@ -266,7 +412,7 @@ export function equals(a: unknown, b: unknown): boolean {
|
|
|
266
412
|
return true;
|
|
267
413
|
}
|
|
268
414
|
|
|
269
|
-
const keysA = Object.keys(a
|
|
415
|
+
const keysA = Object.keys(a);
|
|
270
416
|
const keysB = Object.keys(b as object);
|
|
271
417
|
if (keysA.length !== keysB.length) return false;
|
|
272
418
|
|
|
@@ -299,7 +445,11 @@ export function pipe(value: unknown, ...fns: ((x: unknown) => unknown)[]): unkno
|
|
|
299
445
|
export function compose<A>(): (a: A) => A;
|
|
300
446
|
export function compose<A, B>(fn1: (a: A) => B): (a: A) => B;
|
|
301
447
|
export function compose<A, B, C>(fn2: (b: B) => C, fn1: (a: A) => B): (a: A) => C;
|
|
302
|
-
export function compose<A, B, C, D>(
|
|
448
|
+
export function compose<A, B, C, D>(
|
|
449
|
+
fn3: (c: C) => D,
|
|
450
|
+
fn2: (b: B) => C,
|
|
451
|
+
fn1: (a: A) => B
|
|
452
|
+
): (a: A) => D;
|
|
303
453
|
export function compose(...fns: ((x: unknown) => unknown)[]): (x: unknown) => unknown {
|
|
304
454
|
return (value: unknown) => fns.reduceRight((acc, fn) => fn(acc), value);
|
|
305
455
|
}
|
package/src/materials.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/std — Materials Module
|
|
3
|
+
*
|
|
4
|
+
* Provides PBR material types, texture map definitions, and material presets.
|
|
5
|
+
* Maps directly to HoloScript material_block grammar constructs.
|
|
6
|
+
*
|
|
7
|
+
* @version 0.2.0
|
|
8
|
+
* @module @holoscript/std/materials
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// PBR Material
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
export interface PBRMaterial {
|
|
16
|
+
name: string;
|
|
17
|
+
baseColor: string; // hex color
|
|
18
|
+
roughness: number; // 0.0 - 1.0
|
|
19
|
+
metallic: number; // 0.0 - 1.0
|
|
20
|
+
emissiveColor?: string;
|
|
21
|
+
emissiveIntensity?: number;
|
|
22
|
+
opacity?: number; // 0.0 - 1.0
|
|
23
|
+
ior?: number; // Index of refraction (glass ~1.5, water ~1.33)
|
|
24
|
+
subsurface?: number;
|
|
25
|
+
clearcoat?: number;
|
|
26
|
+
clearcoatRoughness?: number;
|
|
27
|
+
// Texture maps
|
|
28
|
+
albedoMap?: string;
|
|
29
|
+
normalMap?: string;
|
|
30
|
+
roughnessMap?: string;
|
|
31
|
+
metallicMap?: string;
|
|
32
|
+
emissionMap?: string;
|
|
33
|
+
aoMap?: string;
|
|
34
|
+
heightMap?: string;
|
|
35
|
+
opacityMap?: string;
|
|
36
|
+
displacementMap?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface UnlitMaterial {
|
|
40
|
+
name: string;
|
|
41
|
+
color: string;
|
|
42
|
+
emissiveColor?: string;
|
|
43
|
+
emissiveIntensity?: number;
|
|
44
|
+
opacity?: number;
|
|
45
|
+
texture?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// Material Presets
|
|
50
|
+
// =============================================================================
|
|
51
|
+
|
|
52
|
+
export const MATERIAL_PRESETS: Record<string, Partial<PBRMaterial>> = {
|
|
53
|
+
metal: { roughness: 0.2, metallic: 1.0 },
|
|
54
|
+
wood: { roughness: 0.85, metallic: 0.0, baseColor: '#8B6914' },
|
|
55
|
+
glass: { roughness: 0.05, metallic: 0.0, opacity: 0.3, ior: 1.5 },
|
|
56
|
+
plastic: { roughness: 0.4, metallic: 0.0 },
|
|
57
|
+
concrete: { roughness: 0.95, metallic: 0.0, baseColor: '#808080' },
|
|
58
|
+
fabric: { roughness: 0.9, metallic: 0.0, subsurface: 0.2 },
|
|
59
|
+
water: { roughness: 0.05, metallic: 0.0, opacity: 0.7, ior: 1.33 },
|
|
60
|
+
rubber: { roughness: 0.95, metallic: 0.0, baseColor: '#222222' },
|
|
61
|
+
marble: { roughness: 0.3, metallic: 0.0, baseColor: '#f0f0f0' },
|
|
62
|
+
skin: { roughness: 0.6, metallic: 0.0, subsurface: 0.5 },
|
|
63
|
+
foliage: { roughness: 0.8, metallic: 0.0, baseColor: '#2d5a27', subsurface: 0.3 },
|
|
64
|
+
chrome: { roughness: 0.05, metallic: 1.0, baseColor: '#cccccc' },
|
|
65
|
+
gold: { roughness: 0.2, metallic: 1.0, baseColor: '#ffd700' },
|
|
66
|
+
copper: { roughness: 0.3, metallic: 1.0, baseColor: '#b87333' },
|
|
67
|
+
ice: { roughness: 0.1, metallic: 0.0, opacity: 0.8, ior: 1.31 },
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export function createPBRMaterial(
|
|
71
|
+
name: string,
|
|
72
|
+
preset?: keyof typeof MATERIAL_PRESETS,
|
|
73
|
+
overrides?: Partial<PBRMaterial>
|
|
74
|
+
): PBRMaterial {
|
|
75
|
+
const base = preset ? MATERIAL_PRESETS[preset] : {};
|
|
76
|
+
return {
|
|
77
|
+
name,
|
|
78
|
+
baseColor: '#ffffff',
|
|
79
|
+
roughness: 0.5,
|
|
80
|
+
metallic: 0.0,
|
|
81
|
+
...base,
|
|
82
|
+
...overrides,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// Texture Map Types
|
|
88
|
+
// =============================================================================
|
|
89
|
+
|
|
90
|
+
export type TextureMapType =
|
|
91
|
+
| 'albedo_map'
|
|
92
|
+
| 'normal_map'
|
|
93
|
+
| 'roughness_map'
|
|
94
|
+
| 'metallic_map'
|
|
95
|
+
| 'emission_map'
|
|
96
|
+
| 'ao_map'
|
|
97
|
+
| 'height_map'
|
|
98
|
+
| 'opacity_map'
|
|
99
|
+
| 'displacement_map'
|
|
100
|
+
| 'specular_map'
|
|
101
|
+
| 'clearcoat_map';
|
|
102
|
+
|
|
103
|
+
export interface TextureConfig {
|
|
104
|
+
source: string;
|
|
105
|
+
tiling?: [number, number];
|
|
106
|
+
offset?: [number, number];
|
|
107
|
+
filter?: 'linear' | 'nearest';
|
|
108
|
+
wrap?: 'repeat' | 'clamp' | 'mirror';
|
|
109
|
+
}
|
package/src/math.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Vector math, quaternion operations, interpolation, and noise functions.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Vec2, Vec3,
|
|
7
|
+
import type { Vec2, Vec3, Quat, EulerAngles, AABB } from './types.js';
|
|
8
8
|
import { vec3, quat } from './types.js';
|
|
9
9
|
|
|
10
10
|
// =============================================================================
|
|
@@ -34,7 +34,13 @@ export function inverseLerp(a: number, b: number, value: number): number {
|
|
|
34
34
|
return (value - a) / (b - a);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export function remap(
|
|
37
|
+
export function remap(
|
|
38
|
+
value: number,
|
|
39
|
+
inMin: number,
|
|
40
|
+
inMax: number,
|
|
41
|
+
outMin: number,
|
|
42
|
+
outMax: number
|
|
43
|
+
): number {
|
|
38
44
|
return lerp(outMin, outMax, inverseLerp(inMin, inMax, value));
|
|
39
45
|
}
|
|
40
46
|
|
|
@@ -153,10 +159,7 @@ export const vec3Math = {
|
|
|
153
159
|
const dot = clamp(vec3Math.dot(a, b), -1, 1);
|
|
154
160
|
const theta = Math.acos(dot) * t;
|
|
155
161
|
const relative = vec3Math.normalize(vec3Math.sub(b, vec3Math.mul(a, dot)));
|
|
156
|
-
return vec3Math.add(
|
|
157
|
-
vec3Math.mul(a, Math.cos(theta)),
|
|
158
|
-
vec3Math.mul(relative, Math.sin(theta))
|
|
159
|
-
);
|
|
162
|
+
return vec3Math.add(vec3Math.mul(a, Math.cos(theta)), vec3Math.mul(relative, Math.sin(theta)));
|
|
160
163
|
},
|
|
161
164
|
|
|
162
165
|
negate: (v: Vec3): Vec3 => ({ x: -v.x, y: -v.y, z: -v.z }),
|
|
@@ -406,17 +409,23 @@ export const quatMath = {
|
|
|
406
409
|
export const aabbMath = {
|
|
407
410
|
contains: (aabb: AABB, point: Vec3): boolean => {
|
|
408
411
|
return (
|
|
409
|
-
point.x >= aabb.min.x &&
|
|
410
|
-
point.
|
|
411
|
-
point.
|
|
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
|
|
412
418
|
);
|
|
413
419
|
},
|
|
414
420
|
|
|
415
421
|
intersects: (a: AABB, b: AABB): boolean => {
|
|
416
422
|
return (
|
|
417
|
-
a.min.x <= b.max.x &&
|
|
418
|
-
a.
|
|
419
|
-
a.min.
|
|
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
|
|
420
429
|
);
|
|
421
430
|
},
|
|
422
431
|
|
|
@@ -508,7 +517,14 @@ export const noise = {
|
|
|
508
517
|
/**
|
|
509
518
|
* Fractal Brownian Motion (fBm)
|
|
510
519
|
*/
|
|
511
|
-
fbm: (
|
|
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 => {
|
|
512
528
|
let value = 0;
|
|
513
529
|
let amplitude = 1;
|
|
514
530
|
let frequency = 1;
|
|
@@ -550,7 +566,7 @@ export const noise = {
|
|
|
550
566
|
|
|
551
567
|
// Pseudo-random point in cell
|
|
552
568
|
const hash = perm[(perm[(perm[cellX & 255] + cellY) & 255] + cellZ) & 255];
|
|
553
|
-
const px = cellX +
|
|
569
|
+
const px = cellX + hash / 255;
|
|
554
570
|
const py = cellY + ((hash * 7) % 255) / 255;
|
|
555
571
|
const pz = cellZ + ((hash * 13) % 255) / 255;
|
|
556
572
|
|
package/src/physics.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/std — Physics Module
|
|
3
|
+
*
|
|
4
|
+
* Provides physics primitives: ColliderShape, RigidbodyConfig, ForceField, Joint.
|
|
5
|
+
* Runtime representations for HoloScript physics blocks.
|
|
6
|
+
*
|
|
7
|
+
* @version 0.2.0
|
|
8
|
+
* @module @holoscript/std/physics
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { Vec3 } from './spatial.js';
|
|
12
|
+
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Collider Shapes
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
export type ColliderShapeType =
|
|
18
|
+
| 'box'
|
|
19
|
+
| 'sphere'
|
|
20
|
+
| 'capsule'
|
|
21
|
+
| 'mesh'
|
|
22
|
+
| 'convex'
|
|
23
|
+
| 'cylinder'
|
|
24
|
+
| 'heightfield';
|
|
25
|
+
|
|
26
|
+
export interface ColliderConfig {
|
|
27
|
+
shape: ColliderShapeType;
|
|
28
|
+
isTrigger: boolean;
|
|
29
|
+
friction: number;
|
|
30
|
+
restitution: number;
|
|
31
|
+
// Shape-specific
|
|
32
|
+
radius?: number;
|
|
33
|
+
halfExtents?: Vec3;
|
|
34
|
+
height?: number;
|
|
35
|
+
meshAsset?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function createBoxCollider(
|
|
39
|
+
halfExtents: Vec3,
|
|
40
|
+
options?: Partial<ColliderConfig>
|
|
41
|
+
): ColliderConfig {
|
|
42
|
+
return {
|
|
43
|
+
shape: 'box',
|
|
44
|
+
isTrigger: false,
|
|
45
|
+
friction: 0.5,
|
|
46
|
+
restitution: 0.0,
|
|
47
|
+
halfExtents,
|
|
48
|
+
...options,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function createSphereCollider(
|
|
53
|
+
radius: number,
|
|
54
|
+
options?: Partial<ColliderConfig>
|
|
55
|
+
): ColliderConfig {
|
|
56
|
+
return { shape: 'sphere', isTrigger: false, friction: 0.5, restitution: 0.0, radius, ...options };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function createCapsuleCollider(
|
|
60
|
+
radius: number,
|
|
61
|
+
height: number,
|
|
62
|
+
options?: Partial<ColliderConfig>
|
|
63
|
+
): ColliderConfig {
|
|
64
|
+
return {
|
|
65
|
+
shape: 'capsule',
|
|
66
|
+
isTrigger: false,
|
|
67
|
+
friction: 0.5,
|
|
68
|
+
restitution: 0.0,
|
|
69
|
+
radius,
|
|
70
|
+
height,
|
|
71
|
+
...options,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// =============================================================================
|
|
76
|
+
// Rigidbody
|
|
77
|
+
// =============================================================================
|
|
78
|
+
|
|
79
|
+
export interface RigidbodyConfig {
|
|
80
|
+
mass: number;
|
|
81
|
+
useGravity: boolean;
|
|
82
|
+
linearDamping: number;
|
|
83
|
+
angularDamping: number;
|
|
84
|
+
freezePosition: [boolean, boolean, boolean];
|
|
85
|
+
freezeRotation: [boolean, boolean, boolean];
|
|
86
|
+
isKinematic: boolean;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function createRigidbody(mass: number, options?: Partial<RigidbodyConfig>): RigidbodyConfig {
|
|
90
|
+
return {
|
|
91
|
+
mass,
|
|
92
|
+
useGravity: true,
|
|
93
|
+
linearDamping: 0.0,
|
|
94
|
+
angularDamping: 0.05,
|
|
95
|
+
freezePosition: [false, false, false],
|
|
96
|
+
freezeRotation: [false, false, false],
|
|
97
|
+
isKinematic: false,
|
|
98
|
+
...options,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// =============================================================================
|
|
103
|
+
// Force Fields
|
|
104
|
+
// =============================================================================
|
|
105
|
+
|
|
106
|
+
export type ForceFieldType = 'directional' | 'radial' | 'vortex' | 'buoyancy';
|
|
107
|
+
|
|
108
|
+
export interface ForceFieldConfig {
|
|
109
|
+
type: ForceFieldType;
|
|
110
|
+
strength: number;
|
|
111
|
+
direction?: Vec3;
|
|
112
|
+
falloff: 'none' | 'linear' | 'quadratic';
|
|
113
|
+
turbulence: number;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// =============================================================================
|
|
117
|
+
// Joints
|
|
118
|
+
// =============================================================================
|
|
119
|
+
|
|
120
|
+
export type JointType = 'hinge' | 'slider' | 'ball_socket' | 'fixed' | 'd6' | 'spring';
|
|
121
|
+
|
|
122
|
+
export interface JointConfig {
|
|
123
|
+
type: JointType;
|
|
124
|
+
connectedBody?: string;
|
|
125
|
+
axis?: Vec3;
|
|
126
|
+
limits?: [number, number];
|
|
127
|
+
damping: number;
|
|
128
|
+
springForce?: number;
|
|
129
|
+
breakForce?: number;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// =============================================================================
|
|
133
|
+
// Raycast Utility
|
|
134
|
+
// =============================================================================
|
|
135
|
+
|
|
136
|
+
export interface RaycastHit {
|
|
137
|
+
point: Vec3;
|
|
138
|
+
normal: Vec3;
|
|
139
|
+
distance: number;
|
|
140
|
+
objectName: string;
|
|
141
|
+
}
|