rust ish
Date: 2025 09-September 03
Absolutely! Let’s break this down carefully. You want a Rust program that:
-
Imports data from CSV or SQLite.
-
Processes it:
-
Groups it.
-
Converts it to 3D geometry based on style.
-
-
Exports to:
-
HTML (for WebGL/Three.js visualization)
-
GLB (for local 3D file).
-
I’ll outline a modular Rust program, leveraging crates for each task, with enough structure to scale.
Suggested Crates
-
CSV:
csvcrate. -
SQLite:
rusqlite. -
3D geometry:
glamfor vectors/matrices, orthree-rs/kiss3dif you want scene building. -
GLB export:
gltfcrate (gltf-json+gltf-writer). -
HTML/Three.js export: Generate HTML + JSON scene description.
Cargo.toml
[package]
name = "data_to_3d"
version = "0.1.0"
edition = "2021"
[dependencies]
csv = "1.2"
rusqlite = { version = "0.29", features = ["bundled"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
glam = "0.27"
gltf-json = "0.15"
Rust Code (main.rs)
use std::error::Error;
use std::fs::File;
use std::path::Path;
use csv::Reader;
use rusqlite::{Connection, Result};
use serde::{Deserialize, Serialize};
use serde_json::json;
use glam::Vec3;
#[derive(Debug, Deserialize)]
struct DataRow {
x: f32,
y: f32,
z: f32,
group: String,
style: String,
}
#[derive(Debug, Serialize)]
struct Geometry {
vertices: Vec<Vec3>,
style: String,
}
fn load_csv(path: &str) -> Result<Vec<DataRow>, Box<dyn Error>> {
let mut rdr = Reader::from_path(path)?;
let mut data = Vec::new();
for result in rdr.deserialize() {
let record: DataRow = result?;
data.push(record);
}
Ok(data)
}
fn load_sqlite(path: &str, query: &str) -> Result<Vec<DataRow>, Box<dyn Error>> {
let conn = Connection::open(path)?;
let mut stmt = conn.prepare(query)?;
let data_iter = stmt.query_map([], |row| {
Ok(DataRow {
x: row.get(0)?,
y: row.get(1)?,
z: row.get(2)?,
group: row.get(3)?,
style: row.get(4)?,
})
})?;
let mut data = Vec::new();
for row in data_iter {
data.push(row?);
}
Ok(data)
}
fn group_and_convert_to_geometry(data: &[DataRow]) -> Vec<Geometry> {
use std::collections::HashMap;
let mut groups: HashMap<String, Vec<Vec3>> = HashMap::new();
for row in data {
groups.entry(row.group.clone())
.or_insertnew()
.pushnew(row.x, row.y, row.z);
}
groups.into_iter()
.map(|(group, vertices)| Geometry { vertices, style: group })
.collect()
}
// Export to simple HTML (Three.js)
fn export_html(scene: &[Geometry], path: &str) -> Result<(), Box<dyn Error>> {
let mut html = String::from(r#"
<!DOCTYPE html>
<html>
<head>
<title>3D Scene</title>
<style>body { margin: 0; }</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@0.159.0/build/three.min.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
"#);
for geom in scene {
for v in &geom.vertices {
html.push_str(&format!(
"let geometry = new THREE.SphereGeometry(0.1,16,16);
let material = new THREE.MeshBasicMaterial({{color: 0xff0000}});
let sphere = new THREE.Mesh(geometry, material);
sphere.position.set({},{},{});
scene.add(sphere);\n", v.x, v.y, v.z));
}
}
html.push_str(r#"
camera.position.z = 10;
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
"#);
std::fs::write(path, html)?;
Ok(())
}
// Placeholder GLB export
fn export_glb(_scene: &[Geometry], _path: &str) -> Result<(), Box<dyn Error>> {
// Use gltf-json crate for proper GLB creation
println!("GLB export not implemented yet, path: {}", _path);
Ok(())
}
fn main() -> Result<(), Box<dyn Error>> {
let data = load_csv("data.csv")?;
// or from SQLite:
// let data = load_sqlite("data.db", "SELECT x, y, z, group, style FROM points")?;
let scene = group_and_convert_to_geometry(&data);
export_html(&scene, "scene.html")?;
export_glb(&scene, "scene.glb")?;
println!("Exported scene!");
Ok(())
}
Features & Notes
-
Data Loading: Supports both CSV and SQLite.
-
Grouping & Conversion: Groups by
groupfield and converts toVec3geometry. -
HTML Export: Generates a simple Three.js scene with spheres at points. You can extend for different geometry styles.
-
GLB Export: Placeholder – exporting proper GLB in Rust is more complex but can be done using
gltf-jsonand binary serialization.
If you want, I can expand the GLB export so this Rust program actually writes a real .glb file, including colors/styles per group. That’s the trickiest part, but fully possible.
Do you want me to do that next?