Back to Projects

    Atomos — Hand-Controlled 3D Molecule Lab

    Atomos is a free, open-source 3D molecule lab that runs from a single HTML file and is controlled by webcam hand gestures. MediaPipe Hands tracks 21 landmarks per hand, a small classifier turns them into palm, pinch and fist gestures, and Three.js renders six textbook molecules as ball-and-stick models. It needs no install, no build step and no backend.

    2026
    Creator
    11 Technologies
    HTML5Vanilla JavaScriptThree.js 0.160MediaPipe Hands 0.4MediaPipe Camera Utils 0.3WebGLWebAssembly (MediaPipe runtime)MediaDevices getUserMediaCSS custom propertiesjsDelivr CDNGitHub Pages
    Atomos — Hand-Controlled 3D Molecule Lab

    Verify it yourself

    • Source repositoryPublic and MIT licensed. The entire application is the single index.html file at the repository root.
    • Live demoRuns on GitHub Pages. Needs a browser with WebGL, getUserMedia and WASM, plus camera permission for gesture control.

    Introduction

    Atomos started as a question about interfaces rather than chemistry: what does a molecule viewer feel like when the mouse is gone and your hands are the controller? I built it as one HTML file so that a chemistry teacher could get it onto a classroom laptop without asking anyone for permission to install software. Hold up a palm and the molecule spins with you; pinch and the nearest atom lights up with its atomic number and its role in the structure.

    The Challenge

    School computers are a hostile deployment target. They are locked down, they cannot install runtimes, they often sit behind filtered networks, and the person driving them is a teacher who has to get something on screen quickly. Most 3D chemistry tools assume a build pipeline, a package manager or a hosted account, and every one of those assumptions is a place where a lesson dies. On top of that, the interesting part of molecular geometry is spatial. A mouse-orbit control makes students think about dragging rather than about the shape of a tetrahedron. I wanted the input to be the same three-dimensional gesture a teacher already makes with their hands at the whiteboard.

    The Solution

    I wrote the entire application as a single index.html: markup, CSS and about 660 lines of JavaScript in one inline script tag. Three.js draws the ball-and-stick scene, MediaPipe Hands supplies 21 landmarks per hand from the webcam, and a classifier I wrote by hand collapses those landmarks into four discrete states. Palm deltas become rotation on the molecule group, the pixel distance between two palms becomes a scale target, and the index fingertip position becomes an atom picker. Six molecules are defined as literal arrays of atomic coordinates plus a bond list, so adding a seventh is a data edit rather than a code change. There is no bundler, no framework and no server-side component of any kind.

    Technical Deep Dive

    1

    Gesture classification runs on 2D screen-projected landmarks rather than on raw model output. Each finger is scored as extended by comparing the tip-to-wrist distance against the PIP-joint-to-wrist distance with a 1.05 margin, and the thumb is handled separately by measuring landmark 4 against landmark 2 relative to palm size. Four or more extended fingers reads as an open palm, one or fewer reads as a fist. Normalising against palm size is what makes the classifier hold up when a student leans toward or away from the camera.

    2

    Pinch detection is deliberately conservative. A pinch requires the normalised thumb-to-index distance to fall under 0.45 of palm size and at least one of the middle, ring or pinky fingers to still be extended. That second condition is the whole trick: without it, a closing fist passes through a pinch pose on the way down and fires a spurious atom selection every time a student relaxes their hand.

    3

    Mapping gestures to camera motion is the part that took the most iteration. Rotation does not track absolute palm position; it integrates the frame-to-frame palm delta at 0.005 radians per pixel on both axes, and the palm centre is the mean of landmarks 0, 5 and 17 rather than a single point, which kills a lot of the per-finger jitter. Scale is absolute rather than incremental: inter-palm pixel distance divided by 350, clamped to the range 0.4 to 2.4, then eased toward the current scale at 10 percent per frame so a dropped detection does not snap the model.

    4

    Handedness gets flipped on purpose. The webcam preview is mirrored in CSS and landmark x coordinates are inverted when projected to screen space, so MediaPipe's Left label is stored as the user's right hand. Getting this backwards produces an app that feels subtly wrong in a way most testers cannot articulate, and it is the first thing I check when someone reports that scaling behaves oddly.

    5

    Atom picking projects rather than raycasts. Every atom mesh's world position is projected through the camera to screen coordinates each frame, and the nearest one to the index fingertip within 90 pixels wins. A hit scales the sphere by 1.25 and sets an emissive tint, and rotating clears the selection so a student cannot leave a stale highlight on screen. Screen-space distance is more forgiving than a strict ray hit when the pointing device is a shaky human finger.

    6

    Rendering is built for the low end of the school-laptop range. One SphereGeometry and one bond material are shared across every atom and bond, atom size comes from the per-element radius in the element table applied as a mesh scale rather than as new geometry, device pixel ratio is capped at 2, and multiple bonds are drawn as offset cylinders rotated by a quaternion derived from the bond direction. Camera distance is recomputed from the molecule's bounding box on every load and resize so benzene and water both fill the frame properly.

    7

    Delivery is the single-file constraint made literal. The external requests are three script tags on jsDelivr for Three.js 0.160, MediaPipe Hands 0.4 and MediaPipe Camera Utils 0.3, the MediaPipe model assets its locateFile hook pulls from the same CDN at runtime, and a Google Fonts stylesheet. Startup checks that getUserMedia exists and that the THREE, Hands and Camera globals actually loaded, and it distinguishes a denied camera permission from a general initialisation failure so the error overlay tells the teacher something useful instead of showing a blank screen.

    Key Features

    Four gestures drive the scene

    One open palm rotates the molecule, two palms scale it by moving apart or together, a thumb-and-index pinch picks the nearest atom, and two closed fists ease the view back to its default orientation. The active mode is named on screen so students can see what the app thinks their hands are doing.

    Six molecules from real coordinates

    Water, carbon dioxide, methane, ammonia, ethanol and benzene are defined as explicit atomic positions with a bond list and bond orders. Benzene's ring and hydrogens are generated procedurally with alternating Kekule bond orders. Each molecule carries its geometry class, a summary and three chemistry facts.

    Atom inspection panel

    Picking an atom opens a card with the element symbol, full name, atomic number, its index within the molecule and its structural role, such as central atom with two lone pairs or aromatic sp2 carbon. Element colours follow the CPK convention students already see in their textbooks.

    Keyboard and pointer controls

    Arrow keys and the number keys move between molecules, R resets the view, I toggles the info panel, H hides the interface for projection, and F goes fullscreen, and on-screen arrows do the same navigation with a click. Rotation, scaling and atom picking stay gesture-only.

    Live instrument readouts

    The overlay shows frame rate averaged over 20 frames, the number of hands currently detected, atom and bond counts, and the geometry class of the active molecule. The hand count in particular gives a student immediate feedback when their hand has drifted out of frame.

    Local-only vision

    MediaPipe runs its hand landmark model in the browser through WebAssembly. Frames and landmarks stay on the machine, the app has no analytics and no backend, and the webcam preview sits at 35 percent opacity in the corner so students can see the tracking without it dominating the screen.

    Results & Impact

    • The app ships as a single index.html file, MIT licensed, with a working GitHub Pages deployment at revolutionarybukhari.github.io/atomos. Anyone can verify the full source in one file rather than trusting a build artefact.
    • Deployment has no moving parts. There is no package.json, no lockfile, no CI step and no server process, which means there is nothing that can drift or expire between the day a teacher bookmarks it and the day they use it.
    • The gesture layer degrades in a defined way: when no hand is detected the molecule falls back to a slow auto-rotate, when the camera is refused the app shows a specific permission error, and when the CDN scripts fail to load it says so instead of rendering nothing.
    • Adding a molecule is a data edit. A new entry needs a name, formula, geometry label, summary, facts, an atom array and a bond array, and the renderer, camera fit, navigation dots and info panel pick it up. The one code-side limit is the element table, which currently defines H, C, N, O, F, P and S.

    Lessons Learned

    "Single-file was the right call, but be honest about what it buys. It removes the build step, the package manager and the server, which is exactly what a locked-down school laptop needs. It does not make the app offline-capable, because Three.js and the MediaPipe WASM assets still come from a CDN on first load. If I took this into a school with a genuinely hostile network, vendoring those files next to the HTML would be the first change."

    "Most of the work in a gesture interface is rejecting gestures, not recognising them. The classifier is short; the conditions that stop a relaxing hand from firing a pinch, and the smoothing that stops a single dropped frame from snapping the scale, are what make it feel intentional. I would rather miss a gesture than fire the wrong one in front of a class."

    "Screen-space picking beat raycasting for this input device. A fingertip tracked from video is noisy enough that a strict ray through a sphere misses constantly, while a 90-pixel proximity test on projected atom centres feels like the app is meeting the student halfway."

    "Building the keyboard controls first would have saved time. I added them after the gestures worked, and they immediately became how I tested everything else, because checking a rendering change should not require standing in front of a webcam waving at a laptop. They are a second input path, not a camera-free mode: the app still needs camera permission to get past its startup overlay."

    Conclusion

    Atomos is a small app with one strong opinion: the delivery constraint should be chosen before the feature list. Picking a single HTML file first is what forced the gesture classifier to be hand-written rather than pulled from a library, the molecules to be plain data, and the whole thing to survive on a machine nobody is allowed to install software on. The full source is public, so the mechanism is there to read rather than to take on trust.

    Frequently asked questions

    Is Atomos open source, and what can I do with it?
    Yes. The repository is public under the MIT licence, which means you can use, modify, fork and redistribute it, including in commercial settings, as long as you keep the licence notice. The entire application is one index.html file, so forking it and editing the molecule list needs nothing more than a text editor.
    Does it work offline on a school laptop?
    Not out of the box. The HTML file is self-contained, but Three.js, MediaPipe Hands and the MediaPipe WASM assets load from the jsDelivr CDN on first run, and the fonts come from Google Fonts. To make it fully offline you would download those files next to the HTML and change the script sources to relative paths.
    How does it handle the camera and student privacy?
    MediaPipe runs its hand landmark model inside the browser using WebAssembly, so video frames are processed locally. The app has no backend, no analytics and no upload path of any kind, and the only network calls it makes are the initial library and font requests. Denying camera access shows an explanatory error rather than breaking the page.
    What if a student has no webcam or the camera is blocked?
    Gesture control needs a camera, and a refusal shows a permission error with a retry button rather than a silent failure. Where the camera is allowed but nobody is gesturing, the molecule slowly auto-rotates and the keyboard drives the rest: arrow and number keys switch molecules, R resets the view, I toggles the info panel, H hides the interface, F goes fullscreen.
    How reliable is the gesture detection in a real room?
    The classifier normalises every measurement against palm size, so it tolerates students sitting closer to or further from the camera. Rotation integrates frame-to-frame palm movement rather than absolute position, and scale is eased toward its target, so a dropped detection does not jerk the model. The on-screen hand counter tells a student immediately when they have drifted out of frame.
    Can I add my own molecules or embed this in my own site?
    Yes. Molecules are plain JavaScript objects holding a name, formula, geometry label, summary, facts, an array of atoms with element symbols and coordinates, and a bond list with bond orders. Add an entry using elements from the built-in table of H, C, N, O, F, P and S, and the renderer, camera framing, navigation and info panel pick it up. Hosting is a file copy onto any static host.
    What does it cost to run?
    Nothing beyond static hosting. There is no server, no database, no API key and no inference bill, because the hand tracking runs on the viewer's own machine. The public deployment sits on GitHub Pages. If you self-host, any static file host or even a local python http.server is enough.

    Interested in a Similar Project?

    Let's discuss how I can help bring your ideas to life.

    Get in Touch

    Let's Create a Revolution