indicatrix-cut
The desktop faceting-design editor: browse, search, and render your own
faceting-design library with indicatrix's full spectral renderer, and edit
cutting schedules with material retargeting and a solid inspection view.
Import and export your own .asc files.
Built with Slint. This crate is both a library
(indicatrix_cut) and a binary (indicatrix-cut) — the library exposes
gui::build_main_window(), a fully-wired, not-yet-shown MainWindow.
Documentation map
This file is the entry point: building, what the app does, and the code
structure. Deeper material lives alongside it in docs/:
docs/settings.md— the settings file's location, persistence guarantees, render-quality controls, and remote-worker configuration.docs/remote-rendering.md— the preview-then-handoff model: when a render moves from local CPU to a remote worker, and how denoising and the TLS connection are handled across that.docs/export.md— how.ascimport and export work.docs/gpu.md— thegpufeature and exactly when and why a frame falls back from GPU to the CPU tracer.docs/manual/README.md— the user manual, for lapidaries using the app rather than developers working on it.
Build and run
cargo build -p indicatrix-cut
cargo run -p indicatrix-cut
build.rs runs slint_build::compile("ui/app.slint") at build time, which pulls
in theme.slint, types.slint, and everything under ui/components/. No
platform-specific setup beyond what Slint itself needs (a Windows graphics
backend) was found in this crate's Cargo.toml.
Working directory matters. The local catalog database is opened as a
relative path (facet_diagrams.sqlite in the process's current working
directory, not a fixed config directory), so running the built .exe from a
different folder than expected opens (or creates) a different database.
Exports are unaffected by this — every export asks where to save via a native
dialog, and ./exports/ is only the suggested default.
Icon and console behaviour
build.rs embeds assets/icon.ico as a Windows resource, which covers both Explorer's
view of the .exe and the window's own titlebar/taskbar icon — a Win32 window with no
icon of its own falls back to the executable's first icon resource, so nothing needs to
ship alongside the binary. Regenerate the icon with:
python scripts/make-icons.py
A release build sets windows_subsystem = "windows", so launching the .exe
directly no longer opens an empty console beside the window. A debug build keeps its
console, so cargo run still shows panics during development. If a tracing subscriber
is ever added to this crate, it must write somewhere other than stdout — a release build
has no console to write to.
The gpu feature
cargo build -p indicatrix-cut --features gpu
Routes both the viewport's progressive accumulation and the high-resolution
export worker through indicatrix's verified GPU megakernel instead of the
multithreaded CPU tracer. Off by default. Measured on this project's
integrated AMD Radeon (Vulkan), at 960x540 / 64 spp / 12 bounces on Emerald:
1.44 s on GPU vs 10.66 s across 16 CPU threads, a 7.4x speedup. The
fallback to the CPU tracer is per frame (per batch, for an export), not per
session, and is a normal outcome, not an error — see
docs/gpu.md for exactly when and why it happens.
What it does
- Search and filter your library by title/designer, shape, gear, and range filters on refractive index, L/W ratio, volume, and facet count.
- View a diagram in 3D with
indicatrix's full spectral path tracer — orbit camera, adjustable lighting/exposure/material/quality, live optical-metrics readouts (brilliance/fire/scintillation/windowing/extinction) and a tilt-performance analysis graph — 19 measured tilt angles swept at four camera azimuths (0°, 45°, 90°, 135°), switchable or overlaid, with a hover readout that interpolates between the measured points. - View the cutting-schedule table (facet/angle/index/notes) and any attached original files.
- Import your own
.ascfile(s) — a single file, or a folder, optionally including its subfolders — into the local library. Imports run off the UI thread with progress, and geometry-derived metadata (proportions, and a conservatively classified shape) is measured at import rather than left blank. Export a diagram back out as.asc— either its original attached file, byte-for-byte, or reconstructed from the stored angle/index table if no original is attached (a reconstructed file is explicitly marked as such — seeindicatrix-formats's andindicatrix-vault's READMEs onmark_reconstructed). - Rename/delete library entries.
- Export a high-resolution still — 1080p, 4K, or a custom size up to 8192×8192, at up to 32768 samples per pixel, in sRGB / Display P3 / Rec.2020 (the two wide-gamut choices carry an embedded ICC profile) — with a live thumbnail of the render as it progresses.
- Every path the app asks for — import source, environment map, certificate folder, and each export destination — is chosen through a native OS file dialog; the text fields remain, so a pasted path still works.
- Offload rendering to a remote
indicatrix-workerover mutual TLS, with a preview-then-handoff model while the camera is moving (below).
Structure
src/
lib.rs slint::include_modules!(), pub mod gui, crate-private bridge/settings
main.rs entry point + the release-build windows_subsystem attribute
gui/ callback wiring, one module per area of the UI
mod.rs orchestrator: DB, RenderContext, settings, callback wiring
library/ import / rename / delete / export-.asc / shape editing
detail.rs detail loading, facet-plane reconstruction, file export
search.rs range-filter reading, diagram-list refresh
remote/ settle detection, handoff wiring, merged-frame render/denoise
render_export.rs the high-resolution export's UI side
... camera/lighting, materials, crystal optics, tilt profile
bridge/ everything off the UI thread, plus pure logic it depends on
render_thread/ the local progressive render loop and RenderContext
export_thread/ the high-resolution export worker (local + remote engines)
handoff.rs pure preview/remote handoff state machine (no sockets/threads)
remote_render.rs the mutual-TLS TcpStream driver
guide_pass.rs primary-ray-only prepass for remote-frame denoise guides
pixel_buffer.rs zero-copy RGBA8 -> SharedPixelBuffer transfer
... enrolment, ICC profiles, library mirror/source, girdle finish
settings/
model/ pure data/logic (no Slint or threading dependency)
store.rs on-disk TOML load/save, infallible on failure
persist.rs debounced background writer
assets/
icon.ico, icon.png generated by scripts/make-icons.py
ui/
app.slint, theme.slint, types.slint, components/*.slint, icons/*.svg
MainWindow (ui/app.slint) layout: a top toolbar (search, shape/gear filters,
range sliders, import, remote-worker configuration, denoise toggle), a
diagram-list panel on the left, and on the right a detail header plus three
tabs — the 3D viewport, the cutting-schedule table, and attachments.
Testing
cargo test -p indicatrix-cut
No tests/ directory — all coverage is inline #[cfg(test)]. What's covered:
the HandoffMachine state machine exhaustively (including an all-state-pairs
no-panic sweep), settings TOML round trips (including remote-worker fields and
PreviewScale::Custom), the debounced settings writer, tonemap/denoise
correctness and the "denoise is a no-op at converged sample counts" property,
quality-preset label/index round trips, and filename sanitization. Nothing
exercises the actual Slint window, a live socket to a indicatrix-worker, or the
SQLite-backed end-to-end flow — per the source's own doc comments, those are
left to manual verification.