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 ADDED
@@ -0,0 +1,714 @@
1
+ ![Latticework by Lovelace LOL](LoomLarge.png)
2
+
3
+ # LoomLarge (Latticework Animation Platform)
4
+
5
+ **LoomLarge** is a next-generation interactive 3D character animation platform built on **Latticework**, featuring reactive state management with XState, facial animation control via ARKit FACS (Facial Action Coding System), and modular agency-based architecture for lip-sync, eye/head tracking, prosodic expression, and conversational AI.
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+ 1. [Quick Start](#quick-start)
11
+ 2. [Core Concepts](#core-concepts)
12
+ - [Latticework Architecture](#latticework-architecture)
13
+ - [Composite Rotation System](#composite-rotation-system)
14
+ - [XState & Reactive Services](#xstate--reactive-services)
15
+ 3. [Installation](#installation)
16
+ 4. [Project Structure](#project-structure)
17
+ 5. [How It Works](#how-it-works)
18
+ - [Animation Service](#animation-service)
19
+ - [Eye & Head Tracking](#eye--head-tracking)
20
+ - [Lip-Sync Agency](#lip-sync-agency)
21
+ - [Prosodic Expression](#prosodic-expression)
22
+ 6. [Modules](#modules)
23
+ 7. [Development](#development)
24
+ 8. [Deployment](#deployment)
25
+ 9. [License & Acknowledgments](#license--acknowledgments)
26
+
27
+ ---
28
+
29
+ ## Quick Start
30
+
31
+ ```bash
32
+ # Clone the repository
33
+ git clone https://github.com/meekmachine/LoomLarge.git
34
+ cd LoomLarge
35
+
36
+ # Install dependencies
37
+ yarn install
38
+
39
+ # Start development server (Vite)
40
+ yarn dev
41
+
42
+ # Build for production
43
+ yarn build
44
+
45
+ # Deploy to GitHub Pages
46
+ yarn deploy
47
+ ```
48
+
49
+ The development server will start at `http://localhost:5173` with hot module replacement enabled.
50
+
51
+ ---
52
+
53
+ ## Core Concepts
54
+
55
+ ### Latticework Architecture
56
+
57
+ - **Agency-Based Design**: Independent services (agencies) handle specialized tasks:
58
+ - **Animation Agency**: Core snippet scheduling and playback
59
+ - **Lip-Sync Agency**: Phoneme prediction and viseme animation
60
+ - **Prosodic Expression Agency**: Emotional head gestures and speech timing
61
+ - **Eye/Head Tracking Agency**: Gaze control with mouse, webcam, or manual modes
62
+ - **Conversation Agency**: Multi-modal conversational AI orchestration
63
+
64
+ - **Immutable State**: Reactive state management ensures predictable updates and time-travel debugging
65
+ - **XState Machines**: Declarative state machines replace callback hell and ad-hoc timers
66
+
67
+ ### Composite Rotation System
68
+
69
+ The **Composite Rotation System** in EngineThree allows smooth blending of blendshapes (morphs) and bone rotations:
70
+
71
+ - **Continuum Values** (-1 to +1): Single value controls paired AUs (e.g., Head Left ↔ Right)
72
+ - **Mix Weights** (0 to 1): Blend between 100% morph (0) and 100% bone (1)
73
+ - **Unified Rotation State**: Prevents axis conflicts when multiple systems control the same bones
74
+
75
+ Example:
76
+ ```typescript
77
+ // Eyes: -1 (look left) to +1 (look right)
78
+ engine.applyEyeComposite(yaw, pitch);
79
+
80
+ // Head: yaw/pitch/roll with mix control
81
+ engine.applyHeadComposite(yaw, pitch, roll);
82
+ ```
83
+
84
+ ### XState & Reactive Services
85
+
86
+ - **XState 5.x**: Modern state machines with TypeScript support
87
+ - **Service Pattern**: Each agency exposes a service with start/stop/update lifecycle
88
+ - **Global Context**: Services registered in `ModulesContext` for cross-component access
89
+
90
+ ---
91
+
92
+ ## Installation
93
+
94
+ ### Prerequisites
95
+
96
+ - **Node.js** 18+ (LTS recommended)
97
+ - **Yarn** 1.22+ or npm 8+
98
+ - Modern browser with WebGL 2.0 support
99
+
100
+ ### Setup Steps
101
+
102
+ 1. **Clone and install**:
103
+ ```bash
104
+ git clone https://github.com/meekmachine/LoomLarge.git
105
+ cd LoomLarge
106
+ yarn install
107
+ ```
108
+
109
+ 2. **Add your 3D model**:
110
+ - Place GLB file in `public/characters/`
111
+ - Update model path in `src/App.tsx`:
112
+ ```typescript
113
+ const glbSrc = import.meta.env.BASE_URL + "characters/your-model.glb";
114
+ ```
115
+
116
+ 3. **Configure API keys** (optional, for AI modules):
117
+ - Create `.env.local`:
118
+ ```
119
+ VITE_ANTHROPIC_API_KEY=sk-ant-...
120
+ ```
121
+
122
+ 4. **Start development**:
123
+ ```bash
124
+ yarn dev
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Project Structure
130
+
131
+ ```
132
+ LoomLarge/
133
+ ├── README.md # ← This file
134
+ ├── package.json
135
+ ├── vite.config.ts # Vite bundler config
136
+ ├── public/
137
+ │ ├── characters/ # GLB 3D models
138
+ │ ├── animations/ # Pre-baked animation JSON
139
+ │ ├── models/ # ML models (face-api.js)
140
+ │ └── skyboxes/ # Environment maps
141
+ ├── src/
142
+ │ ├── App.tsx # Main React app entry
143
+ │ ├── main.tsx # Vite entry point
144
+ │ ├── engine/
145
+ │ │ ├── EngineThree.ts # Three.js engine (AU/morph control)
146
+ │ │ ├── EngineWind.ts # Wind physics for hair/cloth
147
+ │ │ └── arkit/
148
+ │ │ └── shapeDict.ts # ARKit FACS AU → morph mappings
149
+ │ ├── latticework/ # Core agencies
150
+ │ │ ├── animation/ # Animation scheduler (XState)
151
+ │ │ ├── lipsync/ # Lip-sync phoneme predictor
152
+ │ │ ├── prosodic/ # Prosodic expression (head gestures)
153
+ │ │ ├── eyeHeadTracking/ # Eye/head tracking service
154
+ │ │ ├── conversation/ # Conversational AI orchestration
155
+ │ │ └── transcription/ # Speech-to-text services
156
+ │ ├── components/
157
+ │ │ ├── au/ # AU control UI components
158
+ │ │ │ ├── AUSection.tsx # AU sliders
159
+ │ │ │ ├── VisemeSection.tsx # Viseme controls
160
+ │ │ │ ├── EyeHeadTrackingSection.tsx # Eye/head tracking UI
161
+ │ │ │ └── ContinuumSlider.tsx # Bidirectional AU slider
162
+ │ │ ├── SliderDrawer.tsx # Main dockable UI drawer
163
+ │ │ ├── PlaybackControls.tsx # Animation playback controls
164
+ │ │ ├── CurveEditor.tsx # Visual curve editor
165
+ │ │ └── ModulesMenu.tsx # Module activation UI
166
+ │ ├── modules/ # Pluggable modules
167
+ │ │ ├── aiChat/ # AI chat module (Anthropic)
168
+ │ │ ├── frenchQuiz/ # French quiz demo module
169
+ │ │ └── config.ts # Module registry
170
+ │ ├── context/
171
+ │ │ ├── threeContext.tsx # Global engine/animation context
172
+ │ │ └── ModulesContext.tsx # Module state management
173
+ │ ├── hooks/
174
+ │ │ └── useWebcamEyeTracking.ts # Webcam face tracking hook
175
+ │ ├── scenes/
176
+ │ │ └── CharacterGLBScene.tsx # Three.js React scene
177
+ │ └── utils/
178
+ │ └── animationLoader.ts # Load animation JSON files
179
+ └── docs/ # Documentation
180
+ ├── QUICK_START.md
181
+ ├── LIPSYNC_COMPLETE_GUIDE.md
182
+ ├── BACKEND_INTEGRATION.md
183
+ └── DEPLOYMENT.md
184
+ ```
185
+
186
+ ---
187
+
188
+ ## How It Works
189
+
190
+ ### Animation Service
191
+
192
+ The **Animation Service** (`latticework/animation/animationService.ts`) is the core scheduler:
193
+
194
+ 1. **Load Snippets**: JSON files defining AU/morph keyframe curves
195
+ ```typescript
196
+ const anim = createAnimationService(host);
197
+ anim.loadSnippet('smile', smileSnippetJSON);
198
+ ```
199
+
200
+ 2. **Schedule Playback**: Queue snippets with priority and duration
201
+ ```typescript
202
+ anim.schedule('smile', {
203
+ duration: 1000,
204
+ priority: 10,
205
+ loop: false
206
+ });
207
+ ```
208
+
209
+ 3. **XState Machine**: Manages snippet lifecycle (`idle` → `playing` → `paused`)
210
+ - Driven by central frame loop (`threeContext.tsx`)
211
+ - Handles overlapping snippets with priority-based blending
212
+
213
+ 4. **Host Interface**: Abstraction layer for AU/morph application
214
+ ```typescript
215
+ const host = {
216
+ applyAU: (id, value) => engine.setAU(id, value),
217
+ setMorph: (key, value) => engine.setMorph(key, value),
218
+ transitionAU: (id, value, duration) => engine.transitionAU(id, value, duration)
219
+ };
220
+ ```
221
+
222
+ ### Eye & Head Tracking
223
+
224
+ The **Eye/Head Tracking Service** (`latticework/eyeHeadTracking/eyeHeadTrackingService.ts`) provides three tracking modes:
225
+
226
+ 1. **Manual Mode**: Direct slider control of gaze direction
227
+ 2. **Mouse Mode**: Character follows cursor with mirror behavior
228
+ - Mouse left → Character looks right (at user)
229
+ - Negative x coordinate for natural gaze
230
+ 3. **Webcam Mode**: Face tracking using BlazeFace model
231
+ - Real-time eye position detection
232
+ - Normalized coordinates (-1 to 1)
233
+
234
+ **Key Features**:
235
+ - **Composite Methods**: Uses `applyEyeComposite(yaw, pitch)` and `applyHeadComposite(yaw, pitch, roll)`
236
+ - **Intensity Control**: Separate sliders for eye and head movement intensity
237
+ - **Head Follow Eyes**: Optional delayed head movement matching eye gaze
238
+ - **Global Service**: Created in App.tsx and shared via ModulesContext
239
+
240
+ **Usage**:
241
+ ```typescript
242
+ // Initialize service with engine reference
243
+ const service = createEyeHeadTrackingService({
244
+ eyeTrackingEnabled: true,
245
+ headTrackingEnabled: true,
246
+ headFollowEyes: true,
247
+ eyeIntensity: 1.0,
248
+ headIntensity: 0.5,
249
+ engine: engine
250
+ });
251
+
252
+ service.start();
253
+ service.setMode('mouse'); // or 'webcam' or 'manual'
254
+
255
+ // Set gaze target manually
256
+ service.setGazeTarget({ x: 0.5, y: -0.2, z: 0 });
257
+ ```
258
+
259
+ ### Lip-Sync Agency
260
+
261
+ The **Lip-Sync Agency** (`latticework/lipsync/`) generates viseme animations from text:
262
+
263
+ 1. **Phoneme Prediction**: Enhanced predictor with coarticulation model
264
+ ```typescript
265
+ const predictor = new EnhancedPhonemePredictor();
266
+ const phonemes = predictor.predict('Hello world');
267
+ ```
268
+
269
+ 2. **Viseme Mapping**: Phonemes → ARKit visemes (AA, CH_J, DD, etc.)
270
+ - Timing based on phoneme duration and speech rate
271
+ - Coarticulation smoothing between adjacent phonemes
272
+
273
+ 3. **Animation Snippet Generation**: Creates JSON snippets for animation service
274
+ ```typescript
275
+ const snippet = generateLipsyncSnippet(text, {
276
+ speechRate: 1.0,
277
+ intensity: 0.8,
278
+ style: 'relaxed' // or 'precise', 'theatrical', etc.
279
+ });
280
+ ```
281
+
282
+ 4. **Integration**: Scheduled via animation service with high priority (30)
283
+
284
+ ### Prosodic Expression
285
+
286
+ The **Prosodic Expression Agency** (`latticework/prosodic/prosodicService.ts`) adds emotional head movements:
287
+
288
+ 1. **XState Machine**: Models prosodic states (idle → analyzing → expressing)
289
+ 2. **Gesture Library**: Pre-defined head nods, tilts, and shakes
290
+ - Nod: Positive affirmation (head pitch down)
291
+ - Shake: Negation (head yaw side-to-side)
292
+ - Tilt: Curiosity/emphasis (head roll)
293
+
294
+ 3. **Emotion Mapping**: Text analysis triggers appropriate gestures
295
+ ```typescript
296
+ // Question → slight head tilt
297
+ // Exclamation → head nod emphasis
298
+ // Negation words → head shake
299
+ ```
300
+
301
+ 4. **Scheduling**: Prosodic snippets scheduled with medium priority (20)
302
+
303
+ ---
304
+
305
+ ## Modules
306
+
307
+ LoomLarge supports pluggable modules for extended functionality:
308
+
309
+ ### AI Chat Module
310
+ - **Description**: Real-time conversational AI using Anthropic Claude
311
+ - **Location**: `src/modules/aiChat/`
312
+ - **Features**:
313
+ - Streaming text-to-speech synthesis
314
+ - Lip-sync integration with prosodic expression
315
+ - Eye/head tracking during conversation
316
+ - WebSocket or LiveKit audio streaming
317
+
318
+ **Activation**:
319
+ ```typescript
320
+ // Via ModulesMenu UI or programmatically:
321
+ import { AIChatApp } from './modules/aiChat';
322
+ <AIChatApp animationManager={anim} />
323
+ ```
324
+
325
+ ### French Quiz Module
326
+ - **Description**: Interactive language learning demo
327
+ - **Location**: `src/modules/frenchQuiz/`
328
+ - **Features**:
329
+ - Survey-style question flow
330
+ - Facial expressions tied to correct/incorrect answers
331
+ - Modal-based UI with progress tracking
332
+
333
+ ### Custom Modules
334
+
335
+ Create your own modules by following this pattern:
336
+
337
+ 1. **Define module config** (`src/modules/config.ts`):
338
+ ```typescript
339
+ export default {
340
+ modules: [
341
+ {
342
+ name: 'My Module',
343
+ description: 'Custom module description',
344
+ component: './modules/myModule/index.tsx'
345
+ }
346
+ ]
347
+ };
348
+ ```
349
+
350
+ 2. **Create module component**:
351
+ ```typescript
352
+ // src/modules/myModule/index.tsx
353
+ import React from 'react';
354
+ import { useModulesContext } from '../../context/ModulesContext';
355
+
356
+ export default function MyModule({ animationManager }: any) {
357
+ const { eyeHeadTrackingService } = useModulesContext();
358
+
359
+ // Your module logic here
360
+ return <div>My Module UI</div>;
361
+ }
362
+ ```
363
+
364
+ ---
365
+
366
+ ## Development
367
+
368
+ ### Running the Dev Server
369
+
370
+ ```bash
371
+ yarn dev
372
+ ```
373
+
374
+ Access at `http://localhost:5173` with:
375
+ - Hot module replacement (HMR)
376
+ - Source maps for debugging
377
+ - Console logging for all services
378
+
379
+ ### Testing Animation Snippets
380
+
381
+ Load test animations in the browser console:
382
+
383
+ ```javascript
384
+ // Global handles (auto-exposed in dev mode)
385
+ window.engine // EngineThree instance
386
+ window.anim // Animation service
387
+
388
+ // Load and play a snippet
389
+ anim.loadSnippet('test', {
390
+ duration: 2000,
391
+ keyframes: {
392
+ 'AU_12': [[0, 0], [1000, 1], [2000, 0]], // Smile curve
393
+ 'AU_6': [[0, 0], [1000, 0.8], [2000, 0]] // Cheek raise
394
+ }
395
+ });
396
+ anim.schedule('test', { priority: 10 });
397
+ anim.play();
398
+ ```
399
+
400
+ ### Debugging Eye/Head Tracking
401
+
402
+ The service includes comprehensive diagnostic logging:
403
+
404
+ ```javascript
405
+ // Check current mode
406
+ window.eyeHeadTrackingService?.getMode(); // 'manual' | 'mouse' | 'webcam'
407
+
408
+ // Set gaze manually
409
+ window.eyeHeadTrackingService?.setGazeTarget({ x: 0.5, y: -0.3, z: 0 });
410
+
411
+ // Update configuration
412
+ window.eyeHeadTrackingService?.updateConfig({
413
+ eyeIntensity: 1.0,
414
+ headIntensity: 0.7,
415
+ headFollowEyes: true
416
+ });
417
+ ```
418
+
419
+ ### TypeScript Type Checking
420
+
421
+ ```bash
422
+ yarn typecheck
423
+ ```
424
+
425
+ Runs `tsc --noEmit` to validate types without building.
426
+
427
+ ---
428
+
429
+ ## Deployment
430
+
431
+ ### GitHub Pages Deployment
432
+
433
+ The project is configured for automatic GitHub Pages deployment:
434
+
435
+ ```bash
436
+ yarn deploy
437
+ ```
438
+
439
+ This script:
440
+ 1. Builds production bundle (`yarn build`)
441
+ 2. Deploys to `gh-pages` branch
442
+ 3. Publishes to `https://meekmachine.github.io/LoomLarge`
443
+
444
+ **Configuration** (`vite.config.ts`):
445
+ ```typescript
446
+ export default defineConfig({
447
+ base: '/LoomLarge/', // GitHub repo name
448
+ build: {
449
+ outDir: 'dist',
450
+ assetsDir: 'assets'
451
+ }
452
+ });
453
+ ```
454
+
455
+ ### Custom Domain
456
+
457
+ To use a custom domain:
458
+
459
+ 1. Add `CNAME` file to `public/`:
460
+ ```
461
+ your-domain.com
462
+ ```
463
+
464
+ 2. Configure DNS:
465
+ ```
466
+ A 185.199.108.153
467
+ A 185.199.109.153
468
+ A 185.199.110.153
469
+ A 185.199.111.153
470
+ CNAME www your-username.github.io
471
+ ```
472
+
473
+ 3. Deploy:
474
+ ```bash
475
+ yarn deploy
476
+ ```
477
+
478
+ ---
479
+
480
+ ## API Reference
481
+
482
+ ### Animation Service API
483
+
484
+ ```typescript
485
+ interface AnimationService {
486
+ loadSnippet(name: string, snippet: AnimationSnippet): void;
487
+ schedule(name: string, options?: ScheduleOptions): void;
488
+ play(): void;
489
+ pause(): void;
490
+ stop(): void;
491
+ setLoop(loop: boolean): void;
492
+ scrub(time: number): void;
493
+ step(deltaSeconds: number): void;
494
+ dispose(): void;
495
+ }
496
+ ```
497
+
498
+ ### Eye/Head Tracking Service API
499
+
500
+ ```typescript
501
+ interface EyeHeadTrackingService {
502
+ start(): void;
503
+ stop(): void;
504
+ setGazeTarget(target: GazeTarget): void;
505
+ setMode(mode: 'manual' | 'mouse' | 'webcam'): void;
506
+ getMode(): 'manual' | 'mouse' | 'webcam';
507
+ updateConfig(config: Partial<EyeHeadTrackingConfig>): void;
508
+ setSpeaking(isSpeaking: boolean): void;
509
+ setListening(isListening: boolean): void;
510
+ blink(): void;
511
+ dispose(): void;
512
+ }
513
+ ```
514
+
515
+ ### EngineThree Composite Methods
516
+
517
+ ```typescript
518
+ class EngineThree {
519
+ // Eye composite rotation (yaw/pitch)
520
+ applyEyeComposite(yaw: number, pitch: number): void;
521
+
522
+ // Head composite rotation (yaw/pitch/roll)
523
+ applyHeadComposite(yaw: number, pitch: number, roll?: number): void;
524
+
525
+ // Get/Set AU mix weight (morph ↔ bone blend)
526
+ getAUMixWeight(auId: number): number | undefined;
527
+ setAUMixWeight(auId: number, mix: number): void;
528
+
529
+ // Direct AU control
530
+ setAU(id: number | string, value: number): void;
531
+ setMorph(key: string, value: number): void;
532
+
533
+ // Smooth transitions
534
+ transitionAU(id: number | string, target: number, duration?: number): void;
535
+ transitionMorph(key: string, target: number, duration?: number): void;
536
+ }
537
+ ```
538
+
539
+ ---
540
+
541
+ ## Troubleshooting
542
+
543
+ ### Character Not Moving
544
+
545
+ 1. **Check engine initialization**:
546
+ ```javascript
547
+ console.log(window.engine); // Should show EngineThree instance
548
+ ```
549
+
550
+ 2. **Verify service startup**:
551
+ ```javascript
552
+ console.log(window.anim?.getSnapshot?.().value); // Should show 'playing' or 'idle'
553
+ ```
554
+
555
+ 3. **Check eye/head tracking**:
556
+ ```javascript
557
+ window.eyeHeadTrackingService?.getState(); // Should show current gaze/status
558
+ ```
559
+
560
+ ### Eye Tracking Direction Issues
561
+
562
+ - **Eyes looking wrong way**: Check coordinate negation in `eyeHeadTrackingService.ts:283`
563
+ - **Head not following**: Verify `headFollowEyes` is enabled in config
564
+ - **Intensity too low**: Increase `eyeIntensity` and `headIntensity` sliders
565
+
566
+ ### Animation Not Loading
567
+
568
+ 1. **Check JSON format**:
569
+ - Must have `duration` and `keyframes` fields
570
+ - AU keys must match ARKit spec (e.g., 'AU_12', not '12')
571
+
572
+ 2. **Verify snippet name**:
573
+ ```javascript
574
+ anim.listSnippets(); // Show all loaded snippets
575
+ ```
576
+
577
+ 3. **Check console for errors**:
578
+ - Look for `[Animation]` prefixed logs
579
+ - Validate keyframe curve format: `[[time, value], ...]`
580
+
581
+ ### TensorFlow.js Bundling Errors
582
+
583
+ If you encounter errors related to TensorFlow.js modules (e.g., `@tensorflow/tfjs-core/dist/ops/ops_for_converter`), this is a **known issue** with TensorFlow.js 4.x and Vite.
584
+
585
+ **The Problem:**
586
+ - TensorFlow.js references internal module paths that don't actually exist in the npm package
587
+ - Vite's esbuild optimizer cannot resolve these phantom paths
588
+ - Results in 100+ bundling errors about missing exports and modules
589
+
590
+ **Solution (Already Implemented):**
591
+ LoomLarge loads TensorFlow.js and BlazeFace from **CDN** instead of npm packages:
592
+
593
+ ```html
594
+ <!-- index.html -->
595
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.22.0/dist/tf.min.js"></script>
596
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface@0.0.7/dist/blazeface.js"></script>
597
+ ```
598
+
599
+ The code uses global `blazeface` object with TypeScript declarations:
600
+ ```typescript
601
+ // useWebcamEyeTracking.ts
602
+ declare const blazeface: any;
603
+ const model = await blazeface.load();
604
+ ```
605
+
606
+ Vite config excludes TensorFlow packages from optimization:
607
+ ```typescript
608
+ // vite.config.ts
609
+ optimizeDeps: {
610
+ exclude: [
611
+ '@tensorflow/tfjs',
612
+ '@tensorflow/tfjs-core',
613
+ '@tensorflow/tfjs-converter',
614
+ '@tensorflow/tfjs-backend-cpu',
615
+ '@tensorflow/tfjs-backend-webgl',
616
+ '@tensorflow-models/blazeface',
617
+ ],
618
+ }
619
+ ```
620
+
621
+ **If you still see errors:**
622
+ 1. Ensure TensorFlow packages are NOT in `package.json` dependencies
623
+ 2. Clear Vite cache: `rm -rf node_modules/.vite`
624
+ 3. Restart dev server: `yarn dev`
625
+
626
+ See [src/hooks/README_useWebcamEyeTracking.md](src/hooks/README_useWebcamEyeTracking.md) for full documentation.
627
+
628
+ ### Build Errors
629
+
630
+ ```bash
631
+ # Clear cache and rebuild
632
+ rm -rf node_modules dist .vite
633
+ yarn install
634
+ yarn build
635
+ ```
636
+
637
+ ---
638
+
639
+ ## Performance Optimization
640
+
641
+ ### Animation Loop
642
+
643
+ - Central frame loop runs at 60 FPS (`threeContext.tsx`)
644
+ - Animation scheduler ticks every frame via `step(deltaTime)`
645
+ - Morph/bone updates batched per frame
646
+
647
+ ### Composite Rotation Caching
648
+
649
+ - Rotation state cached in `compositeRotationState` map
650
+ - Only recalculates when values change
651
+ - Avoids redundant Three.js object updates
652
+
653
+ ### Snippet Scheduling
654
+
655
+ - Priority-based scheduler prevents conflicts
656
+ - Lower priority snippets paused when higher priority plays
657
+ - Automatic cleanup of completed snippets
658
+
659
+ ---
660
+
661
+ ## Contributing
662
+
663
+ We welcome contributions! Please follow these guidelines:
664
+
665
+ 1. **Fork and clone** the repository
666
+ 2. **Create a feature branch**: `git checkout -b feature/my-feature`
667
+ 3. **Follow code style**:
668
+ - TypeScript strict mode
669
+ - ESLint/Prettier for formatting
670
+ - Descriptive variable names
671
+ 4. **Test thoroughly**:
672
+ - Manual testing in dev mode
673
+ - TypeScript type checking (`yarn typecheck`)
674
+ 5. **Commit with descriptive messages**:
675
+ ```
676
+ feat: Add webcam eye tracking support
677
+ fix: Correct head yaw direction in mouse mode
678
+ docs: Update README with API reference
679
+ ```
680
+ 6. **Push and create PR** to `main` branch
681
+
682
+ ---
683
+
684
+ ## License & Acknowledgments
685
+
686
+ **© 2025 Jonathan Sutton Fields, Lovelace LOL**
687
+ Licensed under the **Loom Large, Latticework copyleft license**
688
+
689
+ ### Acknowledgments
690
+
691
+ - **Three.js** – 3D rendering engine
692
+ - **XState** – State machine library
693
+ - **React** – UI framework
694
+ - **Vite** – Lightning-fast bundler
695
+ - **ARKit** – Facial Action Coding System specification
696
+ - **BlazeFace** – Webcam face detection model
697
+
698
+ ### Related Projects
699
+
700
+ - **VISOS** – Predecessor architecture (object-oriented)
701
+ - **eEVA Workbench** – Original survey/conversation platform
702
+ - **Latticework** – Core agency framework
703
+
704
+ ---
705
+
706
+ ## Support
707
+
708
+ - **Issues**: [GitHub Issues](https://github.com/meekmachine/LoomLarge/issues)
709
+ - **Discussions**: [GitHub Discussions](https://github.com/meekmachine/LoomLarge/discussions)
710
+ - **Email**: jonathan@lovelacelol.com
711
+
712
+ ---
713
+
714
+ **Built with ❤️ by the Latticework team**