diff options
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | source/benoit/benoit/application/colour.rs | 13 | ||||
-rw-r--r-- | source/benoit/benoit/application/draw.rs | 9 | ||||
-rw-r--r-- | source/benoit/benoit/application/render_row.rs | 68 |
5 files changed, 61 insertions, 36 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 514d715..36ad036 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 20 + +* Optimise renderer +* Update commenting + # 1↋ * Make configuration support more precise numbers (must be parsed as strings now) @@ -1,6 +1,6 @@ [package] name = "benoit" -version = "0.23.0" +version = "0.24.0" authors = ["Gabriel Bjørnager Jensen"] edition = "2021" description = "Mandelbrot renderer." diff --git a/source/benoit/benoit/application/colour.rs b/source/benoit/benoit/application/colour.rs index db7e467..c9cf507 100644 --- a/source/benoit/benoit/application/colour.rs +++ b/source/benoit/benoit/application/colour.rs @@ -26,7 +26,6 @@ use crate::benoit::application::Application; impl Application { pub fn colour(&self, buffer: &mut [u8], data: &[u32]) { let canvas_size = self.canvas_height * self.canvas_width; - for pixel in 0x0..canvas_size { let iteration_count = data[pixel as usize]; @@ -40,15 +39,19 @@ impl Application { }) * 2.0 }; - let colour: u8 = if iteration_count != self.maximum_iteration_count { + let value: u8 = if iteration_count != self.maximum_iteration_count { (factor * 255.0).round() as u8 } else { 0x0 }; - buffer[pixel as usize * 0x3] = colour; - buffer[pixel as usize * 0x3 + 0x1] = colour; - buffer[pixel as usize * 0x3 + 0x2] = colour; + let red = value; + let green = value; + let blue = value; + + buffer[pixel as usize * 0x3] = red; + buffer[pixel as usize * 0x3 + 0x1] = green; + buffer[pixel as usize * 0x3 + 0x2] = blue; } } } diff --git a/source/benoit/benoit/application/draw.rs b/source/benoit/benoit/application/draw.rs index 1bc22c3..715b3da 100644 --- a/source/benoit/benoit/application/draw.rs +++ b/source/benoit/benoit/application/draw.rs @@ -39,9 +39,14 @@ impl Application { let y = pixel as u32 / self.canvas_width; let x = pixel as u32 - y * self.canvas_width; - let value = image[pixel as usize * 0x3]; + let colour = { + let red = image[pixel as usize * 0x3]; + let green = image[pixel as usize * 0x3 + 0x1]; + let blue = image[pixel as usize * 0x3 + 0x2]; + + Color::RGB(red, green, blue) + }; - let colour = Color::RGB(value, value, value); self.video.as_mut().unwrap().canvas.set_draw_color(colour); let rectangle = Rect::new( diff --git a/source/benoit/benoit/application/render_row.rs b/source/benoit/benoit/application/render_row.rs index f47f166..757e4d3 100644 --- a/source/benoit/benoit/application/render_row.rs +++ b/source/benoit/benoit/application/render_row.rs @@ -27,72 +27,84 @@ use crate::benoit::application::Application; extern crate rug; use rug::Float; -use std::ops::{AddAssign, DivAssign, MulAssign}; impl Application { pub fn render_row(data: &mut [u32], y: u32, canvas_width: u32, canvas_height: u32, center_real: Float, center_imaginary: Float, zoom: Float, maximum_iteration_count: u32) { - let two = Float::with_val(PRECISION, 2.0); - for x in 0x0..canvas_width { let canvas_width = Float::with_val(PRECISION, canvas_width); let canvas_height = Float::with_val(PRECISION, canvas_height); - //let ca = Float::with_val(PRECISION, (&x - &canvas_width / 2.0) / &canvas_width * 4.0 / &zoom + ¢er_real); - //let cb = Float::with_val(PRECISION, (&y - &canvas_height / 2.0) / &canvas_height * 4.0 / &zoom + ¢er_imaginary); - let x_float = Float::with_val(PRECISION, x); let y_float = Float::with_val(PRECISION, y); // Re(c) = (x-canvas_width/2)/canvas_width*4/zoom+Re(z) - let ca = { let tmp0 = Float::with_val(PRECISION, &canvas_width / 2.0); let mut ca = Float::with_val(PRECISION, &x_float - &tmp0); - ca.div_assign(&canvas_width); - ca.mul_assign(4.0); - ca.div_assign(&zoom); - ca.add_assign(¢er_real); + ca /= &canvas_width; + ca *= 4.0; + ca /= &zoom; + ca += ¢er_real; ca }; // Im(c) = (x-canvas_height/2)/canvas_height*4/zoom+Im(z) - let cb = { let tmp0 = Float::with_val(PRECISION, &canvas_height / 2.0); let mut cb = Float::with_val(PRECISION, &y_float - &tmp0); - cb.div_assign(&canvas_height); - cb.mul_assign(4.0); - cb.div_assign(&zoom); - cb.add_assign(¢er_imaginary); + cb /= &canvas_height; + cb *= 4.0; + cb /= &zoom; + cb += ¢er_imaginary; cb }; + // Formaly, the initial condition that + // + // z = 0 + // + // may be skipped as the first two iterations will + // always be + // + // z0 = 0 + // z1 = z0^2+c = 0^2+c = 0+c = c + // + // That is, the result of the second iteration will + // always be the value of (c). let mut za = Float::with_val(PRECISION, &ca); let mut zb = Float::with_val(PRECISION, &cb); let mut iteration_count: u32 = 0x0; - while iteration_count < maximum_iteration_count { + while { let square_distance = Float::with_val(PRECISION, &za * &za + &zb * &zb); - if square_distance > 4.0 { break } - + square_distance <= 4.0 && iteration_count < maximum_iteration_count + } { { - // z = z^2 + c - - // Complex square: - // a = a^2 - b^2 - // b = 2abi + // The Mandelbrot Set (M) is defined as the set of values in the complex plane where the iterating function + // + // z = z^2+c + // + // stays bounded: I.e. the absolute value of (z) stays bounded: + // + // abs(z) = sqrt(Re(z)^2+Im(z)^2) <= 2^2 = 4 let za_temporary = Float::with_val(PRECISION, &za); - za = Float::with_val(PRECISION, &za * &za - &zb * &zb); - za = Float::with_val(PRECISION, &za + &ca); + // We can calculate the square of a complex number (z) as: + // + // z^2 = (a+ib)^2 = (a+ib)(a+ib) = a^2+iab+iab-b^2 = a^2-b^2+2iab + + za = za.square(); + za -= &zb * &zb; + za += &ca; - zb = Float::with_val(PRECISION, &za_temporary * &zb); - zb = Float::with_val(PRECISION, &zb * &two + &cb); + zb *= &za_temporary; + zb *= 2.0; + zb += &cb; } iteration_count += 0x1; |