use eframe::egui;
use siplot::{Colormap, ColormapName, PointMarker, Scatter3D, Scene3dGeometry, SceneWidget, Vec3};
const N: usize = 1000;
struct ScatterApp {
scene: SceneWidget,
}
impl ScatterApp {
fn new(cc: &eframe::CreationContext<'_>) -> Self {
let rs = cc
.wgpu_render_state
.as_ref()
.expect("eframe must use the wgpu renderer");
let mut rng = Lcg::new(0x5eed_1234);
let (mut xs, mut ys, mut zs, mut vs) = (vec![], vec![], vec![], vec![]);
for _ in 0..N {
let (x, y, z) = (rng.unit(), rng.unit(), rng.unit());
let r2 = (x - 0.5).powi(2) + (y - 0.5).powi(2) + (z - 0.5).powi(2);
xs.push(x);
ys.push(y);
zs.push(z);
vs.push((-11.0 * r2 as f64).exp());
}
let scatter = Scatter3D::new()
.with_data(&xs, &ys, &zs, &vs)
.with_colormap(Colormap::new(ColormapName::Magma, 0.0, 1.0))
.with_marker(PointMarker::Diamond)
.with_size(11.0);
let mut geometry = Scene3dGeometry::new();
scatter.append_to(&mut geometry);
let mut scene = SceneWidget::new(rs, 0);
scene.set_bounds(rs, (Vec3::ZERO, Vec3::new(1.0, 1.0, 1.0)));
scene.set_geometry(rs, geometry);
Self { scene }
}
}
impl eframe::App for ScatterApp {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show_inside(ui, |ui| {
self.scene.show(ui);
});
}
}
struct Lcg(u64);
impl Lcg {
fn new(seed: u64) -> Self {
Lcg(seed)
}
fn unit(&mut self) -> f32 {
self.0 = self
.0
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
((self.0 >> 40) as f32) / (1u32 << 24) as f32
}
}
fn main() -> eframe::Result {
eframe::run_native(
"siplot: 3D scatter",
eframe::NativeOptions {
renderer: eframe::Renderer::Wgpu,
..Default::default()
},
Box::new(|cc| Ok(Box::new(ScatterApp::new(cc)) as Box<dyn eframe::App>)),
)
}