loomlarge 0.1.0
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 +714 -0
- package/dist/index.cjs +1176 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +631 -0
- package/dist/index.d.ts +631 -0
- package/dist/index.js +1166 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomLarge - AU Mapping Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for configurable Action Unit mappings.
|
|
5
|
+
* Allows the engine to work with different character rigs (CC4, Mixamo, etc.)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* AUMappingConfig - Complete configuration for AU-to-morph/bone mappings
|
|
10
|
+
*
|
|
11
|
+
* This is the main configuration object that defines how Action Units
|
|
12
|
+
* map to morph targets and bone transformations for a specific rig type.
|
|
13
|
+
*/
|
|
14
|
+
interface AUMappingConfig {
|
|
15
|
+
/** AU ID to morph target names (e.g., AU 12 → ['Mouth_Smile_L', 'Mouth_Smile_R']) */
|
|
16
|
+
auToMorphs: Record<number, string[]>;
|
|
17
|
+
/** AU ID to bone bindings (e.g., AU 51 → [{ node: 'HEAD', channel: 'ry', scale: 1, maxDegrees: 30 }]) */
|
|
18
|
+
auToBones: Record<number, BoneBinding[]>;
|
|
19
|
+
/** Bone key to actual node name in the model (e.g., 'HEAD' → 'CC_Base_Head') */
|
|
20
|
+
boneNodes: Record<string, string>;
|
|
21
|
+
/** Morph category to mesh names (e.g., 'face' → ['CC_Base_Body_1']) */
|
|
22
|
+
morphToMesh: Record<string, string[]>;
|
|
23
|
+
/** Viseme keys in order (typically 15 phoneme positions) */
|
|
24
|
+
visemeKeys: string[];
|
|
25
|
+
/** Optional: Default mix weights for bone/morph blending (0 = morph only, 1 = bone only) */
|
|
26
|
+
auMixDefaults?: Record<number, number>;
|
|
27
|
+
/** Optional: AU metadata (names, muscle basis, etc.) */
|
|
28
|
+
auInfo?: Record<string, AUInfo>;
|
|
29
|
+
/** Optional: Eye mesh node fallbacks (some rigs use mesh nodes instead of bone nodes) */
|
|
30
|
+
eyeMeshNodes?: {
|
|
31
|
+
LEFT: string;
|
|
32
|
+
RIGHT: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Helper type for mesh categories in morphToMesh
|
|
37
|
+
*/
|
|
38
|
+
type MorphCategory = 'face' | 'viseme' | 'eye' | 'tearLine' | 'tongue' | 'hair';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* LoomLarge - Core Type Definitions
|
|
42
|
+
*
|
|
43
|
+
* Type definitions for the 3D character animation engine.
|
|
44
|
+
* These are framework-agnostic interfaces that work with any 3D engine.
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* TransitionHandle - returned from transition methods
|
|
48
|
+
* Provides promise-based completion notification plus fine-grained control.
|
|
49
|
+
*/
|
|
50
|
+
interface TransitionHandle {
|
|
51
|
+
/** Resolves when the transition completes (or is cancelled) */
|
|
52
|
+
promise: Promise<void>;
|
|
53
|
+
/** Pause this transition (holds at current value) */
|
|
54
|
+
pause: () => void;
|
|
55
|
+
/** Resume this transition after pause */
|
|
56
|
+
resume: () => void;
|
|
57
|
+
/** Cancel this transition immediately (resolves promise) */
|
|
58
|
+
cancel: () => void;
|
|
59
|
+
}
|
|
60
|
+
/** Standard bone keys used in AU bindings */
|
|
61
|
+
type BoneKey = 'EYE_L' | 'EYE_R' | 'JAW' | 'HEAD' | 'NECK' | 'TONGUE' | string;
|
|
62
|
+
/**
|
|
63
|
+
* BoneBinding - Defines how an AU maps to bone transformations
|
|
64
|
+
*/
|
|
65
|
+
interface BoneBinding {
|
|
66
|
+
node: BoneKey;
|
|
67
|
+
channel: 'rx' | 'ry' | 'rz' | 'tx' | 'ty' | 'tz';
|
|
68
|
+
scale: -1 | 1;
|
|
69
|
+
maxDegrees?: number;
|
|
70
|
+
maxUnits?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* RotationAxis - Defines which AUs control a specific rotation axis
|
|
74
|
+
*/
|
|
75
|
+
interface RotationAxis {
|
|
76
|
+
aus: number[];
|
|
77
|
+
axis: 'rx' | 'ry' | 'rz';
|
|
78
|
+
negative?: number;
|
|
79
|
+
positive?: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* CompositeRotation - Defines unified rotation axes for bones
|
|
83
|
+
*/
|
|
84
|
+
interface CompositeRotation {
|
|
85
|
+
node: string;
|
|
86
|
+
pitch: RotationAxis | null;
|
|
87
|
+
yaw: RotationAxis | null;
|
|
88
|
+
roll: RotationAxis | null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* AUInfo - Metadata about an Action Unit
|
|
92
|
+
*/
|
|
93
|
+
interface AUInfo {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
muscularBasis?: string;
|
|
97
|
+
links?: string[];
|
|
98
|
+
faceArea?: 'Upper' | 'Lower';
|
|
99
|
+
facePart?: string;
|
|
100
|
+
}
|
|
101
|
+
/** Per-axis rotation state */
|
|
102
|
+
interface RotationAxisState {
|
|
103
|
+
value: number;
|
|
104
|
+
maxRadians: number;
|
|
105
|
+
}
|
|
106
|
+
interface CompositeRotationState {
|
|
107
|
+
pitch: RotationAxisState;
|
|
108
|
+
yaw: RotationAxisState;
|
|
109
|
+
roll: RotationAxisState;
|
|
110
|
+
}
|
|
111
|
+
type RotationsState = Record<string, CompositeRotationState>;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* LoomLarge Engine Interface
|
|
115
|
+
*
|
|
116
|
+
* Defines the contract for 3D character animation engines.
|
|
117
|
+
* Implementations can target different 3D frameworks (Three.js, Babylon.js, etc.)
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Mesh interface - minimal requirements for meshes with morph targets
|
|
122
|
+
*/
|
|
123
|
+
interface LoomMesh {
|
|
124
|
+
name: string;
|
|
125
|
+
visible: boolean;
|
|
126
|
+
isMesh: boolean;
|
|
127
|
+
morphTargetInfluences?: number[];
|
|
128
|
+
morphTargetDictionary?: Record<string, number>;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Vector3-like interface
|
|
132
|
+
*/
|
|
133
|
+
interface LoomVector3 {
|
|
134
|
+
x: number;
|
|
135
|
+
y: number;
|
|
136
|
+
z: number;
|
|
137
|
+
clone(): LoomVector3;
|
|
138
|
+
copy(v: LoomVector3): void;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Euler rotation interface
|
|
142
|
+
*/
|
|
143
|
+
interface LoomEuler {
|
|
144
|
+
x: number;
|
|
145
|
+
y: number;
|
|
146
|
+
z: number;
|
|
147
|
+
order: string;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Quaternion interface
|
|
151
|
+
*/
|
|
152
|
+
interface LoomQuaternion {
|
|
153
|
+
clone(): LoomQuaternion;
|
|
154
|
+
copy(q: LoomQuaternion): void;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Object3D interface - minimal requirements for scene objects
|
|
158
|
+
*/
|
|
159
|
+
interface LoomObject3D {
|
|
160
|
+
name?: string;
|
|
161
|
+
position: LoomVector3;
|
|
162
|
+
quaternion: LoomQuaternion;
|
|
163
|
+
rotation: LoomEuler & {
|
|
164
|
+
set(x: number, y: number, z: number, order: string): void;
|
|
165
|
+
};
|
|
166
|
+
traverse(callback: (obj: any) => void): void;
|
|
167
|
+
getObjectByName(name: string): LoomObject3D | undefined;
|
|
168
|
+
updateMatrixWorld(force: boolean): void;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Payload for initializing the engine with a loaded model
|
|
172
|
+
*/
|
|
173
|
+
interface ReadyPayload {
|
|
174
|
+
meshes: LoomMesh[];
|
|
175
|
+
model: LoomObject3D;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Configuration options for the LoomLarge engine
|
|
179
|
+
*/
|
|
180
|
+
interface LoomLargeConfig {
|
|
181
|
+
/** AU to morph target mappings */
|
|
182
|
+
auMappings?: AUMappingConfig;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Mesh info returned from getMeshList()
|
|
186
|
+
*/
|
|
187
|
+
interface MeshInfo {
|
|
188
|
+
name: string;
|
|
189
|
+
visible: boolean;
|
|
190
|
+
morphCount: number;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* LoomLarge Engine Interface
|
|
194
|
+
*
|
|
195
|
+
* The main interface for controlling 3D character facial animation.
|
|
196
|
+
* Supports Action Units (AUs), morph targets, visemes, and bone control.
|
|
197
|
+
*/
|
|
198
|
+
interface LoomLarge {
|
|
199
|
+
/**
|
|
200
|
+
* Initialize the engine with a loaded model.
|
|
201
|
+
* Call this after loading your 3D model.
|
|
202
|
+
*/
|
|
203
|
+
onReady(payload: ReadyPayload): void;
|
|
204
|
+
/**
|
|
205
|
+
* Update animation state. Call each frame with delta time in seconds.
|
|
206
|
+
*/
|
|
207
|
+
update(deltaSeconds: number): void;
|
|
208
|
+
/**
|
|
209
|
+
* Dispose engine resources and cleanup.
|
|
210
|
+
*/
|
|
211
|
+
dispose(): void;
|
|
212
|
+
/**
|
|
213
|
+
* Set AU value immediately (no transition)
|
|
214
|
+
* @param id - AU number (e.g., 12 for smile) or string ('12L' for left side)
|
|
215
|
+
* @param v - Value 0-1
|
|
216
|
+
* @param balance - Optional L/R balance: -1 = left only, 0 = both, +1 = right only
|
|
217
|
+
*/
|
|
218
|
+
setAU(id: number | string, v: number, balance?: number): void;
|
|
219
|
+
/**
|
|
220
|
+
* Transition AU value smoothly over time
|
|
221
|
+
* @param id - AU number or string
|
|
222
|
+
* @param to - Target value 0-1
|
|
223
|
+
* @param durationMs - Transition duration in milliseconds
|
|
224
|
+
* @param balance - Optional L/R balance
|
|
225
|
+
*/
|
|
226
|
+
transitionAU(id: number | string, to: number, durationMs?: number, balance?: number): TransitionHandle;
|
|
227
|
+
/**
|
|
228
|
+
* Get current AU value
|
|
229
|
+
*/
|
|
230
|
+
getAU(id: number): number;
|
|
231
|
+
/**
|
|
232
|
+
* Set morph target value immediately
|
|
233
|
+
* @param key - Morph target name
|
|
234
|
+
* @param v - Value 0-1
|
|
235
|
+
* @param meshNames - Optional specific meshes to target
|
|
236
|
+
*/
|
|
237
|
+
setMorph(key: string, v: number, meshNames?: string[]): void;
|
|
238
|
+
/**
|
|
239
|
+
* Transition morph target value smoothly
|
|
240
|
+
* @param key - Morph target name
|
|
241
|
+
* @param to - Target value 0-1
|
|
242
|
+
* @param durationMs - Transition duration in milliseconds
|
|
243
|
+
* @param meshNames - Optional specific meshes to target
|
|
244
|
+
*/
|
|
245
|
+
transitionMorph(key: string, to: number, durationMs?: number, meshNames?: string[]): TransitionHandle;
|
|
246
|
+
/**
|
|
247
|
+
* Set viseme value immediately (for lip-sync)
|
|
248
|
+
* @param visemeIndex - Viseme index 0-14
|
|
249
|
+
* @param value - Value 0-1
|
|
250
|
+
* @param jawScale - Jaw movement multiplier (default 1.0)
|
|
251
|
+
*/
|
|
252
|
+
setViseme(visemeIndex: number, value: number, jawScale?: number): void;
|
|
253
|
+
/**
|
|
254
|
+
* Transition viseme value smoothly
|
|
255
|
+
*/
|
|
256
|
+
transitionViseme(visemeIndex: number, to: number, durationMs?: number, jawScale?: number): TransitionHandle;
|
|
257
|
+
/**
|
|
258
|
+
* Set mix weight for an AU (blend between morph and bone contribution)
|
|
259
|
+
*/
|
|
260
|
+
setAUMixWeight(id: number, weight: number): void;
|
|
261
|
+
/**
|
|
262
|
+
* Get current mix weight for an AU
|
|
263
|
+
*/
|
|
264
|
+
getAUMixWeight(id: number): number;
|
|
265
|
+
/**
|
|
266
|
+
* Pause all transitions
|
|
267
|
+
*/
|
|
268
|
+
pause(): void;
|
|
269
|
+
/**
|
|
270
|
+
* Resume all transitions
|
|
271
|
+
*/
|
|
272
|
+
resume(): void;
|
|
273
|
+
/**
|
|
274
|
+
* Check if engine is paused
|
|
275
|
+
*/
|
|
276
|
+
getPaused(): boolean;
|
|
277
|
+
/**
|
|
278
|
+
* Clear all active transitions
|
|
279
|
+
*/
|
|
280
|
+
clearTransitions(): void;
|
|
281
|
+
/**
|
|
282
|
+
* Get count of active transitions
|
|
283
|
+
*/
|
|
284
|
+
getActiveTransitionCount(): number;
|
|
285
|
+
/**
|
|
286
|
+
* Reset all facial animation to neutral state
|
|
287
|
+
*/
|
|
288
|
+
resetToNeutral(): void;
|
|
289
|
+
/**
|
|
290
|
+
* Get list of all meshes in the model
|
|
291
|
+
*/
|
|
292
|
+
getMeshList(): MeshInfo[];
|
|
293
|
+
/**
|
|
294
|
+
* Set mesh visibility
|
|
295
|
+
*/
|
|
296
|
+
setMeshVisible(meshName: string, visible: boolean): void;
|
|
297
|
+
/**
|
|
298
|
+
* Update AU mappings configuration
|
|
299
|
+
*/
|
|
300
|
+
setAUMappings(mappings: AUMappingConfig): void;
|
|
301
|
+
/**
|
|
302
|
+
* Get current AU mappings configuration
|
|
303
|
+
*/
|
|
304
|
+
getAUMappings(): AUMappingConfig;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Animation System Interface
|
|
309
|
+
*
|
|
310
|
+
* Defines the contract for transition/animation systems.
|
|
311
|
+
* Implementations can use different interpolation strategies.
|
|
312
|
+
*/
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Animation system that manages value transitions over time.
|
|
316
|
+
*/
|
|
317
|
+
interface Animation {
|
|
318
|
+
/**
|
|
319
|
+
* Update all active transitions by delta time.
|
|
320
|
+
* @param dtSeconds - Time elapsed since last tick in seconds
|
|
321
|
+
*/
|
|
322
|
+
tick(dtSeconds: number): void;
|
|
323
|
+
/**
|
|
324
|
+
* Add or replace a transition for the given key.
|
|
325
|
+
* If a transition with the same key exists, it should be cancelled and replaced.
|
|
326
|
+
*
|
|
327
|
+
* @param key - Unique identifier for this transition
|
|
328
|
+
* @param from - Starting value
|
|
329
|
+
* @param to - Target value
|
|
330
|
+
* @param durationMs - Duration in milliseconds
|
|
331
|
+
* @param apply - Callback to apply the interpolated value
|
|
332
|
+
* @param easing - Optional easing function (default: ease-in-out)
|
|
333
|
+
* @returns TransitionHandle for control
|
|
334
|
+
*/
|
|
335
|
+
addTransition(key: string, from: number, to: number, durationMs: number, apply: (value: number) => void, easing?: (t: number) => number): TransitionHandle;
|
|
336
|
+
/**
|
|
337
|
+
* Clear all active transitions.
|
|
338
|
+
*/
|
|
339
|
+
clearTransitions(): void;
|
|
340
|
+
/**
|
|
341
|
+
* Get count of active transitions.
|
|
342
|
+
*/
|
|
343
|
+
getActiveTransitionCount(): number;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* LoomLargeThree - Three.js Implementation
|
|
348
|
+
*
|
|
349
|
+
* Default implementation of the LoomLarge interface for Three.js.
|
|
350
|
+
* Controls 3D character facial animation using Action Units (AUs),
|
|
351
|
+
* morph targets, visemes, and bone transformations.
|
|
352
|
+
*/
|
|
353
|
+
|
|
354
|
+
declare class LoomLargeThree implements LoomLarge {
|
|
355
|
+
private config;
|
|
356
|
+
private animation;
|
|
357
|
+
private auValues;
|
|
358
|
+
private rigReady;
|
|
359
|
+
private missingBoneWarnings;
|
|
360
|
+
private rotations;
|
|
361
|
+
private pendingCompositeNodes;
|
|
362
|
+
private isPaused;
|
|
363
|
+
private translations;
|
|
364
|
+
private faceMesh;
|
|
365
|
+
private meshes;
|
|
366
|
+
private model;
|
|
367
|
+
private meshByName;
|
|
368
|
+
private morphCache;
|
|
369
|
+
private bones;
|
|
370
|
+
private mixWeights;
|
|
371
|
+
private visemeValues;
|
|
372
|
+
private static readonly VISEME_JAW_AMOUNTS;
|
|
373
|
+
private static readonly JAW_MAX_DEGREES;
|
|
374
|
+
constructor(config?: LoomLargeConfig, animation?: Animation);
|
|
375
|
+
onReady(payload: ReadyPayload): void;
|
|
376
|
+
update(deltaSeconds: number): void;
|
|
377
|
+
dispose(): void;
|
|
378
|
+
setAU(id: number | string, v: number, balance?: number): void;
|
|
379
|
+
transitionAU(id: number | string, to: number, durationMs?: number, balance?: number): TransitionHandle;
|
|
380
|
+
getAU(id: number): number;
|
|
381
|
+
setMorph(key: string, v: number, meshNames?: string[]): void;
|
|
382
|
+
transitionMorph(key: string, to: number, durationMs?: number, meshNames?: string[]): TransitionHandle;
|
|
383
|
+
setViseme(visemeIndex: number, value: number, jawScale?: number): void;
|
|
384
|
+
transitionViseme(visemeIndex: number, to: number, durationMs?: number, jawScale?: number): TransitionHandle;
|
|
385
|
+
setAUMixWeight(id: number, weight: number): void;
|
|
386
|
+
getAUMixWeight(id: number): number;
|
|
387
|
+
pause(): void;
|
|
388
|
+
resume(): void;
|
|
389
|
+
getPaused(): boolean;
|
|
390
|
+
clearTransitions(): void;
|
|
391
|
+
getActiveTransitionCount(): number;
|
|
392
|
+
resetToNeutral(): void;
|
|
393
|
+
getMeshList(): MeshInfo[];
|
|
394
|
+
setMeshVisible(meshName: string, visible: boolean): void;
|
|
395
|
+
setAUMappings(mappings: AUMappingConfig): void;
|
|
396
|
+
getAUMappings(): AUMappingConfig;
|
|
397
|
+
private computeSideValues;
|
|
398
|
+
private getMeshNamesForAU;
|
|
399
|
+
private getMorphValue;
|
|
400
|
+
private isMixedAU;
|
|
401
|
+
private initBoneRotations;
|
|
402
|
+
private updateBoneRotation;
|
|
403
|
+
private updateBoneTranslation;
|
|
404
|
+
private transitionBoneRotation;
|
|
405
|
+
private transitionBoneTranslation;
|
|
406
|
+
private flushPendingComposites;
|
|
407
|
+
private applyCompositeRotation;
|
|
408
|
+
private resolveBones;
|
|
409
|
+
private combineHandles;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Helper function to collect meshes with morph targets from a scene.
|
|
413
|
+
*/
|
|
414
|
+
declare function collectMorphMeshes(root: LoomObject3D): LoomMesh[];
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* AnimationThree - Lerp-based animation system
|
|
418
|
+
*
|
|
419
|
+
* Default implementation of the Animation interface.
|
|
420
|
+
* Uses simple lerp interpolation with easing functions.
|
|
421
|
+
*/
|
|
422
|
+
|
|
423
|
+
declare class AnimationThree implements Animation {
|
|
424
|
+
private transitions;
|
|
425
|
+
/**
|
|
426
|
+
* Tick all active transitions by dt seconds.
|
|
427
|
+
* Applies eased interpolation and removes completed transitions.
|
|
428
|
+
* Respects individual transition pause state.
|
|
429
|
+
*/
|
|
430
|
+
tick(dtSeconds: number): void;
|
|
431
|
+
/**
|
|
432
|
+
* Add or replace a transition for the given key.
|
|
433
|
+
* If a transition with the same key exists, it is cancelled and replaced.
|
|
434
|
+
* @returns TransitionHandle with { promise, pause, resume, cancel }
|
|
435
|
+
*/
|
|
436
|
+
addTransition(key: string, from: number, to: number, durationMs: number, apply: (value: number) => void, easing?: (t: number) => number): TransitionHandle;
|
|
437
|
+
/** Clear all running transitions. */
|
|
438
|
+
clearTransitions(): void;
|
|
439
|
+
/** Get count of active transitions. */
|
|
440
|
+
getActiveTransitionCount(): number;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Hair Physics Interface
|
|
445
|
+
*
|
|
446
|
+
* Defines the contract for hair physics simulation systems.
|
|
447
|
+
* Implementations can use different physics models (spring-damper, verlet, etc.)
|
|
448
|
+
*/
|
|
449
|
+
/**
|
|
450
|
+
* Configuration for hair physics simulation
|
|
451
|
+
*/
|
|
452
|
+
interface HairPhysicsConfig$1 {
|
|
453
|
+
mass: number;
|
|
454
|
+
stiffness: number;
|
|
455
|
+
damping: number;
|
|
456
|
+
gravity: number;
|
|
457
|
+
headInfluence: number;
|
|
458
|
+
windEnabled: boolean;
|
|
459
|
+
windStrength: number;
|
|
460
|
+
windDirectionX: number;
|
|
461
|
+
windDirectionZ: number;
|
|
462
|
+
windTurbulence: number;
|
|
463
|
+
windFrequency: number;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Hair strand definition for multi-strand simulation
|
|
467
|
+
*/
|
|
468
|
+
interface HairStrand {
|
|
469
|
+
id: string;
|
|
470
|
+
morphKeys: {
|
|
471
|
+
left: string;
|
|
472
|
+
right: string;
|
|
473
|
+
front?: string;
|
|
474
|
+
back?: string;
|
|
475
|
+
};
|
|
476
|
+
mass?: number;
|
|
477
|
+
stiffness?: number;
|
|
478
|
+
damping?: number;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Current physics state of hair simulation
|
|
482
|
+
*/
|
|
483
|
+
interface HairState {
|
|
484
|
+
x: number;
|
|
485
|
+
z: number;
|
|
486
|
+
vx: number;
|
|
487
|
+
vz: number;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Head orientation state for physics input
|
|
491
|
+
*/
|
|
492
|
+
interface HeadState$1 {
|
|
493
|
+
yaw: number;
|
|
494
|
+
pitch: number;
|
|
495
|
+
roll: number;
|
|
496
|
+
yawVelocity: number;
|
|
497
|
+
pitchVelocity: number;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Output morph values from physics simulation
|
|
501
|
+
*/
|
|
502
|
+
interface HairMorphOutput$1 {
|
|
503
|
+
[morphKey: string]: number;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Hair Physics simulation interface
|
|
507
|
+
*/
|
|
508
|
+
interface HairPhysics$1 {
|
|
509
|
+
/**
|
|
510
|
+
* Update physics simulation
|
|
511
|
+
* @param dt Delta time in seconds
|
|
512
|
+
* @param headState Current head orientation and velocity
|
|
513
|
+
* @returns Morph values to apply to hair meshes
|
|
514
|
+
*/
|
|
515
|
+
update(dt: number, headState: HeadState$1): HairMorphOutput$1;
|
|
516
|
+
/**
|
|
517
|
+
* Get current physics state (for debugging/UI)
|
|
518
|
+
*/
|
|
519
|
+
getState(): HairState;
|
|
520
|
+
/**
|
|
521
|
+
* Update configuration
|
|
522
|
+
*/
|
|
523
|
+
setConfig(config: Partial<HairPhysicsConfig$1>): void;
|
|
524
|
+
/**
|
|
525
|
+
* Get current configuration
|
|
526
|
+
*/
|
|
527
|
+
getConfig(): HairPhysicsConfig$1;
|
|
528
|
+
/**
|
|
529
|
+
* Reset physics state to rest position
|
|
530
|
+
*/
|
|
531
|
+
reset(): void;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* CC4 Preset - Character Creator 4 AU Mappings
|
|
536
|
+
*
|
|
537
|
+
* Complete FACS Action Unit to morph target and bone mappings for CC4 rigs.
|
|
538
|
+
* This includes all the composite rotations, continuum pairs, mesh classifications,
|
|
539
|
+
* and AU metadata that we painstakingly worked through.
|
|
540
|
+
*/
|
|
541
|
+
|
|
542
|
+
declare const CC4_PRESET: AUMappingConfig;
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* HairPhysics - Spring-damper pendulum simulation for hair movement
|
|
546
|
+
*
|
|
547
|
+
* This is a pure physics simulation class with no Three.js dependencies.
|
|
548
|
+
* It outputs normalized morph values (0-1) that can be applied to hair meshes
|
|
549
|
+
* via EngineThree.setMorph() or transitionMorph().
|
|
550
|
+
*
|
|
551
|
+
* Physics model:
|
|
552
|
+
* - Hair is modeled as a damped pendulum affected by:
|
|
553
|
+
* - Gravity (constant downward force based on head orientation)
|
|
554
|
+
* - Head velocity (inertia causes hair to lag behind head movement)
|
|
555
|
+
* - Wind (oscillating force with turbulence)
|
|
556
|
+
* - Spring restoration (hair returns to rest position)
|
|
557
|
+
* - Damping (air resistance)
|
|
558
|
+
*/
|
|
559
|
+
interface HairPhysicsConfig {
|
|
560
|
+
mass: number;
|
|
561
|
+
stiffness: number;
|
|
562
|
+
damping: number;
|
|
563
|
+
gravity: number;
|
|
564
|
+
headInfluence: number;
|
|
565
|
+
windEnabled: boolean;
|
|
566
|
+
windStrength: number;
|
|
567
|
+
windDirectionX: number;
|
|
568
|
+
windDirectionZ: number;
|
|
569
|
+
windTurbulence: number;
|
|
570
|
+
windFrequency: number;
|
|
571
|
+
}
|
|
572
|
+
interface HairPhysicsState {
|
|
573
|
+
x: number;
|
|
574
|
+
z: number;
|
|
575
|
+
vx: number;
|
|
576
|
+
vz: number;
|
|
577
|
+
}
|
|
578
|
+
interface HairMorphOutput {
|
|
579
|
+
L_Hair_Left: number;
|
|
580
|
+
L_Hair_Right: number;
|
|
581
|
+
L_Hair_Front: number;
|
|
582
|
+
R_Hair_Left: number;
|
|
583
|
+
R_Hair_Right: number;
|
|
584
|
+
R_Hair_Front: number;
|
|
585
|
+
}
|
|
586
|
+
interface HeadState {
|
|
587
|
+
yaw: number;
|
|
588
|
+
pitch: number;
|
|
589
|
+
roll: number;
|
|
590
|
+
yawVelocity: number;
|
|
591
|
+
pitchVelocity: number;
|
|
592
|
+
}
|
|
593
|
+
declare const DEFAULT_HAIR_PHYSICS_CONFIG: HairPhysicsConfig;
|
|
594
|
+
declare class HairPhysics {
|
|
595
|
+
private config;
|
|
596
|
+
private state;
|
|
597
|
+
private time;
|
|
598
|
+
private prevHeadYaw;
|
|
599
|
+
private prevHeadPitch;
|
|
600
|
+
constructor(config?: Partial<HairPhysicsConfig>);
|
|
601
|
+
/**
|
|
602
|
+
* Update physics simulation
|
|
603
|
+
* @param dt Delta time in seconds
|
|
604
|
+
* @param headState Current head orientation and velocity
|
|
605
|
+
* @returns Morph values to apply to hair meshes
|
|
606
|
+
*/
|
|
607
|
+
update(dt: number, headState: HeadState): HairMorphOutput;
|
|
608
|
+
/**
|
|
609
|
+
* Convert physics state to morph target values
|
|
610
|
+
* Maps pendulum position to left/right/front morphs for both sides
|
|
611
|
+
*/
|
|
612
|
+
private computeMorphOutput;
|
|
613
|
+
/**
|
|
614
|
+
* Get current physics state (for debugging/UI)
|
|
615
|
+
*/
|
|
616
|
+
getState(): HairPhysicsState;
|
|
617
|
+
/**
|
|
618
|
+
* Update configuration
|
|
619
|
+
*/
|
|
620
|
+
setConfig(config: Partial<HairPhysicsConfig>): void;
|
|
621
|
+
/**
|
|
622
|
+
* Get current configuration
|
|
623
|
+
*/
|
|
624
|
+
getConfig(): HairPhysicsConfig;
|
|
625
|
+
/**
|
|
626
|
+
* Reset physics state to rest position
|
|
627
|
+
*/
|
|
628
|
+
reset(): void;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
export { type AUInfo, type AUMappingConfig, type Animation, AnimationThree, type BoneBinding, type BoneKey, CC4_PRESET, type CompositeRotation, type CompositeRotationState, DEFAULT_HAIR_PHYSICS_CONFIG, type HairMorphOutput$1 as HairMorphOutput, HairPhysics, type HairPhysicsConfig$1 as HairPhysicsConfig, type HairPhysics$1 as HairPhysicsInterface, type HairMorphOutput as HairPhysicsMorphOutput, type HairPhysicsState, type HairState, type HairStrand, type HeadState$1 as HeadState, type LoomEuler, type LoomLarge, type LoomLargeConfig, LoomLargeThree, type LoomMesh, type LoomObject3D, type LoomQuaternion, type LoomVector3, type MeshInfo, type MorphCategory, type ReadyPayload, type RotationAxis, type RotationAxisState, type RotationsState, type TransitionHandle, collectMorphMeshes, LoomLargeThree as default };
|