# Project 1: crystal visualizer in WASM
[back to index](https://hackmd.io/hz9-b8TdTNSY4sLyKBuVCQ)
- project repo: https://github.com/rs4rse/vizcrystal
note:
The content below was generated from chatgpt-5 by just providing the goal (crystal visualizer) and tech-stacks (bevy, cif, wasm), we do vibe coding from scratch.
The proposal may need to be adapted along the vibe coding. (like `cifparser` which not existed but David has some prototype crate where we can use the modules here. Otherwise see project3 and go with xyz files.)
## Core Goal
Build a web-based crystal structure visualizer in **Rust** using **Bevy** compiled to **WebAssembly (WASM)**.
The app should load a valid **CIF (Crystallographic Information File)** and render the 3D crystal structure, supporting mouse-based interaction (zoom, rotate, pan).
Publish to npm.
## tech stacks
- wasm
- rust
- use typescript where if possible since in rust we deal with types anyway.
- wasm-bindgen https://wasm-bindgen.github.io/
- wasmbuild deno glue code https://github.com/denoland/wasmbuild
---
## **Phase 1: Setup**
* Set up a **Bevy project** targeting WASM.
* Use `wasm-bindgen` or `wasm-pack` to compile.
* Serve via `trunk` or `wasm-server-runner`.
* Confirm that a simple rotating cube renders correctly in browser.
---
## **Phase 2: CIF Parsing**
* Add a Rust crate or implement a small parser for CIF files.
* Option A: Use [cifparser](https://crates.io/crates/cifparser).
* Option B: Write a minimal parser for atomic positions, cell dimensions, and symmetry.
* Extract:
* **Lattice vectors**
* **Atom positions** and **species**
* Store data in a struct, e.g.:
```rust
struct Crystal {
lattice: [[f32; 3]; 3],
atoms: Vec<Atom>,
}
struct Atom {
element: String,
position: [f32; 3],
}
```
---
## **Phase 3: Visualization in Bevy**
* Render atoms as spheres (or colored meshes).
* Render bonds as cylinders (optional at first).
* Color atoms by element type (basic mapping: H=white, C=black, O=red, etc.).
* Add unit cell edges (wireframe cube).
---
## **Phase 4: Camera & Interaction**
* Add **mouse controls**:
* **Rotate**: Click & drag.
* **Zoom**: Scroll wheel.
* **Pan**: Right-click drag or middle button.
* Use `bevy_mod_picking` or implement a custom orbital camera system.
---
## **Phase 5: Web Integration**
* Create an **HTML file** with a file upload button (`<input type="file">`).
* Use **JavaScript + wasm-bindgen** to pass uploaded CIF file content to Rust.
* When a file is loaded:
* Parse CIF → Render in scene.
* Ensure browser app works offline (bundle with Trunk).
---
## **Phase 6: Extensions (Optional / Bonus)**
* **Multiple CIFs**: Dropdown to switch between different crystals.
* **Supercell builder**: Duplicate unit cell `n x n x n`.
* **Labels**: Show element symbols next to atoms.
* **Bond detection**: Compute bonds dynamically using distance cutoff.
---
## **Deliverables**
1. WASM + Bevy app running in browser.
2. Working CIF file parser.
3. Interactive crystal visualization (zoom/rotate).
4. Extended functionality (optional):
* Bonds, labels, supercell.
---
## **Tech Hints**
* Bevy WASM:
```bash
cargo install trunk
trunk serve --open
```
* For parsing files from HTML:
* Use `web-sys` or `gloo-file` to read uploaded files.
* For interactivity:
* Bevy’s `Transform` + mouse input events.
* For bonds:
* Distance cutoff \~1.2 × (r1 + r2) where r = covalent radii.