Parent epic
#19
Problem
Scenes with many identical meshes (trees, rocks, particles, game tiles) currently create individual THREE.Mesh objects, resulting in one draw call per object. For 1 000+ objects this tanks performance. THREE.InstancedMesh can collapse them to a single draw call but its matrix API is verbose and error-prone.
Goal
A composable helper in packages/threejs/src/ that wraps InstancedMesh with a clean, functional API matching the project's existing patterns.
Plan
1. packages/threejs/src/instancing.ts
/**
* Creates a managed InstancedMesh with helpers to set/update instance transforms.
* @param geometry - shared BufferGeometry
* @param material - shared Material
* @param transforms - initial array of { position, rotation, scale } objects
* @returns { mesh, updateInstance, resetInstances }
*/
export const createInstancedMesh = (
geometry: THREE.BufferGeometry,
material: THREE.Material,
transforms: InstanceTransform[]
): InstancedMeshHandle => { … }
- Internally uses a pre-allocated
Matrix4 and Euler/Quaternion — no new in update path
updateInstance(index, transform) mutates the matrix at index and sets instanceMatrix.needsUpdate = true
resetInstances(transforms) bulk-updates all matrices
2. Export from packages/threejs/src/index.ts
3. Apply in at least one existing scene
- Identify a view that renders many identical objects (e.g.
ContinuousWorld tree population in area-population.ts)
- Migrate from individual meshes to
createInstancedMesh
- Measure draw call reduction (before/after comment in PR)
4. Tests (packages/threejs/src/instancing.test.ts)
createInstancedMesh returns a mesh with correct count
updateInstance sets the matrix correctly at a given index
- Pre-allocated scratch objects are not re-created across calls
Acceptance criteria
Parent epic
#19
Problem
Scenes with many identical meshes (trees, rocks, particles, game tiles) currently create individual
THREE.Meshobjects, resulting in one draw call per object. For 1 000+ objects this tanks performance.THREE.InstancedMeshcan collapse them to a single draw call but its matrix API is verbose and error-prone.Goal
A composable helper in
packages/threejs/src/that wrapsInstancedMeshwith a clean, functional API matching the project's existing patterns.Plan
1.
packages/threejs/src/instancing.tsMatrix4andEuler/Quaternion— nonewin update pathupdateInstance(index, transform)mutates the matrix atindexand setsinstanceMatrix.needsUpdate = trueresetInstances(transforms)bulk-updates all matrices2. Export from
packages/threejs/src/index.ts3. Apply in at least one existing scene
ContinuousWorldtree population inarea-population.ts)createInstancedMesh4. Tests (
packages/threejs/src/instancing.test.ts)createInstancedMeshreturns a mesh with correctcountupdateInstancesets the matrix correctly at a given indexAcceptance criteria
createInstancedMeshexported from@webgamekit/threejsnew THREE.*in the update path