fuzzyworld

nordic-skating / local-littlejs / files / CONVERSION_PLAN.md

Branch local-littlejs · default branch · all branches

CONVERSION_PLAN.md

7.1 KB · history · blame

Nordic Skating to LittleJS Conversion Plan

Overview

This document outlines the strategy for converting the Nordic Skating project from Three.js to LittleJS.

Current Project Analysis

Key Components Using Three.js:

  1. Main Render Loop (src/main.ts) - WebGLRenderer setup - Scene and camera management - Animation loop

  2. Render Components - ice.ts: Ice surface with textures and materials - sky.ts: Sky dome with custom shader (322 lines of GLSL) - marks.ts: Skating trail marks with line geometry - drifts.ts: Drift effects - snow.ts: Particle system with custom shader - shores.ts: Shore elements

Three.js Features Used:

LittleJS Capabilities Analysis

Key Features Available in LittleJS:

  1. 2D/3D Hybrid Rendering: WebGL2 + Canvas2D
  2. 3D Support: - Built-in 3D renderer that shares canvas with 2D - Shape builders, OBJ and glTF model loading - Shadow maps, lights, cameras
  3. Shaders: Shadertoy-style shaders for post-processing or object-level effects
  4. Particles: Robust particle effect system
  5. Physics: Arcade physics and Box2D integration
  6. Textures: Runtime texture loading and atlas support
  7. Audio: Sound and music support with spatial audio
  8. Input: Comprehensive input handling (mouse, keyboard, touch)

Compatibility Notes:

Conversion Strategy

Phase 1: Setup and Prototyping (Week 1)

Tasks: 1. Install LittleJS alongside Three.js 2. Create minimal prototype showing basic scene 3. Test shader compatibility 4. Verify performance characteristics

Implementation:

npm install littlejsengine --save

Phase 2: Core Infrastructure Migration (Week 2-3)

Tasks: 1. Replace Three.js renderer with LittleJS 2. Migrate scene management 3. Convert camera system 4. Set up animation loop compatibility

Key Changes: - Replace THREE.WebGLRenderer with engineInit() pattern - Adapt gameUpdate() and gameRender() callbacks - Convert coordinate systems (LittleJS uses different conventions)

Phase 3: Component-by-Component Migration (Week 4-6)

Order of Migration: 1. Sky System (sky.ts) - Highest priority due to complex shader - Test shader compatibility first

  1. Ice Surface (ice.ts) - Plane geometry conversion - Material adaptation

  2. Snow Particles (snow.ts) - Convert THREE.Points to LittleJS particles - Adapt custom shader

  3. Skating Marks (marks.ts) - Line geometry to LittleJS equivalent

  4. Drifts and Shores - Final render components

Phase 4: Integration and Testing (Week 7-8)

Tasks: 1. Verify all components work together 2. Test performance characteristics 3. Optimize shaders and rendering 4. Ensure mobile compatibility 5. Test on various devices/browsers

Technical Challenges and Solutions

1. Custom Shaders Conversion

Challenge: Sky and snow use complex GLSL shaders with custom uniforms.

Solution: - Adapt shaders to LittleJS's shader system - Map Three.js uniforms to LittleJS equivalents - Test shader performance in LittleJS context

2. Coordinate System Differences

Challenge: LittleJS may use different coordinate conventions.

Solution: - Create conversion utilities for positions/rotations - Test thoroughly with existing lake geometries

3. Particle System Migration

Challenge: THREE.Points with custom shader to LittleJS particles.

Solution: - Use LittleJS's particle system API - Adapt vertex/fragment shaders to LittleJS format - Maintain same visual appearance and performance

4. Material System Differences

Challenge: Different material property names and capabilities.

Solution: - Create material conversion utilities - Test all material combinations (transparent, emissive, etc.)

Implementation Plan

Step 1: Setup Dual Environment

// In main.ts
import * as THREE from 'three'
import { engineInit } from 'littlejsengine'

// Keep Three.js for now, add LittleJS alongside
function gameInit() {
  // Initialize both systems
}

function gameUpdate() {
  // Update both systems in parallel during transition
}

function gameRender() {
  // Render with both, compare results
}

engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost)

Step 2: Create Adapter Utilities

// src/adapters/littlejs-adapter.ts

export class LittleJSAdapter {
  static convertColor(threeColor: THREE.Color): number {
    // Convert Three.js Color to LittleJS format
  }

  static convertVector3(vec: THREE.Vector3): [number, number, number] {
    // Convert Three.js Vector3 to tuple
  }

  static createMaterial(options: { 
    color?: THREE.Color,
    transparent?: boolean,
    emissive?: THREE.Color
  }): any {
    // Create LittleJS material equivalent
  }
}

