diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 132 |
1 files changed, 76 insertions, 56 deletions
diff --git a/src/main.rs b/src/main.rs index 078b8bc..5be2399 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ /* @TODO: -- auto-select level set by sampling a bunch of points - bring time back, w pause/rewind/adjust time speed (start out paused?) - fullscreen key - options for: @@ -12,7 +11,7 @@ ---release--- - switch framebuffer texture to grayscale - show that θ = σ(z) / sqrt(x² + y²) - (x,y,z) → (x cosθ + y sinθ, y cosθ - x sinθ, z) + (x,y,z) → (x cosθ + y sinθ, y cosθ - x sinθ, z) is lipschitz continuous, & add it - feedback for copy/paste (flash screen or something) - Params instead of depth for GenRandom @@ -40,6 +39,8 @@ the era of serialization a263736466a169536d6f6f74684d696e82a169536d6f6f74684d696e82a1634d696e82a166537068657265a163463332fa3ee5212ca167436f6d706f736583a167436f6d706f736582a167436f6d706f736582684964656e74697479684964656e74697479675369676d6f6964a166537068657265a163463332fa3f7bf840684964656e74697479a1634d697883a165546f727573a266726164697573a163463332fa3f1b29f269746869636b6e657373a163463332fa3e08d8c8a167436f6d706f736583a16f496e66696e6974654d6972726f7273a163463332fa3e59bc38a16443756265a163463332fa3f155e80684964656e74697479a163463332fa3f42e49aa168426f784672616d65a26473697a65a163463332fa4034884d69746869636b6e657373a163463332fa3d0bd15a6e636f6c6f725f66756e6374696f6ea167436f6d706f736582a16641726374616ea163463332fa3eea41e4a16f496e66696e6974654d6972726f7273a163463332fa3f5ddffe a263736466a167436f6d706f736583a166526f7461746583a163463332fa3f76cab2a163463332fa3d81cad0a163463332fa3f76ebd4a1634d696e82a167436f6d706f736583675369676d6f6964a1634d696e82a1634d697883a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3e5a3e68684964656e74697479a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3f46ade4684964656e74697479a163463332fa3f551da4a1634d696e82a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3f306be8684964656e74697479a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3ca99ac0684964656e74697479684964656e74697479a167436f6d706f736583a16f496e66696e6974654d6972726f7273a163463332fa3e9febeca167436f6d706f736583a16f496e66696e6974654d6972726f7273a163463332fa3ee05424a167436f6d706f736583675369676d6f6964a1634d696e82a166537068657265a163463332fa3e16dcf0a166537068657265a163463332fa3f48f0dc684964656e74697479684964656e74697479684964656e74697479684964656e746974796e636f6c6f725f66756e6374696f6ea167436f6d706f736582a16353696ea163463332fa3f1c2a8e675369676d6f6964 a263736466a167436f6d706f736583a165537153696ea163463332fa3e784c98a1634d697883a166537068657265a163463332fa3ea1ce4ca1634d696e82a166537068657265a163463332fa3f55f124a167436f6d706f736583675369676d6f6964a166537068657265a163463332fa3ef84fb0684964656e74697479a163463332fa3d2f72c0684964656e746974796e636f6c6f725f66756e6374696f6ea16f496e66696e6974654d6972726f7273a163463332fa3e9d85d0 +a263736466a1634d696e82a1634d696e82a166537068657265a163463332fa3f2365aca1634d697883a167436f6d706f736583a16641726374616ea163463332fa3eb04a5ca167436f6d706f736583675369676d6f6964a169536d6f6f74684d696e82a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3eeb25b8684964656e74697479a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3f10d6a2684964656e74697479684964656e74697479684964656e74697479a165546f727573a266726164697573a163463332fa3d9099f069746869636b6e657373a163463332fa3e00b102a163463332fa3f06b5a2a1634d696e82a165546f727573a266726164697573a163463332fa40121b0169746869636b6e657373a163463332fa3e32f4faa1634d697883a16443756265a163463332fa3f7f9dc8a1634d697883a165546f727573a266726164697573a163463332fa3f9286e369746869636b6e657373a163463332fa3d8a3f27a167436f6d706f736583a167436f6d706f736582a167436f6d706f736582684964656e74697479684964656e74697479a16f496e66696e6974654d6972726f7273a163463332fa3ea62688a168426f784672616d65a26473697a65a163463332fa3fc0fb4969746869636b6e657373a163463332fa3e472462684964656e74697479a163463332fa3f69a73ea163463332fa3f5b9c9e6e636f6c6f725f66756e6374696f6ea16f496e66696e6974654d6972726f7273a163463332fa3ef4ea8c +a263736466a169536d6f6f74684d696e82a1634d696e82a167436f6d706f736583a167436f6d706f736582a16641726374616ea163463332fa3e6d7230a1695472616e736c61746583a163463332fa3e7262f8a163463332fa3eece0eca163463332fa3f49c42ca168426f784672616d65a26473697a65a163463332fa3ff3ee1169746869636b6e657373a163463332fa3df6dfed684964656e74697479a167436f6d706f736583a16f496e66696e6974654d6972726f7273a163463332fa3f2a2de8a165546f727573a266726164697573a163463332fa3fc93f1e69746869636b6e657373a163463332fa3e0fa700684964656e74697479a169536d6f6f74684d696e82a169536d6f6f74684d696e82a1634d696e82a169536d6f6f74684d696e82a167436f6d706f736583675369676d6f6964a1634d696e82a166537068657265a163463332fa3e0586b0a166537068657265a163463332fa3f4d6214684964656e74697479a167436f6d706f736583a167436f6d706f736582684964656e74697479684964656e74697479a1634d697883a166537068657265a163463332fa3f5c46e6a166537068657265a163463332fa3f3f4896a163463332fa3f10ba30684964656e74697479a166537068657265a163463332fa3ef3b604a167436f6d706f736583a165537153696ea163463332fa3ef1bfb8a1634d697883a1634d697883a168426f784672616d65a26473697a65a163463332fa3ee4801069746869636b6e657373a163463332fa3dc84d37a168426f784672616d65a26473697a65a163463332fa4019d5d269746869636b6e657373a163463332fa3d5d0307a163463332fa3eb7554ca167436f6d706f736583a165537153696ea163463332fa3f31c33ca167436f6d706f736583684964656e74697479a166537068657265a163463332fa3e7db3c0684964656e74697479684964656e74697479a163463332fa3f3176c0684964656e74697479a165546f727573a266726164697573a163463332fa3f253f0c69746869636b6e657373a163463332fa3c96c48d6e636f6c6f725f66756e6374696f6ea16f496e66696e6974654d6972726f7273a163463332fa3ea219f4 */ extern crate nalgebra; @@ -48,15 +49,16 @@ pub mod sdf; mod sdl; pub mod win; -use win::ColorF32; use nalgebra::{Matrix3, Matrix4, Rotation3, Vector3}; use std::time::Instant; +use win::ColorF32; type Vec3 = Vector3<f32>; type Mat3 = Matrix3<f32>; type Mat4 = Matrix4<f32>; type Rot3 = Rotation3<f32>; +#[derive(Clone)] struct View { pos: Vec3, rotation: Mat3, @@ -102,7 +104,7 @@ impl View { struct Programs { main: win::Program, - test: win::Program + test: win::Program, } impl Programs { @@ -112,27 +114,29 @@ impl Programs { test: window.new_program(), } } - + fn load_scene(&mut self, window: &mut win::Window, scene: &sdf::Scene) -> Result<(), String> { let source_main = include_str!("fshader_main.glsl"); let source_test = include_str!("fshader_test.glsl"); let source_common = include_str!("fshader_common.glsl"); - + let mut sdf = String::new(); let mut get_color = String::new(); scene.sdf.to_glsl_function("sdf", &mut sdf); scene .color_function .to_glsl_function("get_color_", &mut get_color); - let source_main = source_main.replace("%SDF%", &sdf) + let source_main = source_main + .replace("%SDF%", &sdf) .replace("%COLOR%", &get_color) .replace("%COMMON%", source_common); - let source_test = source_test.replace("%SDF%", &sdf) + let source_test = source_test + .replace("%SDF%", &sdf) .replace("%COMMON%", source_common); - + //println!("{fshader_source}"); println!("scene: {}", scene.export_string()); - + window .link_program( &mut self.main, @@ -164,7 +168,6 @@ impl Programs { } } - fn get_rng() -> impl rand::Rng { use rand::SeedableRng; rand::rngs::SmallRng::seed_from_u64(rand::random::<u64>()) @@ -177,6 +180,7 @@ const TEST_WIDTH: u16 = 100; struct State { window: win::Window, view: View, + initial_view: View, show_debug_info: bool, total_time: f64, frame_time: Instant, @@ -199,22 +203,26 @@ impl State { color_max_depth: 6, }; let scene = sdf::Scene::good_random(&mut get_rng(), &config); - programs.load_scene(&mut window, &scene).unwrap_or_else(|e| - eprintln!("Error: {e}") - ); + programs + .load_scene(&mut window, &scene) + .unwrap_or_else(|e| eprintln!("Error: {e}")); //gen_program_from_string(&mut window, &mut program, "a263736466a167436f6d706f736583a1695472616e736c61746583a163463332fa3ea4c00ca163463332fa3e85dc00a163463332fa3f2bbdaea167436f6d706f736583a166526f7461746583a163463332fa3f750dc2a163463332fa3f5a7f0ea163463332fa3f2df98ca1634d696e82a167436f6d706f736583a167436f6d706f736582a16353696ea163463332fa3f7cc2a0a167436f6d706f736582684964656e74697479684964656e74697479a166537068657265a163463332fa3f26f8f6684964656e74697479a167436f6d706f736583a166526f7461746583a163463332fa3f1bfed8a163463332fa3f1e1e30a163463332fa3eddc6b0a1634d697883a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3ea149ec684964656e74697479a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3f6b0018684964656e74697479a163463332fa3e60a8d8684964656e74697479684964656e74697479684964656e746974796e636f6c6f725f66756e6374696f6ea165537153696ea163463332fa3ebaa7ec")?; - + let mut framebuffer_texture = window.create_texture(&Default::default()); // we don't really care if there's an error. not much bad will happen. - let _ = window.set_texture_no_data::<win::ColorF32>(&mut framebuffer_texture, TEST_WIDTH.into(), TEST_HEIGHT.into()); - + let _ = window.set_texture_no_data::<win::ColorF32>( + &mut framebuffer_texture, + TEST_WIDTH.into(), + TEST_HEIGHT.into(), + ); + let mut framebuffer = window.create_framebuffer(); window.set_framebuffer_texture( &mut framebuffer, win::FramebufferAttachment::Color0, &framebuffer_texture, ); - + let mut main_buffer = window.create_buffer(); let mut test_buffer = window.create_buffer(); let data: &[[f32; 2]] = &[ @@ -229,14 +237,14 @@ impl State { window.set_buffer_data(&mut test_buffer, data); let main_array = window.create_vertex_array(main_buffer, &programs.main); let test_array = window.create_vertex_array(test_buffer, &programs.test); - let view = View::default(); - - window.set_mouse_relative(true); + window.set_mouse_relative(true); + let mut me = Self { window, programs, - view, + view: View::default(), + initial_view: View::default(), config, frame_time: Instant::now(), show_debug_info: false, @@ -250,7 +258,7 @@ impl State { me.load_scene(scene); Ok(me) } - + fn load_scene(&mut self, scene: sdf::Scene) { match self.programs.load_scene(&mut self.window, &scene) { Ok(()) => { @@ -258,40 +266,50 @@ impl State { // *technically speaking* the location of v_pos could change between reloads self.window.array_attrib2f(&mut self.main_array, "v_pos", 0); self.window.array_attrib2f(&mut self.test_array, "v_pos", 0); - + + // percentage of space occupied by object + let frac = 0.25; // determine default level set // specifically we want to select y such that - // for ~1/4 of p values, sdf(p) < y + // for ~frac of p values, sdf(p) < y self.window.bind_framebuffer(Some(&self.framebuffer)); - self.window.viewport(0, 0, TEST_WIDTH.into(), TEST_HEIGHT.into()); - + self.window + .viewport(0, 0, TEST_WIDTH.into(), TEST_HEIGHT.into()); + + self.window.use_program(&self.programs.test); self.window.draw_array(&self.test_array); - + self.window.viewport_full_screen(); self.window.bind_framebuffer(None); - - let mut sdf_values: Vec<f32> = self.window.get_texture_data_vec::<ColorF32>( - &self.framebuffer_texture - ).iter() + + let mut sdf_values: Vec<f32> = self + .window + .get_texture_data_vec::<ColorF32>(&self.framebuffer_texture) + .iter() .map(|c| c.r) .collect(); - let i = sdf_values.len() / 4; - let level_set = *sdf_values.select_nth_unstable_by(i, - |a, b| a.total_cmp(b)).1; - self.view.level_set = level_set; + let i = (sdf_values.len() as f64 * frac) as usize; + let level_set = *sdf_values + .select_nth_unstable_by(i, |a, b| a.total_cmp(b)) + .1; + drop(sdf_values); + let mut initial_view = View::default(); + initial_view.level_set = level_set; + self.initial_view = initial_view.clone(); + self.view = initial_view; } Err(e) => { eprintln!("Error: {e}") } }; } - + // returns false if we should quit fn frame(&mut self) -> bool { let frame_dt = self.frame_time.elapsed().as_secs_f32(); self.frame_time = Instant::now(); self.total_time += f64::from(frame_dt); - + while let Some(event) = self.window.next_event() { use win::Event::*; use win::Key::*; @@ -302,40 +320,43 @@ impl State { let new_scene = sdf::Scene::good_random(&mut get_rng(), &self.config); self.load_scene(new_scene); } - KeyDown { key: C, modifier, .. } if modifier.ctrl() => { + KeyDown { + key: C, modifier, .. + } if modifier.ctrl() => { // copy scene match self.window.set_clipboard_text(&self.scene.export_string()) { - Ok(()) => { - } + Ok(()) => {} Err(e) => { eprintln!("couldn't copy text to clipboard: {e}") } } } - KeyDown { key: V, modifier, .. } if modifier.ctrl() => { + KeyDown { + key: V, modifier, .. + } if modifier.ctrl() => { // paste scene match self.window.get_clipboard_text() { - Ok(s) => { - match sdf::Scene::import_string(&s) { - Some(new_scene) => { - self.load_scene(new_scene); - } - None => { - eprintln!("bad string") - } + Ok(s) => match sdf::Scene::import_string(&s) { + Some(new_scene) => { + self.load_scene(new_scene); } - } + None => { + eprintln!("bad string") + } + }, Err(e) => { // very unlikely to happen eprintln!("couldn't get clipboard text: {e}") } } } - KeyDown { key: N0, .. } => self.view.level_set = 0.0, + KeyDown { key: N0, .. } => self.view = self.initial_view.clone(), MouseMotion { xrel, yrel, .. } => { let mouse_sensitivity = 0.05; - self.view.yaw_by(-xrel as f32 * mouse_sensitivity * frame_dt); - self.view.pitch_by(-yrel as f32 * mouse_sensitivity * frame_dt); + self.view + .yaw_by(-xrel as f32 * mouse_sensitivity * frame_dt); + self.view + .pitch_by(-yrel as f32 * mouse_sensitivity * frame_dt); } _ => {} } @@ -409,12 +430,11 @@ impl State { if self.show_debug_info { println!("frame time = {:?}ms", frame_dt * 1000.0); } - + true } } - fn try_main() -> Result<(), String> { let mut state = State::new()?; while state.frame() {} |