diff options
-rw-r--r-- | Cargo.lock | 36 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/main.rs | 34 | ||||
-rw-r--r-- | src/sdf.rs | 60 |
4 files changed, 119 insertions, 14 deletions
@@ -26,6 +26,9 @@ dependencies = [ "gl", "nalgebra", "rand", + "serde", + "serde_cbor", + "serde_derive", ] [[package]] @@ -88,6 +91,12 @@ dependencies = [ ] [[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] name = "khronos_api" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -259,6 +268,33 @@ dependencies = [ ] [[package]] +name = "serde" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91" + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "simba" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -11,3 +11,6 @@ nalgebra = "0.31" gen_random_proc_macro = { path = "./gen_random_proc_macro" } gen_random = { path = "./gen_random" } rand = { version = "0.8", features = ["small_rng"] } +serde_cbor = "0.11.2" +serde = "1.0.150" +serde_derive = "1.0.150" diff --git a/src/main.rs b/src/main.rs index 59923b0..26abb34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -87,12 +87,7 @@ impl View { } } -fn gen_program_with_seed(window: &mut win::Window, program: &mut win::Program, seed: u64) -> Result<(), String> { - use rand::SeedableRng; - - let mut rng = rand::rngs::SmallRng::seed_from_u64(seed); - let my_sdf = sdf::R3ToR::good_random(&mut rng, 6); - let color_function = sdf::R3ToR3::good_random(&mut rng, 7); +fn gen_program_from_scene(window: &mut win::Window, program: &mut win::Program, scene: &sdf::Scene) -> Result<(), String> { let mut fshader_source = String::new(); fshader_source.push_str( @@ -129,8 +124,8 @@ float sdf_torus(vec3 p, vec2 t) { } ", ); - my_sdf.to_glsl_function("sdf", &mut fshader_source); - color_function.to_glsl_function("get_color_", &mut fshader_source); + scene.sdf.to_glsl_function("sdf", &mut fshader_source); + scene.color_function.to_glsl_function("get_color_", &mut fshader_source); fshader_source.push_str( " @@ -233,7 +228,7 @@ void main() { ); //println!("{fshader_source}"); - println!("seed: {seed}"); + println!("scene: {}", scene.to_string()); window .link_program(program, @@ -251,17 +246,38 @@ void main() { Ok(()) } +fn gen_program_with_seed(window: &mut win::Window, program: &mut win::Program, seed: u64) -> Result<(), String> { + use rand::SeedableRng; + + let mut rng = rand::rngs::SmallRng::seed_from_u64(seed); + let my_sdf = sdf::R3ToR::good_random(&mut rng, 6); + let color_function = sdf::R3ToR3::good_random(&mut rng, 7); + let scene = sdf::Scene { + sdf: my_sdf, + color_function + }; + gen_program_from_scene(window, program, &scene) +} + fn gen_program(window: &mut win::Window, program: &mut win::Program) -> Result<(), String> { let seed = rand::random::<u64>(); gen_program_with_seed(window, program, seed) } +#[allow(dead_code)] // @TODO @TEMPORARY +fn gen_program_from_string(window: &mut win::Window, program: &mut win::Program, s: &str) -> Result<(), String> { + let scene = sdf::Scene::from_string(s).ok_or_else(|| "bad scene string".to_string())?; + gen_program_from_scene(window, program, &scene) +} + + fn try_main() -> Result<(), String> { let mut window = win::Window::new("AutoSDF", 1280, 720, true) .map_err(|e| format!("Error creating window: {e}"))?; let mut program = window.new_program(); gen_program(&mut window, &mut program)?; + //gen_program_from_string(&mut window, &mut program, "a263736466a167436f6d706f736583a1695472616e736c61746583a163463332fa3ea4c00ca163463332fa3e85dc00a163463332fa3f2bbdaea167436f6d706f736583a166526f7461746583a163463332fa3f750dc2a163463332fa3f5a7f0ea163463332fa3f2df98ca1634d696e82a167436f6d706f736583a167436f6d706f736582a16353696ea163463332fa3f7cc2a0a167436f6d706f736582684964656e74697479684964656e74697479a166537068657265a163463332fa3f26f8f6684964656e74697479a167436f6d706f736583a166526f7461746583a163463332fa3f1bfed8a163463332fa3f1e1e30a163463332fa3eddc6b0a1634d697883a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3ea149ec684964656e74697479a167436f6d706f736583684964656e74697479a166537068657265a163463332fa3f6b0018684964656e74697479a163463332fa3e60a8d8684964656e74697479684964656e74697479684964656e746974796e636f6c6f725f66756e6374696f6ea165537153696ea163463332fa3ebaa7ec")?; let mut buffer = window.create_buffer(); let data: &[[f32; 2]] = &[ @@ -1,3 +1,5 @@ +extern crate serde_cbor; +extern crate serde; extern crate gen_random_proc_macro; extern crate rand; @@ -5,6 +7,7 @@ use gen_random::GenRandom; use gen_random_proc_macro::GenRandom; use std::fmt::{self, Display, Formatter, Write}; use rand::Rng; +use serde_derive::{Serialize, Deserialize}; // we're only writing numbers and strings so write! should never fail. macro_rules! write_str { @@ -12,7 +15,7 @@ macro_rules! write_str { } /// these are constant across 3D space, not across time/user input/etc. -#[derive(Debug, GenRandom)] +#[derive(Debug, GenRandom, Serialize, Deserialize)] pub enum Constant { #[prob(0.5)] F32(f32), @@ -63,7 +66,7 @@ impl Display for Constant { } } -#[derive(GenRandom, Debug)] +#[derive(GenRandom, Debug, Serialize, Deserialize)] pub struct Constant3(Constant, Constant, Constant); impl std::ops::Add<f32> for Constant3 { @@ -93,7 +96,7 @@ impl Display for Constant3 { } } -#[derive(GenRandom, Debug)] +#[derive(GenRandom, Debug, Serialize, Deserialize)] pub enum R3ToR3 { #[prob(0)] Identity, @@ -122,7 +125,7 @@ pub enum R3ToR3 { // note : i dont think R → R transformations really accomplish that much // that can't be done with R³ → R³. -#[derive(GenRandom, Debug)] +#[derive(GenRandom, Debug, Serialize, Deserialize)] pub enum RToR { #[prob(1)] Identity, @@ -132,7 +135,7 @@ pub enum RToR { Subtract(Constant), } -#[derive(GenRandom, Debug)] +#[derive(GenRandom, Debug, Serialize, Deserialize)] pub enum R3ToR { #[prob(1)] Sphere(Constant), @@ -475,6 +478,31 @@ impl Function for R3ToR { } } +/// encode `data` in hexadecimal +fn encode_hex(data: &[u8]) -> String { + let mut s = String::with_capacity(data.len() * 2); + for byte in data { + write_str!(s, "{byte:02x}"); + } + s +} + +/// decode `data` from hexadecimal. +/// returns None if this isn't a valid hexadecimal string. +fn decode_hex(data: &str) -> Option<Vec<u8>> { + let data = data.trim(); + if data.len() % 2 != 0 { + return None + } + + let mut bytes = Vec::with_capacity(data.len() / 2); + for i in 0..data.len() / 2 { + let s = data.get(2*i..2*i+2)?; + let byte = u8::from_str_radix(s, 16).ok()?; + bytes.push(byte); + } + Some(bytes) +} impl R3ToR { pub fn good_random(rng: &mut impl Rng, max_depth: isize) -> Self { @@ -504,4 +532,26 @@ impl R3ToR3 { } } +#[derive(Serialize, Deserialize)] +pub struct Scene { + pub sdf: R3ToR, + pub color_function: R3ToR3 +} + +impl Scene { + pub fn to_string(&self) -> String { + let mut data: Vec<u8> = vec![]; + // write errors should never happen + // that said, we don't want to panic if for whatever reason this fails. + let _ = serde_cbor::to_writer(&mut data, self); + encode_hex(&data) + } + + /// returns None if `s` is not a valid SDF string + pub fn from_string(s: &str) -> Option<Self> { + let bytes = decode_hex(s)?; + serde_cbor::from_reader(&bytes[..]).ok()? + } +} + |