Step 3: Migrate Sky Component First

// New sky-littlejs.ts
import { engine, createShaderMaterial } from 'littlejsengine'

export class SkyLittleJS {
  private mesh: any

  constructor() {
    // Create LittleJS equivalent of sky dome
    this.mesh = engine.createMesh({
      geometry: engine.createSphereGeometry(1000, 32, 16),
      material: createShaderMaterial({
        vertex: adaptedVertexShader,
        fragment: adaptedFragmentShader,
        uniforms: this.setupUniforms()
      })
    })
  }

  private setupUniforms() {
    // Map Three.js uniforms to LittleJS format
  }
}

Testing Strategy

  1. Unit Tests: Test each component in isolation
  2. Visual Regression: Compare screenshots before/after
  3. Performance Benchmarks: Measure FPS and memory usage
  4. Cross-Browser Testing: Ensure compatibility across browsers
  5. Mobile Testing: Verify touch controls and performance

Rollback Plan

If conversion proves problematic: 1. Maintain Three.js as primary renderer 2. Use LittleJS for specific optimized components only 3. Keep both renderers with feature flags 4. Gradual migration path remains open

Success Criteria

  1. All visual elements maintain same appearance
  2. Performance meets or exceeds current implementation
  3. Mobile compatibility improved
  4. Bundle size reduced (target: < 50KB gzipped)
  5. No regression in functionality
  6. Easier to maintain and extend

Timeline Estimate

Resources

