diff options
-rw-r--r-- | CHANGELOG.md | 8 | ||||
-rw-r--r-- | Cargo.toml | 5 | ||||
-rw-r--r-- | source/benoit/benoit.rs | 2 | ||||
-rw-r--r-- | source/benoit/benoit/application/colour.rs | 44 | ||||
-rw-r--r-- | source/benoit/benoit/application/draw.rs | 15 | ||||
-rw-r--r-- | source/benoit/benoit/application/handle_keys.rs | 4 | ||||
-rw-r--r-- | source/benoit/benoit/application/render_row_julia.rs | 13 | ||||
-rw-r--r-- | source/benoit/benoit/application/render_row_normal.rs | 21 | ||||
-rw-r--r-- | source/benoit/benoit/application/run.rs | 6 | ||||
-rw-r--r-- | source/benoit/benoit/iteration/iterate_mandelbrot.rs | 2 | ||||
-rw-r--r-- | source/benoit/benoit/video/initialise.rs | 9 |
11 files changed, 100 insertions, 29 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a8383..74c4f6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# 2↋ + +* Optimise and refactor code +* Update colouring +* Log version and copyright +* Fix complex-to-cartesian conversions (and controls) +* Update translation feedback + # 2↊ * Fix Julia toggle messages @@ -1,6 +1,6 @@ [package] name = "benoit" -version = "0.34.0" +version = "0.35.0" authors = ["Gabriel Bjørnager Jensen"] edition = "2021" description = "Mandelbrot renderer." @@ -12,7 +12,8 @@ name = "benoit" path = "source/benoit/main.rs" [profile.release] -lto = true +codegen-units = 1 +lto = "fat" [dependencies] rayon = "1.7.0" diff --git a/source/benoit/benoit.rs b/source/benoit/benoit.rs index b301f36..2812e52 100644 --- a/source/benoit/benoit.rs +++ b/source/benoit/benoit.rs @@ -28,4 +28,6 @@ pub mod iteration; pub mod render_data; pub mod video; +pub const VERSION: u32 = 0x23; + pub const PRECISION: u32 = 0x80; diff --git a/source/benoit/benoit/application/colour.rs b/source/benoit/benoit/application/colour.rs index c243f71..a4587c6 100644 --- a/source/benoit/benoit/application/colour.rs +++ b/source/benoit/benoit/application/colour.rs @@ -23,6 +23,33 @@ use crate::benoit::application::Application; +fn hsv_to_rgb(hue: f32, saturation: f32, value: f32) -> (f32, f32, f32) { + return if saturation <= 0.0 { + let value = value.min(1.0); + + (value, value, value) + } else { + let h = hue % 1.0 * 6.0; + let s = saturation.min(1.0); + let v = value.min(1.0); + + let f = h % 1.0; + let p = v * (1.0 - s); + let q = v * (1.0 - s * f); + let t = v * (1.0 - s * (1.0 - f)); + + match h.trunc() as u8 { + 0x0 => (v, t, p), + 0x1 => (q, v, p), + 0x2 => (p, v, t), + 0x3 => (p, q, v), + 0x4 => (t, p, v), + 0x5 => (v, p, q), + value => unreachable!(), + } + }; +} + impl Application { pub fn colour(&self, buffer: &mut [u8], iter_count_buffer: &[u32], square_dist_buffer: &[f32]) { let canvas_size = self.canvas_width * self.canvas_width; @@ -30,20 +57,13 @@ impl Application { for pixel in 0x0..canvas_size { let iter_count = iter_count_buffer[pixel as usize]; - let (red, green, blue) = if iter_count != self.max_iter_count { - let distance = square_dist_buffer[pixel as usize].sqrt(); - - let factor_range = 16.0_f32.min(self.max_iter_count as f32); + let distance = square_dist_buffer[pixel as usize].sqrt(); - let mut factor = (iter_count as f32 + 1.0 - distance.log2().log2()) / factor_range % 1.0; + let factor_range = 16.0_f32.min(self.max_iter_count as f32); + let factor = (iter_count as f32 + 1.0 - distance.log2().log2()) / factor_range % 1.0; - factor = (if factor >= 1.0 / 2.0 { - 1.0 - factor - } else { - factor - }) * 2.0; - - (factor * factor, factor * factor, factor) + let (red, green, blue) = if iter_count != self.max_iter_count { + hsv_to_rgb(factor, 7.0 / 8.0, 7.0 / 8.0) } else { (0.0, 0.0, 0.0) }; diff --git a/source/benoit/benoit/application/draw.rs b/source/benoit/benoit/application/draw.rs index 7c62c98..31ba470 100644 --- a/source/benoit/benoit/application/draw.rs +++ b/source/benoit/benoit/application/draw.rs @@ -59,8 +59,6 @@ impl Application { } if !self.julia { - let viewport_colour = Color::RGB(0xFF, 0x0, 0x0); - let canvas_width = { let mut canvas_width = Float::with_val(PRECISION, self.canvas_width); canvas_width *= self.scale; @@ -74,11 +72,15 @@ impl Application { let mut width = Float::with_val(PRECISION, 1.0 / &zoom_ratio); + // Remember that cartesian coordinates have an + // inverted vertical axis compared to those of + // SDL's coordinate system. + let mut offset_x = self.centre_real.clone(); - let mut offset_y = self.centre_imag.clone(); + let mut offset_y = Float::with_val(PRECISION, -&self.centre_imag); offset_x -= &previous_position.centre_real; - offset_y -= &previous_position.centre_imag; + offset_y += &previous_position.centre_imag; offset_x /= 4.0; offset_y /= 4.0; @@ -107,7 +109,10 @@ impl Application { ) }; - self.video.as_mut().unwrap().canvas.set_draw_color(viewport_colour); + self.video.as_mut().unwrap().canvas.set_draw_color(Color::RGBA(0x0, 0x0, 0x0, 0x3F)); + self.video.as_mut().unwrap().canvas.fill_rects(&[viewport]).unwrap(); + + self.video.as_mut().unwrap().canvas.set_draw_color(Color::RGB(0xFF, 0xFF, 0xFF)); self.video.as_mut().unwrap().canvas.draw_rects(&[viewport]).unwrap(); } diff --git a/source/benoit/benoit/application/handle_keys.rs b/source/benoit/benoit/application/handle_keys.rs index 0a1b281..1991c36 100644 --- a/source/benoit/benoit/application/handle_keys.rs +++ b/source/benoit/benoit/application/handle_keys.rs @@ -92,8 +92,8 @@ impl Application { }; match scan_code { - Scancode::S => self.centre_imag += &translate_ammount, - Scancode::W => self.centre_imag -= &translate_ammount, + Scancode::S => self.centre_imag -= &translate_ammount, + Scancode::W => self.centre_imag += &translate_ammount, _ => {}, }; diff --git a/source/benoit/benoit/application/render_row_julia.rs b/source/benoit/benoit/application/render_row_julia.rs index 7bfa6be..3f4bb0c 100644 --- a/source/benoit/benoit/application/render_row_julia.rs +++ b/source/benoit/benoit/application/render_row_julia.rs @@ -28,7 +28,8 @@ use crate::benoit::render_data::RenderData; extern crate rug; -use rug::Float; +use rug::{Assign, Float}; +use rug::float::Special; use std::sync::Arc; impl Application { @@ -71,12 +72,22 @@ impl Application { zb }; + let mut za_prev = Float::with_val(PRECISION, Special::Nan); + let mut zb_prev = Float::with_val(PRECISION, Special::Nan); + let mut iter_count: u32 = 0x0; let mut square_dist; while { square_dist = Float::with_val(PRECISION, &za * &za + &zb * &zb).to_f32(); + + let periodic = za == za_prev && zb == zb_prev; + + if periodic { iter_count = data.max_iter_count } square_dist <= 256.0 && iter_count < data.max_iter_count } { + za_prev.assign(&za); + zb_prev.assign(&zb); + iterator(&mut za, &mut zb, ca, cb); iter_count += 0x1; diff --git a/source/benoit/benoit/application/render_row_normal.rs b/source/benoit/benoit/application/render_row_normal.rs index b3d3835..157c767 100644 --- a/source/benoit/benoit/application/render_row_normal.rs +++ b/source/benoit/benoit/application/render_row_normal.rs @@ -28,7 +28,8 @@ use crate::benoit::render_data::RenderData; extern crate rug; -use rug::Float; +use rug::{Assign, Float}; +use rug::float::Special; use std::sync::Arc; impl Application { @@ -60,13 +61,16 @@ impl Application { cb *= 4.0; cb /= &canvas_width; cb /= &data.zoom; - cb += &data.centre_imag; + cb -= &data.centre_imag; cb }; - let mut za = Float::with_val(PRECISION, &ca); - let mut zb = Float::with_val(PRECISION, &cb); + let mut za = ca.clone(); + let mut zb = cb.clone(); + + let mut za_prev = Float::with_val(PRECISION, Special::Nan); + let mut zb_prev = Float::with_val(PRECISION, Special::Nan); let mut iter_count: u32 = 0x0; let mut square_dist; @@ -74,8 +78,17 @@ impl Application { square_dist = Float::with_val(PRECISION, &za * &za + &zb * &zb).to_f32(); // Having a larger escape radius gives better // results with regard to smoothing. + + // Check if the value is periodic, i.e. its + // sequence repeats. + let periodic = za == za_prev && zb == zb_prev; + + if periodic { iter_count = data.max_iter_count } square_dist <= 256.0 && iter_count < data.max_iter_count } { + za_prev.assign(&za); + zb_prev.assign(&zb); + iterator(&mut za, &mut zb, &ca, &cb); iter_count += 0x1; diff --git a/source/benoit/benoit/application/run.rs b/source/benoit/benoit/application/run.rs index e8ee4e3..b9aa50b 100644 --- a/source/benoit/benoit/application/run.rs +++ b/source/benoit/benoit/application/run.rs @@ -21,12 +21,18 @@ If not, see <https://www.gnu.org/licenses/>. */ +use crate::benoit::VERSION; use crate::benoit::application::Application; extern crate sdl2; impl Application { pub fn run(&mut self) -> i32 { + println!(); + println!("Benoit {VERSION:X}"); + println!("Copyright 2021, 2023 Gabriel Bjørnager Jensen."); + println!(); + eprintln!("rendering the {}", self.fractal.get_name()); return match self.interactive { diff --git a/source/benoit/benoit/iteration/iterate_mandelbrot.rs b/source/benoit/benoit/iteration/iterate_mandelbrot.rs index 34a3c79..6be612c 100644 --- a/source/benoit/benoit/iteration/iterate_mandelbrot.rs +++ b/source/benoit/benoit/iteration/iterate_mandelbrot.rs @@ -41,7 +41,7 @@ pub fn iterate_mandelbrot(za: &mut Float, zb: &mut Float, ca: &Float, cb: &Float // We can calculate the square of a complex number // as: // - // (a+ib)^2 = (a+ib)(a+ib) = a^2+iab+iab-b^2 = a^2-b^2+2iab + // (a+bi)^2 = (a+bi)(a+bi) = a^2+abi+abi-b^2 = a^2-b^2+2abi za.square_mut(); *za -= &*zb * &*zb; diff --git a/source/benoit/benoit/video/initialise.rs b/source/benoit/benoit/video/initialise.rs index 15449fd..40bc68d 100644 --- a/source/benoit/benoit/video/initialise.rs +++ b/source/benoit/benoit/video/initialise.rs @@ -25,14 +25,19 @@ use crate::benoit::video::Video; extern crate sdl2; +use crate::benoit::VERSION; +use sdl2::render::BlendMode; + impl Video { pub fn initialise(canvas_width: u32, scale: u32) -> Video { let sdl = sdl2::init().expect("unable to initialise sdl2"); let sdl_video = sdl.video().expect("unable to initialise video"); - let window = sdl_video.window("Benoit", canvas_width * scale, canvas_width * scale).position_centered().build().expect("unable to open window"); + let window = sdl_video.window(format!("Benoit {VERSION:X}").as_str(), canvas_width * scale, canvas_width * scale).position_centered().build().expect("unable to open window"); + + let mut canvas = window.into_canvas().build().expect("unable to create canvas"); - let canvas = window.into_canvas().build().expect("unable to create canvas"); + canvas.set_blend_mode(BlendMode::Blend); return Video { sdl: sdl, |