Try it live About this project
Foldscape Memories (also titled Nature Memories · Duo inside the repository) is an interactive site that unfolds travel photographs into three-dimensional memories, built with React, Three.js, GSAP and Vite. The device presentation grows out of the author’s earlier browser replica of the iPhone Duo foldable (SkentSun / iPhone Duo Depth Lab) — a complete mockup with inner and cover screens, seven poses and two finishes, all animated — and this project adds the memory layer on top.
The home page opens on a closed device and a single photograph. Scroll, and candidate photos enter from the right along a cylindrical path and melt through the edge of the cover screen; press Open memory and the device takes five seconds to unfold and lower the camera while the place in the photograph rises out of the display. There are five memories so far: Round Island Light, a red sailboat in Greenland’s ice, the Kálfeyri coastal house in Iceland, Santorini and Osaka Castle. Drag to orbit, scroll to zoom, and Rewind folds the photograph back along the same timeline. A separate Wallpaper Studio in the top-right corner dresses the inner and cover screens from an uploaded image or video and generates depth in the browser.
The photographs and GLB models for all five cases ship with the repository, so viewing needs no API key; the optional in-browser depth generation downloads an inference model on demand. The site is deployed on Vercel (build output dist/client) under the MIT license, with Apple’s official model and wallpaper assets declared separately in THIRD_PARTY.md and excluded from that license.
Highlights
- The home page is a circular photo gallery: scroll, drag or use the arrow keys, and each photograph travels along a cylindrical path to the device edge and melts into the cover screen; reverse scrolling retraces the same path and can stop at any point.
- Open memory first carries the selected photo to the device and waits for its scene to load, then spends five seconds unfolding, dropping the camera and adjusting zoom before a slow 4°/s auto-orbit; drag to orbit, scroll to zoom, and Rewind runs the timeline backwards into the closed photograph.
- Five memories — Round Island Light, a red sailboat in Greenland’s ice, the Kálfeyri coastal house in Iceland, Santorini and Osaka Castle — each a photograph plus a GLB scene shipped in the repository, so viewing needs no API key.
- The Wallpaper Studio (?view=wallpaper) swaps inner and cover wallpapers from an uploaded image or video, computing a quick depth map in the browser and refining it with a small model for pointer-driven parallax and depth of field; two finishes, Star White and Night Sky; sound is off by default and, once on, is procedural coast noise plus an original ambient chord; reduced-motion disables scene motion, auto-orbit and inertia.
Technical breakdown
3D assets · Five memory-scene GLBs and a foldable device rebuilt from Apple’s model
Each of the five memories is a photograph plus a GLB scene (lighthouse-memory-v2.glb is about 25 MB) stored under public/scenes; at runtime only the upper half of the photo is used as the cover, and the README notes that viewing needs no Tripo API key — the key is only needed when the assets are produced.
The foldable device comes from Apple’s official iPhone Duo USDZ: scripts/prepare-model.mjs drives Playwright to load the USDZ in the dev page, names the moving and fixed halves folding-half / stationary-half, swaps the inner and cover screen materials for replaceable white surfaces and exports a binary GLB through GLTFExporter (textures capped at 512). Only the metal frame may be recoloured — screens, glass, lenses and hinge details are off limits — and THIRD_PARTY.md excludes the Apple assets from the repository’s MIT license.
Photo journey · One GSAP progress drives the gallery, the physical photo and the cover screen
The circular gallery is React Bits’ Circular Gallery ported from OGL to Three.js: it keeps the 100×50 subdivided mesh, velocity-based sine vertex wobble and rounded image sampling, then extends the arc into a cylindrical path with depth and facing, sharing one PerspectiveCamera with the device. GSAP Observer owns wheel, pointer and touch input plus the drag threshold, while a Timeline choreographs the journey as approach → receive-and-melt → settle; new input interrupts the old animation and dragging can sample it in reverse.
The photo queue, the physical photo mesh and the real cover-screen image are driven by the same progress with matching texture coordinates at the screen edge: the outer mesh is clipped where it enters the screen and the screen fills in the corresponding image. Cover transitions use the Melt branch of Morph Slider (intensity 0.95 / scale 4.9 / aberration 0.35) with uTime driven by journey progress rather than wall-clock time, which is what makes rewinding and freeze-frames possible.
Screen portal · Visibility is decided only by the real moving lid
The scene stays authored on the fully unfolded plane and is never rebuilt or rescaled per frame; how much you see is decided by the angle between the moving left screen and the fixed right one — opening the lid first frees the space above the right screen, and the left half is revealed as the lid passes vertical and approaches flat. Hold the lid still and the picture holds; rewind retraces the same volume. Temporary cut faces where the lid intersects the scene are triangulated from real mesh intersections with spatial rejection, cached for unchanged planes and reusable GPU buffers, filled in pale ice or neutral stone and hidden at the closed and open endpoints; a stencil approach was rejected because the delivered meshes have open boundaries. The left water reflection fades in only near flat to avoid a tilted double silhouette.
The 2026-09-16 startup pass moved that hinge geometry clipping into a module worker: each of the five scenes used to take 1–1.6 s of synchronous preparation, now the main thread only spends 8–29 ms restoring transferable buffers; freshly mounted scenes apply the current fold state before rendering, the water-reflection cameras see only the natural scene rather than the phone and gallery, and the Wallpaper Studio’s presets and AI worker load only when that view is entered.
Wallpaper Studio · In-browser depth estimation and the optics of folding
An uploaded image first gets a quick depth map, then a small model refines it (@huggingface/transformers running in depth.worker.js; the AI worker is created only when you actually press generate); foreground and background are displaced and blurred by depth difference so the picture has real space as the pointer moves. The five preset wallpapers ship 512×288 pre-generated depth maps and the video preset uses its poster frame’s. Inner and cover screen layers are composited at runtime from JSON layouts and 20 individual SVG icons into transparent GPU textures, so changing one icon never means redrawing the whole screen.
The folding itself lives in parameters: blur radius coefficients of 3.5 and 1.8 for the inner and cover screens, so the cover blurs first as the lid closes; the hinge is fully folded at 96%, leaving the last 4% for the screen to settle into focus; brightness dims along a sine curve with pose, darkest around 90°; and lateral parallax projects the screen vertices onto a “fully unfolded virtual plane” before sampling, so the geometry folds while the wallpaper slides across as if on a flat pane of glass in front of you, never skewing into a trapezoid.