Source
1# Nordic Skating to LittleJS Conversion Plan
2
3## Overview
4This document outlines the strategy for converting the Nordic Skating project from Three.js to LittleJS.
5
6## Current Project Analysis
7
8### Key Components Using Three.js:
91. **Main Render Loop** (`src/main.ts`)
10 - WebGLRenderer setup
11 - Scene and camera management
12 - Animation loop
13
142. **Render Components**
15 - `ice.ts`: Ice surface with textures and materials
16 - `sky.ts`: Sky dome with custom shader (322 lines of GLSL)
17 - `marks.ts`: Skating trail marks with line geometry
18 - `drifts.ts`: Drift effects
19 - `snow.ts`: Particle system with custom shader
20 - `shores.ts`: Shore elements
21
22### Three.js Features Used:
23- WebGLRenderer
24- Scene, PerspectiveCamera
25- Mesh, Geometry (PlaneGeometry, SphereGeometry, BufferGeometry)
26- Materials (MeshLambertMaterial, LineBasicMaterial, ShaderMaterial)
27- Textures and texture loading
28- Custom GLSL shaders for sky and snow effects
29- Points system for particles
30
31## LittleJS Capabilities Analysis
32
33### Key Features Available in LittleJS:
341. **2D/3D Hybrid Rendering**: WebGL2 + Canvas2D
352. **3D Support**:
36 - Built-in 3D renderer that shares canvas with 2D
37 - Shape builders, OBJ and glTF model loading
38 - Shadow maps, lights, cameras
393. **Shaders**: Shadertoy-style shaders for post-processing or object-level effects
404. **Particles**: Robust particle effect system
415. **Physics**: Arcade physics and Box2D integration
426. **Textures**: Runtime texture loading and atlas support
437. **Audio**: Sound and music support with spatial audio
448. **Input**: Comprehensive input handling (mouse, keyboard, touch)
45
46### Compatibility Notes:
47- LittleJS has its own 3D renderer, but also supports Three.js as a plugin
48- Custom shaders can be adapted to LittleJS's shader system
49- Particle systems need conversion from THREE.Points to LittleJS particles
50- Material system is different but conceptually similar
51
52## Conversion Strategy
53
54### Phase 1: Setup and Prototyping (Week 1)
55
56**Tasks:**
571. Install LittleJS alongside Three.js
582. Create minimal prototype showing basic scene
593. Test shader compatibility
604. Verify performance characteristics
61
62**Implementation:**
63```bash
64npm install littlejsengine --save
65```
66
67### Phase 2: Core Infrastructure Migration (Week 2-3)
68
69**Tasks:**
701. Replace Three.js renderer with LittleJS
712. Migrate scene management
723. Convert camera system
734. Set up animation loop compatibility
74
75**Key Changes:**
76- Replace `THREE.WebGLRenderer` with `engineInit()` pattern
77- Adapt `gameUpdate()` and `gameRender()` callbacks
78- Convert coordinate systems (LittleJS uses different conventions)
79
80### Phase 3: Component-by-Component Migration (Week 4-6)
81
82**Order of Migration:**
831. **Sky System** (`sky.ts`)
84 - Highest priority due to complex shader
85 - Test shader compatibility first
86
872. **Ice Surface** (`ice.ts`)
88 - Plane geometry conversion
89 - Material adaptation
90
913. **Snow Particles** (`snow.ts`)
92 - Convert THREE.Points to LittleJS particles
93 - Adapt custom shader
94
954. **Skating Marks** (`marks.ts`)
96 - Line geometry to LittleJS equivalent
97
985. **Drifts and Shores**
99 - Final render components
100
101### Phase 4: Integration and Testing (Week 7-8)
102
103**Tasks:**
1041. Verify all components work together
1052. Test performance characteristics
1063. Optimize shaders and rendering
1074. Ensure mobile compatibility
1085. Test on various devices/browsers
109
110## Technical Challenges and Solutions
111
112### 1. Custom Shaders Conversion
113**Challenge**: Sky and snow use complex GLSL shaders with custom uniforms.
114
115**Solution**:
116- Adapt shaders to LittleJS's shader system
117- Map Three.js uniforms to LittleJS equivalents
118- Test shader performance in LittleJS context
119
120### 2. Coordinate System Differences
121**Challenge**: LittleJS may use different coordinate conventions.
122
123**Solution**:
124- Create conversion utilities for positions/rotations
125- Test thoroughly with existing lake geometries
126
127### 3. Particle System Migration
128**Challenge**: THREE.Points with custom shader to LittleJS particles.
129
130**Solution**:
131- Use LittleJS's particle system API
132- Adapt vertex/fragment shaders to LittleJS format
133- Maintain same visual appearance and performance
134
135### 4. Material System Differences
136**Challenge**: Different material property names and capabilities.
137
138**Solution**:
139- Create material conversion utilities
140- Test all material combinations (transparent, emissive, etc.)
141
142## Implementation Plan
143
144### Step 1: Setup Dual Environment
145```typescript
146// In main.ts
147import * as THREE from 'three'
148import { engineInit } from 'littlejsengine'
149
150// Keep Three.js for now, add LittleJS alongside
151function gameInit() {
152 // Initialize both systems
153}
154
155function gameUpdate() {
156 // Update both systems in parallel during transition
157}
158
159function gameRender() {
160 // Render with both, compare results
161}
162
163engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost)
164```
165
166### Step 2: Create Adapter Utilities
167```typescript
168// src/adapters/littlejs-adapter.ts
169
170export class LittleJSAdapter {
171 static convertColor(threeColor: THREE.Color): number {
172 // Convert Three.js Color to LittleJS format
173 }
174
175 static convertVector3(vec: THREE.Vector3): [number, number, number] {
176 // Convert Three.js Vector3 to tuple
177 }
178
179 static createMaterial(options: {
180 color?: THREE.Color,
181 transparent?: boolean,
182 emissive?: THREE.Color
183 }): any {
184 // Create LittleJS material equivalent
185 }
186}
187```
188
189### Step 3: Migrate Sky Component First
190```typescript
191// New sky-littlejs.ts
192import { engine, createShaderMaterial } from 'littlejsengine'
193
194export class SkyLittleJS {
195 private mesh: any
196
197 constructor() {
198 // Create LittleJS equivalent of sky dome
199 this.mesh = engine.createMesh({
200 geometry: engine.createSphereGeometry(1000, 32, 16),
201 material: createShaderMaterial({
202 vertex: adaptedVertexShader,
203 fragment: adaptedFragmentShader,
204 uniforms: this.setupUniforms()
205 })
206 })
207 }
208
209 private setupUniforms() {
210 // Map Three.js uniforms to LittleJS format
211 }
212}
213```
214
215## Testing Strategy
216
2171. **Unit Tests**: Test each component in isolation
2182. **Visual Regression**: Compare screenshots before/after
2193. **Performance Benchmarks**: Measure FPS and memory usage
2204. **Cross-Browser Testing**: Ensure compatibility across browsers
2215. **Mobile Testing**: Verify touch controls and performance
222
223## Rollback Plan
224
225If conversion proves problematic:
2261. Maintain Three.js as primary renderer
2272. Use LittleJS for specific optimized components only
2283. Keep both renderers with feature flags
2294. Gradual migration path remains open
230
231## Success Criteria
232
2331. All visual elements maintain same appearance
2342. Performance meets or exceeds current implementation
2353. Mobile compatibility improved
2364. Bundle size reduced (target: < 50KB gzipped)
2375. No regression in functionality
2386. Easier to maintain and extend
239
240## Timeline Estimate
241
242- **Total Duration**: 8 weeks
243- **Critical Path**: Shader conversion and particle system migration
244- **Risk Areas**: Complex shaders, coordinate system differences
245
246## Resources
247
248- LittleJS Documentation: https://github.com/KilledByAPixel/LittleJS
249- Three.js to LittleJS Migration Guide (to be created)
250- Test cases for visual regression
251- Performance benchmarks