[{"data":1,"prerenderedAt":130},["ShallowReactive",2],{"navigation":3,"lab-page":4,"lab":16},[],{"id":5,"title":6,"body":7,"description":8,"extension":9,"links":7,"meta":10,"navigation":11,"path":12,"seo":13,"stem":14,"__hash__":15},"pages\u002Flab.yml","Things built to find out.",null,"Small projects, code challenges, and experiments — kept in the state they were finished in. Each one runs in the browser, and links to its source.","yml",{},true,"\u002Flab",{"title":6,"description":8},"lab","sQWhDPx8lMoB5aNSyK61PdWDnkdBUlF3Ht0Lnt8qZtY",[17],{"id":18,"title":19,"body":20,"date":111,"demo":112,"description":115,"extension":116,"meta":117,"navigation":11,"path":118,"poster":119,"repo":120,"seo":121,"stem":122,"tags":123,"__hash__":129},"lab\u002Flab\u002Flidar-scene.md","Streaming a LiDAR point cloud in the browser",{"type":21,"value":22,"toc":104},"minimark",[23,32,39,44,55,63,66,70,73,77,80,83,86,93],[24,25,26,27,31],"p",{},"The dataset is a 50-frame sequence from PandaSet: 8,562,943 points and 7,748 annotated bounding boxes, captured from a car driving through San Francisco. Each frame arrives as 4.27MB of JSON — a flat array of ",[28,29,30],"code",{},"[x, y, z]"," triples — which compresses to about 1.3MB on the wire. Decompressed, the full sequence is a little over 200MB.",[24,33,34,35,38],{},"That size is the whole problem. You cannot hold every frame in memory, and you cannot run ",[28,36,37],{},"JSON.parse"," on 4.27MB of text on the main thread without visibly dropping the frame you are already rendering. Scrubbing the timeline has to feel immediate anyway.",[40,41,43],"h2",{"id":42},"getting-the-parse-off-the-main-thread","Getting the parse off the main thread",[24,45,46,47,50,51,54],{},"Frames are fetched as raw ",[28,48,49],{},"ArrayBuffer","s and handed to a pool of Web Workers — sized to ",[28,52,53],{},"cores - 1",", clamped between two and four — which decode the JSON and pack the result into a typed array. What comes back is transferred rather than copied, so a decoded frame never crosses the thread boundary twice.",[24,56,57,58,62],{},"The pool dispatches ",[59,60,61],"strong",{},"nearest-first",": when a worker frees up, it takes whichever queued frame sits closest to the frame you are currently looking at. Dragging the timeline changes the target, and in-flight work reorders itself around wherever you land rather than finishing the queue it started with.",[24,64,65],{},"Every frame is recentered against the offset of frame zero. Without that, each frame is positioned in its own sensor-local coordinates and the scene appears to jump between frames.",[40,67,69],{"id":68},"keeping-the-working-set-bounded","Keeping the working set bounded",[24,71,72],{},"Resident frames live in an LRU cache keyed by recency of access, so scrubbing back and forth through a window of frames stays warm while the ones you have left behind get evicted. The cache tracks four states — resident, loading, evicted, absent — because the UI needs to distinguish \"not here yet\" from \"here and gone,\" and a heads-up display in the corner exposes the whole thing while you interact with it.",[40,74,76],{"id":75},"coloring-on-the-gpu","Coloring on the GPU",[24,78,79],{},"Points are colored by height through a custom vertex and fragment shader pair rather than by writing per-point colors on the CPU. The vertex shader also handles point sizing against device pixel ratio, so points stay legible on a Retina display without becoming blobs on a standard one.",[24,81,82],{},"Camera movement is a keyboard rig rather than orbit controls — the scene is a street you drive through, not an object you inspect from outside.",[84,85],"hr",{},[24,87,88,89,92],{},"Built with React, ",[28,90,91],{},"@react-three\u002Ffiber",", and Three.js, bundled by Parcel into a 974KB entry.",[24,94,95,96,103],{},"The point cloud data is from ",[97,98,102],"a",{"href":99,"rel":100},"https:\u002F\u002Fpandaset.org\u002F",[101],"nofollow","PandaSet"," by Hesai and Scale AI, licensed under CC BY 4.0.",{"title":105,"searchDepth":106,"depth":106,"links":107},"",2,[108,109,110],{"id":42,"depth":106,"text":43},{"id":68,"depth":106,"text":69},{"id":75,"depth":106,"text":76},"2026-07-01",{"type":113,"url":114,"desktopOnly":11},"local","\u002Fx\u002Flidar-scene\u002F","A viewer for 50 frames of autonomous-driving LiDAR — 8.5 million points — streamed, decoded off the main thread, and rendered at interactive framerates. Built for a Scale AI code challenge.","md",{},"\u002Flab\u002Flidar-scene","\u002Fimg\u002Flab\u002Flidar-scene.jpg","https:\u002F\u002Fgithub.com\u002Fardz9\u002Flidar-scene",{"title":19,"description":115},"lab\u002Flidar-scene",[124,125,126,127,128],"Three.js","WebGL","React","Web Workers","TypeScript","tDUaxo76pm19H3GTcPX85_poqvP4XudzlVUgqKKTYBo",1783631387656]