summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs34
-rw-r--r--src/sdf.rs60
2 files changed, 80 insertions, 14 deletions
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]] = &[
diff --git a/src/sdf.rs b/src/sdf.rs
index 5318990..db0a776 100644
--- a/src/sdf.rs
+++ b/src/sdf.rs
@@ -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()?
+ }
+}
+