Acceptance checklist
Work through this before you submit. Everything has to pass.
Interaction
- OrbitControls damping is on; zoom distance and pitch are both clamped
- Opening shot is around 3.2×R, tilted slightly down, whole model on one screen
- The wheel inside the 3D area never scrolls or zooms the page
- Frame rate holds while a slider is dragged continuously (geometry rebuilds are debounced)
- Changing any parameter leaves the camera where it was and does not interrupt motion
- Drag springs back on release; idle has a slight float;
prefers-reduced-motiondisables all of it - The 3D stage sets
user-select: none— dragging never selects page text
Correctness
- 3D geometry, the 2D canvas and the exported file all come from one IR (change any parameter and all three follow)
- The Y-down → Y-up flip happens once on the content group — not per mesh, not on the geometry. No mirrored text, no holes on the wrong side, no inside-out faces
- Every panel parameter has a visible effect in the 3D view, or is hidden for that mode with an explanation — a parameter that is visible but does nothing is not acceptable
Performance and stability
-
setPixelRatiois clamped (DPR ≤ 2) - Five minutes of continuous parameter changes with flat GPU and JS memory (everything is disposed)
- Hide the tab and come back: the view is intact, not blank, nothing lost
- Mounting at 0×0 still initialises correctly once a real size arrives
- A container resize updates
camera.aspect,updateProjectionMatrix()andsetSize()together — the view refits without stretching
Render quality
- Environment lighting is configured (RoomEnvironment or HDRI) with a directional light on top — not bare AmbientLight
- ACES tone mapping is on
- The environment map and any shared texture are built once and disposed on unmount only — not regenerated or disposed per rebuild
- Top and side materials are separate groups, sides a shade darker
- No three.js deprecation warnings in the browser console